1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512125131251412515125161251712518125191252012521125221252312524125251252612527125281252912530125311253212533125341253512536125371253812539125401254112542125431254412545125461254712548125491255012551125521255312554125551255612557125581255912560125611256212563125641256512566125671256812569125701257112572125731257412575125761257712578125791258012581125821258312584125851258612587125881258912590125911259212593125941259512596125971259812599126001260112602126031260412605126061260712608126091261012611126121261312614126151261612617126181261912620126211262212623126241262512626126271262812629126301263112632126331263412635126361263712638126391264012641126421264312644126451264612647126481264912650126511265212653126541265512656126571265812659126601266112662126631266412665126661266712668126691267012671126721267312674126751267612677126781267912680126811268212683126841268512686126871268812689126901269112692126931269412695126961269712698126991270012701127021270312704127051270612707127081270912710127111271212713127141271512716127171271812719127201272112722127231272412725127261272712728127291273012731127321273312734127351273612737127381273912740127411274212743127441274512746127471274812749127501275112752127531275412755127561275712758127591276012761127621276312764127651276612767127681276912770127711277212773127741277512776127771277812779127801278112782127831278412785127861278712788127891279012791127921279312794127951279612797127981279912800128011280212803128041280512806128071280812809128101281112812128131281412815128161281712818128191282012821128221282312824128251282612827128281282912830128311283212833128341283512836128371283812839128401284112842128431284412845128461284712848128491285012851128521285312854128551285612857128581285912860128611286212863128641286512866128671286812869128701287112872128731287412875128761287712878128791288012881128821288312884128851288612887128881288912890128911289212893128941289512896128971289812899129001290112902129031290412905129061290712908129091291012911129121291312914129151291612917129181291912920129211292212923129241292512926129271292812929129301293112932129331293412935129361293712938129391294012941129421294312944129451294612947129481294912950129511295212953129541295512956129571295812959129601296112962129631296412965129661296712968129691297012971129721297312974129751297612977129781297912980129811298212983129841298512986129871298812989129901299112992129931299412995129961299712998129991300013001130021300313004130051300613007130081300913010130111301213013130141301513016130171301813019130201302113022130231302413025130261302713028130291303013031130321303313034130351303613037130381303913040130411304213043130441304513046130471304813049130501305113052130531305413055130561305713058130591306013061130621306313064130651306613067130681306913070130711307213073130741307513076130771307813079130801308113082130831308413085130861308713088130891309013091130921309313094130951309613097130981309913100131011310213103131041310513106131071310813109131101311113112131131311413115131161311713118131191312013121131221312313124131251312613127131281312913130131311313213133131341313513136131371313813139131401314113142131431314413145131461314713148131491315013151131521315313154131551315613157131581315913160131611316213163131641316513166131671316813169131701317113172131731317413175131761317713178131791318013181131821318313184131851318613187131881318913190131911319213193131941319513196131971319813199132001320113202132031320413205132061320713208132091321013211132121321313214132151321613217132181321913220132211322213223132241322513226132271322813229132301323113232132331323413235132361323713238132391324013241132421324313244132451324613247132481324913250132511325213253132541325513256132571325813259132601326113262132631326413265132661326713268132691327013271132721327313274132751327613277132781327913280132811328213283132841328513286132871328813289132901329113292132931329413295132961329713298132991330013301133021330313304133051330613307133081330913310133111331213313133141331513316133171331813319133201332113322133231332413325133261332713328133291333013331133321333313334133351333613337133381333913340133411334213343133441334513346133471334813349133501335113352133531335413355133561335713358133591336013361133621336313364133651336613367133681336913370133711337213373133741337513376133771337813379133801338113382133831338413385133861338713388133891339013391133921339313394133951339613397133981339913400134011340213403134041340513406134071340813409134101341113412134131341413415134161341713418134191342013421134221342313424134251342613427134281342913430134311343213433134341343513436134371343813439134401344113442134431344413445134461344713448134491345013451134521345313454134551345613457134581345913460134611346213463134641346513466134671346813469134701347113472134731347413475134761347713478134791348013481134821348313484134851348613487134881348913490134911349213493134941349513496134971349813499135001350113502135031350413505135061350713508135091351013511135121351313514135151351613517135181351913520135211352213523135241352513526135271352813529135301353113532135331353413535135361353713538135391354013541135421354313544135451354613547135481354913550135511355213553135541355513556135571355813559135601356113562135631356413565135661356713568135691357013571135721357313574135751357613577135781357913580135811358213583135841358513586135871358813589135901359113592135931359413595135961359713598135991360013601136021360313604136051360613607136081360913610136111361213613136141361513616136171361813619136201362113622136231362413625136261362713628136291363013631136321363313634136351363613637136381363913640136411364213643136441364513646136471364813649136501365113652136531365413655136561365713658136591366013661136621366313664136651366613667136681366913670136711367213673136741367513676136771367813679136801368113682136831368413685136861368713688136891369013691136921369313694136951369613697136981369913700137011370213703137041370513706137071370813709137101371113712137131371413715137161371713718137191372013721137221372313724137251372613727137281372913730137311373213733137341373513736137371373813739137401374113742137431374413745137461374713748137491375013751137521375313754137551375613757137581375913760137611376213763137641376513766137671376813769137701377113772137731377413775137761377713778137791378013781137821378313784137851378613787137881378913790137911379213793137941379513796137971379813799138001380113802138031380413805138061380713808138091381013811138121381313814138151381613817138181381913820138211382213823138241382513826138271382813829138301383113832138331383413835138361383713838138391384013841138421384313844138451384613847138481384913850138511385213853138541385513856138571385813859138601386113862138631386413865138661386713868138691387013871138721387313874138751387613877138781387913880138811388213883138841388513886138871388813889138901389113892138931389413895138961389713898138991390013901139021390313904139051390613907139081390913910139111391213913139141391513916139171391813919139201392113922139231392413925139261392713928139291393013931139321393313934139351393613937139381393913940139411394213943139441394513946139471394813949139501395113952139531395413955139561395713958139591396013961139621396313964139651396613967139681396913970139711397213973139741397513976139771397813979139801398113982139831398413985139861398713988139891399013991139921399313994139951399613997139981399914000140011400214003140041400514006140071400814009140101401114012140131401414015140161401714018140191402014021140221402314024140251402614027140281402914030140311403214033140341403514036140371403814039140401404114042140431404414045140461404714048140491405014051140521405314054140551405614057140581405914060140611406214063140641406514066140671406814069140701407114072140731407414075140761407714078140791408014081140821408314084140851408614087140881408914090140911409214093140941409514096140971409814099141001410114102141031410414105141061410714108141091411014111141121411314114141151411614117141181411914120141211412214123141241412514126141271412814129141301413114132141331413414135141361413714138141391414014141141421414314144141451414614147141481414914150141511415214153141541415514156141571415814159141601416114162141631416414165141661416714168141691417014171141721417314174141751417614177141781417914180141811418214183141841418514186141871418814189141901419114192141931419414195141961419714198141991420014201142021420314204142051420614207142081420914210142111421214213142141421514216142171421814219142201422114222142231422414225142261422714228142291423014231142321423314234142351423614237142381423914240142411424214243142441424514246142471424814249142501425114252142531425414255142561425714258142591426014261142621426314264142651426614267142681426914270142711427214273142741427514276142771427814279142801428114282142831428414285142861428714288142891429014291142921429314294142951429614297142981429914300143011430214303143041430514306143071430814309143101431114312143131431414315143161431714318143191432014321143221432314324143251432614327143281432914330143311433214333143341433514336143371433814339143401434114342143431434414345143461434714348143491435014351143521435314354143551435614357143581435914360143611436214363143641436514366143671436814369143701437114372143731437414375143761437714378143791438014381143821438314384143851438614387143881438914390143911439214393143941439514396143971439814399144001440114402144031440414405144061440714408144091441014411144121441314414144151441614417144181441914420144211442214423144241442514426144271442814429144301443114432144331443414435144361443714438144391444014441144421444314444144451444614447144481444914450144511445214453144541445514456144571445814459144601446114462144631446414465144661446714468144691447014471144721447314474144751447614477144781447914480144811448214483144841448514486144871448814489144901449114492144931449414495144961449714498144991450014501145021450314504145051450614507145081450914510145111451214513145141451514516145171451814519145201452114522145231452414525145261452714528145291453014531145321453314534145351453614537145381453914540145411454214543145441454514546145471454814549145501455114552145531455414555145561455714558145591456014561145621456314564145651456614567145681456914570145711457214573145741457514576145771457814579145801458114582145831458414585145861458714588145891459014591145921459314594145951459614597145981459914600146011460214603146041460514606146071460814609146101461114612146131461414615146161461714618146191462014621146221462314624146251462614627146281462914630146311463214633146341463514636146371463814639146401464114642146431464414645146461464714648146491465014651146521465314654146551465614657146581465914660146611466214663146641466514666146671466814669146701467114672146731467414675146761467714678146791468014681146821468314684146851468614687146881468914690146911469214693146941469514696146971469814699147001470114702147031470414705147061470714708147091471014711147121471314714147151471614717147181471914720147211472214723147241472514726147271472814729147301473114732147331473414735147361473714738147391474014741147421474314744147451474614747147481474914750147511475214753147541475514756147571475814759147601476114762147631476414765147661476714768147691477014771147721477314774147751477614777147781477914780147811478214783147841478514786147871478814789147901479114792147931479414795147961479714798147991480014801148021480314804148051480614807148081480914810148111481214813148141481514816148171481814819148201482114822148231482414825148261482714828148291483014831148321483314834148351483614837148381483914840148411484214843148441484514846148471484814849148501485114852148531485414855148561485714858148591486014861148621486314864148651486614867148681486914870148711487214873148741487514876148771487814879148801488114882148831488414885148861488714888148891489014891148921489314894148951489614897148981489914900149011490214903149041490514906149071490814909149101491114912149131491414915149161491714918149191492014921149221492314924149251492614927149281492914930149311493214933149341493514936149371493814939149401494114942149431494414945149461494714948149491495014951149521495314954149551495614957149581495914960149611496214963149641496514966149671496814969149701497114972149731497414975149761497714978149791498014981149821498314984149851498614987149881498914990149911499214993149941499514996149971499814999150001500115002150031500415005150061500715008150091501015011150121501315014150151501615017150181501915020150211502215023150241502515026150271502815029150301503115032150331503415035150361503715038150391504015041150421504315044150451504615047150481504915050150511505215053150541505515056150571505815059150601506115062150631506415065150661506715068150691507015071150721507315074150751507615077150781507915080150811508215083150841508515086150871508815089150901509115092150931509415095150961509715098150991510015101151021510315104151051510615107151081510915110151111511215113151141511515116151171511815119151201512115122151231512415125151261512715128151291513015131151321513315134151351513615137151381513915140151411514215143151441514515146151471514815149151501515115152151531515415155151561515715158151591516015161151621516315164151651516615167151681516915170151711517215173151741517515176151771517815179151801518115182151831518415185151861518715188151891519015191151921519315194151951519615197151981519915200152011520215203152041520515206152071520815209152101521115212152131521415215152161521715218152191522015221152221522315224152251522615227152281522915230152311523215233152341523515236152371523815239152401524115242152431524415245152461524715248152491525015251152521525315254152551525615257152581525915260152611526215263152641526515266152671526815269152701527115272152731527415275152761527715278152791528015281152821528315284152851528615287152881528915290152911529215293152941529515296152971529815299153001530115302153031530415305153061530715308153091531015311153121531315314153151531615317153181531915320153211532215323153241532515326153271532815329153301533115332153331533415335153361533715338153391534015341153421534315344153451534615347153481534915350153511535215353153541535515356153571535815359153601536115362153631536415365153661536715368153691537015371153721537315374153751537615377153781537915380153811538215383153841538515386153871538815389153901539115392153931539415395153961539715398153991540015401154021540315404154051540615407154081540915410154111541215413154141541515416154171541815419154201542115422154231542415425154261542715428154291543015431154321543315434154351543615437154381543915440154411544215443154441544515446154471544815449154501545115452154531545415455154561545715458154591546015461154621546315464154651546615467154681546915470154711547215473154741547515476154771547815479154801548115482154831548415485154861548715488154891549015491154921549315494154951549615497154981549915500155011550215503155041550515506155071550815509155101551115512155131551415515155161551715518155191552015521155221552315524155251552615527155281552915530155311553215533155341553515536155371553815539155401554115542155431554415545155461554715548155491555015551155521555315554155551555615557155581555915560155611556215563155641556515566155671556815569155701557115572155731557415575155761557715578155791558015581155821558315584155851558615587155881558915590155911559215593155941559515596155971559815599156001560115602156031560415605156061560715608156091561015611156121561315614156151561615617156181561915620156211562215623156241562515626156271562815629156301563115632156331563415635156361563715638156391564015641156421564315644156451564615647156481564915650156511565215653156541565515656156571565815659156601566115662156631566415665156661566715668156691567015671156721567315674156751567615677156781567915680156811568215683156841568515686156871568815689156901569115692156931569415695156961569715698156991570015701157021570315704157051570615707157081570915710157111571215713157141571515716157171571815719157201572115722157231572415725157261572715728157291573015731157321573315734157351573615737157381573915740157411574215743157441574515746157471574815749157501575115752157531575415755157561575715758157591576015761157621576315764157651576615767157681576915770157711577215773157741577515776157771577815779157801578115782157831578415785157861578715788157891579015791157921579315794157951579615797157981579915800158011580215803158041580515806158071580815809158101581115812158131581415815158161581715818158191582015821158221582315824158251582615827158281582915830158311583215833158341583515836158371583815839158401584115842158431584415845158461584715848158491585015851158521585315854158551585615857158581585915860158611586215863158641586515866158671586815869158701587115872158731587415875158761587715878158791588015881158821588315884158851588615887158881588915890158911589215893158941589515896158971589815899159001590115902159031590415905159061590715908159091591015911159121591315914159151591615917159181591915920159211592215923159241592515926159271592815929159301593115932159331593415935159361593715938159391594015941159421594315944159451594615947159481594915950159511595215953159541595515956159571595815959159601596115962159631596415965159661596715968159691597015971159721597315974159751597615977159781597915980159811598215983159841598515986159871598815989159901599115992159931599415995159961599715998159991600016001160021600316004160051600616007160081600916010160111601216013160141601516016160171601816019160201602116022160231602416025160261602716028160291603016031160321603316034160351603616037160381603916040160411604216043160441604516046160471604816049160501605116052160531605416055160561605716058160591606016061160621606316064160651606616067160681606916070160711607216073160741607516076160771607816079160801608116082160831608416085160861608716088160891609016091160921609316094160951609616097160981609916100161011610216103161041610516106161071610816109161101611116112161131611416115161161611716118161191612016121161221612316124161251612616127161281612916130161311613216133161341613516136161371613816139161401614116142161431614416145161461614716148161491615016151161521615316154161551615616157161581615916160161611616216163161641616516166161671616816169161701617116172161731617416175161761617716178161791618016181161821618316184161851618616187161881618916190161911619216193161941619516196161971619816199162001620116202162031620416205162061620716208162091621016211162121621316214162151621616217162181621916220162211622216223162241622516226162271622816229162301623116232162331623416235162361623716238162391624016241162421624316244162451624616247162481624916250162511625216253162541625516256162571625816259162601626116262162631626416265162661626716268162691627016271162721627316274162751627616277162781627916280162811628216283162841628516286162871628816289162901629116292162931629416295162961629716298162991630016301163021630316304163051630616307163081630916310163111631216313163141631516316163171631816319163201632116322163231632416325163261632716328163291633016331163321633316334163351633616337163381633916340163411634216343163441634516346163471634816349163501635116352163531635416355163561635716358163591636016361163621636316364163651636616367163681636916370163711637216373163741637516376163771637816379163801638116382163831638416385163861638716388163891639016391163921639316394163951639616397163981639916400164011640216403164041640516406164071640816409164101641116412164131641416415164161641716418164191642016421164221642316424164251642616427164281642916430164311643216433164341643516436164371643816439164401644116442164431644416445164461644716448164491645016451164521645316454164551645616457164581645916460164611646216463164641646516466164671646816469164701647116472164731647416475164761647716478164791648016481164821648316484164851648616487164881648916490164911649216493164941649516496164971649816499165001650116502165031650416505165061650716508165091651016511165121651316514165151651616517165181651916520165211652216523165241652516526165271652816529165301653116532165331653416535165361653716538165391654016541165421654316544165451654616547165481654916550165511655216553165541655516556165571655816559165601656116562165631656416565165661656716568165691657016571165721657316574165751657616577165781657916580165811658216583165841658516586165871658816589165901659116592165931659416595165961659716598165991660016601166021660316604166051660616607166081660916610166111661216613166141661516616166171661816619166201662116622166231662416625166261662716628166291663016631166321663316634166351663616637166381663916640166411664216643166441664516646166471664816649166501665116652166531665416655166561665716658166591666016661166621666316664166651666616667166681666916670166711667216673166741667516676166771667816679166801668116682166831668416685166861668716688166891669016691166921669316694166951669616697166981669916700167011670216703167041670516706167071670816709167101671116712167131671416715167161671716718167191672016721167221672316724167251672616727167281672916730167311673216733167341673516736167371673816739167401674116742167431674416745167461674716748167491675016751167521675316754167551675616757167581675916760167611676216763167641676516766167671676816769167701677116772167731677416775167761677716778167791678016781167821678316784167851678616787167881678916790167911679216793167941679516796167971679816799168001680116802168031680416805168061680716808168091681016811168121681316814168151681616817168181681916820168211682216823168241682516826168271682816829168301683116832168331683416835168361683716838168391684016841168421684316844168451684616847168481684916850168511685216853168541685516856168571685816859168601686116862168631686416865168661686716868168691687016871168721687316874168751687616877168781687916880168811688216883168841688516886168871688816889168901689116892168931689416895168961689716898168991690016901169021690316904169051690616907169081690916910169111691216913169141691516916169171691816919169201692116922169231692416925169261692716928169291693016931169321693316934169351693616937169381693916940169411694216943169441694516946169471694816949169501695116952169531695416955169561695716958169591696016961169621696316964169651696616967169681696916970169711697216973169741697516976169771697816979169801698116982169831698416985169861698716988169891699016991169921699316994169951699616997169981699917000170011700217003170041700517006170071700817009170101701117012170131701417015170161701717018170191702017021170221702317024170251702617027170281702917030170311703217033170341703517036170371703817039170401704117042170431704417045170461704717048170491705017051170521705317054170551705617057170581705917060170611706217063170641706517066170671706817069170701707117072170731707417075170761707717078170791708017081170821708317084170851708617087170881708917090170911709217093170941709517096170971709817099171001710117102171031710417105171061710717108171091711017111171121711317114171151711617117171181711917120171211712217123171241712517126171271712817129171301713117132171331713417135171361713717138171391714017141171421714317144171451714617147171481714917150171511715217153171541715517156171571715817159171601716117162171631716417165171661716717168171691717017171171721717317174171751717617177171781717917180171811718217183171841718517186171871718817189171901719117192171931719417195171961719717198171991720017201172021720317204172051720617207172081720917210172111721217213172141721517216172171721817219172201722117222172231722417225172261722717228172291723017231172321723317234172351723617237172381723917240172411724217243172441724517246172471724817249172501725117252172531725417255172561725717258172591726017261172621726317264172651726617267172681726917270172711727217273172741727517276172771727817279172801728117282172831728417285172861728717288172891729017291172921729317294172951729617297172981729917300173011730217303173041730517306173071730817309173101731117312173131731417315173161731717318173191732017321173221732317324173251732617327173281732917330173311733217333173341733517336173371733817339173401734117342173431734417345173461734717348173491735017351173521735317354173551735617357173581735917360173611736217363173641736517366173671736817369173701737117372173731737417375173761737717378173791738017381173821738317384173851738617387173881738917390173911739217393173941739517396173971739817399174001740117402174031740417405174061740717408174091741017411174121741317414174151741617417174181741917420174211742217423174241742517426174271742817429174301743117432174331743417435174361743717438174391744017441174421744317444174451744617447174481744917450174511745217453174541745517456174571745817459174601746117462174631746417465174661746717468174691747017471174721747317474174751747617477174781747917480174811748217483174841748517486174871748817489174901749117492174931749417495174961749717498174991750017501175021750317504175051750617507175081750917510175111751217513175141751517516175171751817519175201752117522175231752417525175261752717528175291753017531175321753317534175351753617537175381753917540175411754217543175441754517546175471754817549175501755117552175531755417555175561755717558175591756017561175621756317564175651756617567175681756917570175711757217573175741757517576175771757817579175801758117582175831758417585175861758717588175891759017591175921759317594175951759617597175981759917600176011760217603176041760517606176071760817609176101761117612176131761417615176161761717618176191762017621176221762317624176251762617627176281762917630176311763217633176341763517636176371763817639176401764117642176431764417645176461764717648176491765017651176521765317654176551765617657176581765917660176611766217663176641766517666176671766817669176701767117672176731767417675176761767717678176791768017681176821768317684176851768617687176881768917690176911769217693176941769517696176971769817699177001770117702177031770417705177061770717708177091771017711177121771317714177151771617717177181771917720177211772217723177241772517726177271772817729177301773117732177331773417735177361773717738177391774017741177421774317744177451774617747177481774917750177511775217753177541775517756177571775817759177601776117762177631776417765177661776717768177691777017771177721777317774177751777617777177781777917780177811778217783177841778517786177871778817789177901779117792177931779417795177961779717798177991780017801178021780317804178051780617807178081780917810178111781217813178141781517816178171781817819178201782117822178231782417825178261782717828178291783017831178321783317834178351783617837178381783917840178411784217843178441784517846178471784817849178501785117852178531785417855178561785717858178591786017861178621786317864178651786617867178681786917870178711787217873178741787517876178771787817879178801788117882178831788417885178861788717888178891789017891178921789317894178951789617897178981789917900179011790217903179041790517906179071790817909179101791117912179131791417915179161791717918179191792017921179221792317924179251792617927179281792917930179311793217933179341793517936179371793817939179401794117942179431794417945179461794717948179491795017951179521795317954179551795617957179581795917960179611796217963179641796517966179671796817969179701797117972179731797417975179761797717978179791798017981179821798317984179851798617987179881798917990179911799217993179941799517996179971799817999180001800118002180031800418005180061800718008180091801018011180121801318014180151801618017180181801918020180211802218023180241802518026180271802818029180301803118032180331803418035180361803718038180391804018041180421804318044180451804618047180481804918050180511805218053180541805518056180571805818059180601806118062180631806418065180661806718068180691807018071180721807318074180751807618077180781807918080180811808218083180841808518086180871808818089180901809118092180931809418095180961809718098180991810018101181021810318104181051810618107181081810918110181111811218113181141811518116181171811818119181201812118122181231812418125181261812718128181291813018131181321813318134181351813618137181381813918140181411814218143181441814518146181471814818149181501815118152181531815418155181561815718158181591816018161181621816318164181651816618167181681816918170181711817218173181741817518176181771817818179181801818118182181831818418185181861818718188181891819018191181921819318194181951819618197181981819918200182011820218203182041820518206182071820818209182101821118212182131821418215182161821718218182191822018221182221822318224182251822618227182281822918230182311823218233182341823518236182371823818239182401824118242182431824418245182461824718248182491825018251182521825318254182551825618257182581825918260182611826218263182641826518266182671826818269182701827118272182731827418275182761827718278182791828018281182821828318284182851828618287182881828918290182911829218293182941829518296182971829818299183001830118302183031830418305183061830718308183091831018311183121831318314183151831618317183181831918320183211832218323183241832518326183271832818329183301833118332183331833418335183361833718338183391834018341183421834318344183451834618347183481834918350183511835218353183541835518356183571835818359183601836118362183631836418365183661836718368183691837018371183721837318374183751837618377183781837918380183811838218383183841838518386183871838818389183901839118392183931839418395183961839718398183991840018401184021840318404184051840618407184081840918410184111841218413184141841518416184171841818419184201842118422184231842418425184261842718428184291843018431184321843318434184351843618437184381843918440184411844218443184441844518446184471844818449184501845118452184531845418455184561845718458184591846018461184621846318464184651846618467184681846918470184711847218473184741847518476184771847818479184801848118482184831848418485184861848718488184891849018491184921849318494184951849618497184981849918500185011850218503185041850518506185071850818509185101851118512185131851418515185161851718518185191852018521185221852318524185251852618527185281852918530185311853218533185341853518536185371853818539185401854118542185431854418545185461854718548185491855018551185521855318554185551855618557185581855918560185611856218563185641856518566185671856818569185701857118572185731857418575185761857718578185791858018581185821858318584185851858618587185881858918590185911859218593185941859518596185971859818599186001860118602186031860418605186061860718608186091861018611186121861318614186151861618617186181861918620186211862218623186241862518626186271862818629186301863118632186331863418635186361863718638186391864018641186421864318644186451864618647186481864918650186511865218653186541865518656186571865818659186601866118662186631866418665186661866718668186691867018671186721867318674186751867618677186781867918680186811868218683186841868518686186871868818689186901869118692186931869418695186961869718698186991870018701187021870318704187051870618707187081870918710187111871218713187141871518716187171871818719187201872118722187231872418725187261872718728187291873018731187321873318734187351873618737187381873918740187411874218743187441874518746187471874818749187501875118752187531875418755187561875718758187591876018761187621876318764187651876618767187681876918770187711877218773187741877518776187771877818779187801878118782187831878418785187861878718788187891879018791187921879318794187951879618797187981879918800188011880218803188041880518806188071880818809188101881118812188131881418815188161881718818188191882018821188221882318824188251882618827188281882918830188311883218833188341883518836188371883818839188401884118842188431884418845188461884718848188491885018851188521885318854188551885618857188581885918860188611886218863188641886518866188671886818869188701887118872188731887418875188761887718878188791888018881188821888318884188851888618887188881888918890188911889218893188941889518896188971889818899189001890118902189031890418905189061890718908189091891018911189121891318914189151891618917189181891918920189211892218923189241892518926189271892818929189301893118932189331893418935189361893718938189391894018941189421894318944189451894618947189481894918950189511895218953189541895518956189571895818959189601896118962189631896418965189661896718968189691897018971189721897318974189751897618977189781897918980189811898218983189841898518986189871898818989189901899118992189931899418995189961899718998189991900019001190021900319004190051900619007190081900919010190111901219013190141901519016190171901819019190201902119022190231902419025190261902719028190291903019031190321903319034190351903619037190381903919040190411904219043190441904519046190471904819049190501905119052190531905419055190561905719058190591906019061190621906319064190651906619067190681906919070190711907219073190741907519076190771907819079190801908119082190831908419085190861908719088190891909019091190921909319094190951909619097190981909919100191011910219103191041910519106191071910819109191101911119112191131911419115191161911719118191191912019121191221912319124191251912619127191281912919130191311913219133191341913519136191371913819139191401914119142191431914419145191461914719148191491915019151191521915319154191551915619157191581915919160191611916219163191641916519166191671916819169191701917119172191731917419175191761917719178191791918019181191821918319184191851918619187191881918919190191911919219193191941919519196191971919819199192001920119202192031920419205192061920719208192091921019211192121921319214192151921619217192181921919220192211922219223192241922519226192271922819229192301923119232192331923419235192361923719238192391924019241192421924319244192451924619247192481924919250192511925219253192541925519256192571925819259192601926119262192631926419265192661926719268192691927019271192721927319274192751927619277192781927919280192811928219283192841928519286192871928819289192901929119292192931929419295192961929719298192991930019301193021930319304193051930619307193081930919310193111931219313193141931519316193171931819319193201932119322193231932419325193261932719328193291933019331193321933319334193351933619337193381933919340193411934219343193441934519346193471934819349193501935119352193531935419355193561935719358193591936019361193621936319364193651936619367193681936919370193711937219373193741937519376193771937819379193801938119382193831938419385193861938719388193891939019391193921939319394193951939619397193981939919400194011940219403194041940519406194071940819409194101941119412194131941419415194161941719418194191942019421194221942319424194251942619427194281942919430194311943219433194341943519436194371943819439194401944119442194431944419445194461944719448194491945019451194521945319454194551945619457194581945919460194611946219463194641946519466194671946819469194701947119472194731947419475194761947719478194791948019481194821948319484194851948619487194881948919490194911949219493194941949519496194971949819499195001950119502195031950419505195061950719508195091951019511195121951319514195151951619517195181951919520195211952219523195241952519526195271952819529195301953119532195331953419535195361953719538195391954019541195421954319544195451954619547195481954919550195511955219553195541955519556195571955819559195601956119562195631956419565195661956719568195691957019571195721957319574195751957619577195781957919580195811958219583195841958519586195871958819589195901959119592195931959419595195961959719598195991960019601196021960319604196051960619607196081960919610196111961219613196141961519616196171961819619196201962119622196231962419625196261962719628196291963019631196321963319634196351963619637196381963919640196411964219643196441964519646196471964819649196501965119652196531965419655196561965719658196591966019661196621966319664196651966619667196681966919670196711967219673196741967519676196771967819679196801968119682196831968419685196861968719688196891969019691196921969319694196951969619697196981969919700197011970219703197041970519706197071970819709197101971119712197131971419715197161971719718197191972019721197221972319724197251972619727197281972919730197311973219733197341973519736197371973819739197401974119742197431974419745197461974719748197491975019751197521975319754197551975619757197581975919760197611976219763197641976519766197671976819769197701977119772197731977419775197761977719778197791978019781197821978319784197851978619787197881978919790197911979219793197941979519796197971979819799198001980119802198031980419805198061980719808198091981019811198121981319814198151981619817198181981919820198211982219823198241982519826198271982819829198301983119832198331983419835198361983719838198391984019841198421984319844198451984619847198481984919850198511985219853198541985519856198571985819859198601986119862198631986419865198661986719868198691987019871198721987319874198751987619877198781987919880198811988219883198841988519886198871988819889198901989119892198931989419895198961989719898198991990019901199021990319904199051990619907199081990919910199111991219913199141991519916199171991819919199201992119922199231992419925199261992719928199291993019931199321993319934199351993619937199381993919940199411994219943199441994519946199471994819949199501995119952199531995419955199561995719958199591996019961199621996319964199651996619967199681996919970199711997219973199741997519976199771997819979199801998119982199831998419985199861998719988199891999019991199921999319994199951999619997199981999920000200012000220003200042000520006200072000820009200102001120012200132001420015200162001720018200192002020021200222002320024200252002620027200282002920030200312003220033200342003520036200372003820039200402004120042200432004420045200462004720048200492005020051200522005320054200552005620057200582005920060200612006220063200642006520066200672006820069200702007120072200732007420075200762007720078200792008020081200822008320084200852008620087200882008920090200912009220093200942009520096200972009820099201002010120102201032010420105201062010720108201092011020111201122011320114201152011620117201182011920120201212012220123201242012520126201272012820129201302013120132201332013420135201362013720138201392014020141201422014320144201452014620147201482014920150201512015220153201542015520156201572015820159201602016120162201632016420165201662016720168201692017020171201722017320174201752017620177201782017920180201812018220183201842018520186201872018820189201902019120192201932019420195201962019720198201992020020201202022020320204202052020620207202082020920210202112021220213202142021520216202172021820219202202022120222202232022420225202262022720228202292023020231202322023320234202352023620237202382023920240202412024220243202442024520246202472024820249202502025120252202532025420255202562025720258202592026020261202622026320264202652026620267202682026920270202712027220273202742027520276202772027820279202802028120282202832028420285202862028720288202892029020291202922029320294202952029620297202982029920300203012030220303203042030520306203072030820309203102031120312203132031420315203162031720318203192032020321203222032320324203252032620327203282032920330203312033220333203342033520336203372033820339203402034120342203432034420345203462034720348203492035020351203522035320354203552035620357203582035920360203612036220363203642036520366203672036820369203702037120372203732037420375203762037720378203792038020381203822038320384203852038620387203882038920390203912039220393203942039520396203972039820399204002040120402204032040420405204062040720408204092041020411204122041320414204152041620417204182041920420204212042220423204242042520426204272042820429204302043120432204332043420435204362043720438204392044020441204422044320444204452044620447204482044920450204512045220453204542045520456204572045820459204602046120462204632046420465204662046720468204692047020471204722047320474204752047620477204782047920480204812048220483204842048520486204872048820489204902049120492204932049420495204962049720498204992050020501205022050320504205052050620507205082050920510205112051220513205142051520516205172051820519205202052120522205232052420525205262052720528205292053020531205322053320534205352053620537205382053920540205412054220543205442054520546205472054820549205502055120552205532055420555205562055720558205592056020561205622056320564205652056620567205682056920570205712057220573205742057520576205772057820579205802058120582205832058420585205862058720588205892059020591205922059320594205952059620597205982059920600206012060220603206042060520606206072060820609206102061120612206132061420615206162061720618206192062020621206222062320624206252062620627206282062920630206312063220633206342063520636206372063820639206402064120642206432064420645206462064720648206492065020651206522065320654206552065620657206582065920660206612066220663206642066520666206672066820669206702067120672206732067420675206762067720678206792068020681206822068320684206852068620687206882068920690206912069220693206942069520696206972069820699207002070120702207032070420705207062070720708207092071020711207122071320714207152071620717207182071920720207212072220723207242072520726207272072820729207302073120732207332073420735207362073720738207392074020741207422074320744207452074620747207482074920750207512075220753207542075520756207572075820759207602076120762207632076420765207662076720768207692077020771207722077320774207752077620777207782077920780207812078220783207842078520786207872078820789207902079120792207932079420795207962079720798207992080020801208022080320804208052080620807208082080920810208112081220813208142081520816208172081820819208202082120822208232082420825208262082720828208292083020831208322083320834208352083620837208382083920840208412084220843208442084520846208472084820849208502085120852208532085420855208562085720858208592086020861208622086320864208652086620867208682086920870208712087220873208742087520876208772087820879208802088120882208832088420885208862088720888208892089020891208922089320894208952089620897208982089920900209012090220903209042090520906209072090820909209102091120912209132091420915209162091720918209192092020921209222092320924209252092620927209282092920930209312093220933209342093520936209372093820939209402094120942209432094420945209462094720948209492095020951209522095320954209552095620957209582095920960209612096220963209642096520966209672096820969209702097120972209732097420975209762097720978209792098020981209822098320984209852098620987209882098920990209912099220993209942099520996209972099820999210002100121002210032100421005210062100721008210092101021011210122101321014210152101621017210182101921020210212102221023210242102521026210272102821029210302103121032210332103421035210362103721038210392104021041210422104321044210452104621047210482104921050210512105221053210542105521056210572105821059210602106121062210632106421065210662106721068210692107021071210722107321074210752107621077210782107921080210812108221083210842108521086210872108821089210902109121092210932109421095210962109721098210992110021101211022110321104211052110621107211082110921110211112111221113211142111521116211172111821119211202112121122211232112421125211262112721128211292113021131211322113321134211352113621137211382113921140211412114221143211442114521146211472114821149211502115121152211532115421155211562115721158211592116021161211622116321164211652116621167211682116921170211712117221173211742117521176211772117821179211802118121182211832118421185211862118721188211892119021191211922119321194211952119621197211982119921200212012120221203212042120521206212072120821209212102121121212212132121421215212162121721218212192122021221212222122321224212252122621227212282122921230212312123221233212342123521236212372123821239212402124121242212432124421245212462124721248212492125021251212522125321254212552125621257212582125921260212612126221263212642126521266212672126821269212702127121272212732127421275212762127721278212792128021281212822128321284212852128621287212882128921290212912129221293212942129521296212972129821299213002130121302213032130421305213062130721308213092131021311213122131321314213152131621317213182131921320213212132221323213242132521326213272132821329213302133121332213332133421335213362133721338213392134021341213422134321344213452134621347213482134921350213512135221353213542135521356213572135821359213602136121362213632136421365213662136721368213692137021371213722137321374213752137621377213782137921380213812138221383213842138521386213872138821389213902139121392213932139421395213962139721398213992140021401214022140321404214052140621407214082140921410214112141221413214142141521416214172141821419214202142121422214232142421425214262142721428214292143021431214322143321434214352143621437214382143921440214412144221443214442144521446214472144821449214502145121452214532145421455214562145721458214592146021461214622146321464214652146621467214682146921470214712147221473214742147521476214772147821479214802148121482214832148421485214862148721488214892149021491214922149321494214952149621497214982149921500215012150221503215042150521506215072150821509215102151121512215132151421515215162151721518215192152021521215222152321524215252152621527215282152921530215312153221533215342153521536215372153821539215402154121542215432154421545215462154721548215492155021551215522155321554215552155621557215582155921560215612156221563215642156521566215672156821569215702157121572215732157421575215762157721578215792158021581215822158321584215852158621587215882158921590215912159221593215942159521596215972159821599216002160121602216032160421605216062160721608216092161021611216122161321614216152161621617216182161921620216212162221623216242162521626216272162821629216302163121632216332163421635216362163721638216392164021641216422164321644216452164621647216482164921650216512165221653216542165521656216572165821659216602166121662216632166421665216662166721668216692167021671216722167321674216752167621677216782167921680216812168221683216842168521686216872168821689216902169121692216932169421695216962169721698216992170021701217022170321704217052170621707217082170921710217112171221713217142171521716217172171821719217202172121722217232172421725217262172721728217292173021731217322173321734217352173621737217382173921740217412174221743217442174521746217472174821749217502175121752217532175421755217562175721758217592176021761217622176321764217652176621767217682176921770217712177221773217742177521776217772177821779217802178121782217832178421785217862178721788217892179021791217922179321794217952179621797217982179921800218012180221803218042180521806218072180821809218102181121812218132181421815218162181721818218192182021821218222182321824218252182621827218282182921830218312183221833218342183521836218372183821839218402184121842218432184421845218462184721848218492185021851218522185321854218552185621857218582185921860218612186221863218642186521866218672186821869218702187121872218732187421875218762187721878218792188021881218822188321884218852188621887218882188921890218912189221893218942189521896218972189821899219002190121902219032190421905219062190721908219092191021911219122191321914219152191621917219182191921920219212192221923219242192521926219272192821929219302193121932219332193421935219362193721938219392194021941219422194321944219452194621947219482194921950219512195221953219542195521956219572195821959219602196121962219632196421965219662196721968219692197021971219722197321974219752197621977219782197921980219812198221983219842198521986219872198821989219902199121992219932199421995219962199721998219992200022001220022200322004220052200622007220082200922010220112201222013220142201522016220172201822019220202202122022220232202422025220262202722028220292203022031220322203322034220352203622037220382203922040220412204222043220442204522046220472204822049220502205122052220532205422055220562205722058220592206022061220622206322064220652206622067220682206922070220712207222073220742207522076220772207822079220802208122082220832208422085220862208722088220892209022091220922209322094220952209622097220982209922100221012210222103221042210522106221072210822109221102211122112221132211422115221162211722118221192212022121221222212322124221252212622127221282212922130221312213222133221342213522136221372213822139221402214122142221432214422145221462214722148221492215022151221522215322154221552215622157221582215922160221612216222163221642216522166221672216822169221702217122172221732217422175221762217722178221792218022181221822218322184221852218622187221882218922190221912219222193221942219522196221972219822199222002220122202222032220422205222062220722208222092221022211222122221322214222152221622217222182221922220222212222222223222242222522226222272222822229222302223122232222332223422235222362223722238222392224022241222422224322244222452224622247222482224922250222512225222253222542225522256222572225822259222602226122262222632226422265222662226722268222692227022271222722227322274222752227622277222782227922280222812228222283222842228522286222872228822289222902229122292222932229422295222962229722298222992230022301223022230322304223052230622307223082230922310223112231222313223142231522316223172231822319223202232122322223232232422325223262232722328223292233022331223322233322334223352233622337223382233922340223412234222343223442234522346223472234822349223502235122352223532235422355223562235722358223592236022361223622236322364223652236622367223682236922370223712237222373223742237522376223772237822379223802238122382223832238422385223862238722388223892239022391223922239322394223952239622397223982239922400224012240222403224042240522406224072240822409224102241122412224132241422415224162241722418224192242022421224222242322424224252242622427224282242922430224312243222433224342243522436224372243822439224402244122442224432244422445224462244722448224492245022451224522245322454224552245622457224582245922460224612246222463224642246522466224672246822469224702247122472224732247422475224762247722478224792248022481224822248322484224852248622487224882248922490224912249222493224942249522496224972249822499225002250122502225032250422505225062250722508225092251022511225122251322514225152251622517225182251922520225212252222523225242252522526225272252822529225302253122532225332253422535225362253722538225392254022541225422254322544225452254622547225482254922550225512255222553225542255522556225572255822559225602256122562225632256422565225662256722568225692257022571225722257322574225752257622577225782257922580225812258222583225842258522586225872258822589225902259122592225932259422595225962259722598225992260022601226022260322604226052260622607226082260922610226112261222613226142261522616226172261822619226202262122622226232262422625226262262722628226292263022631226322263322634226352263622637226382263922640226412264222643226442264522646226472264822649226502265122652226532265422655226562265722658226592266022661226622266322664226652266622667226682266922670226712267222673226742267522676226772267822679226802268122682226832268422685226862268722688226892269022691226922269322694226952269622697226982269922700227012270222703227042270522706227072270822709227102271122712227132271422715227162271722718227192272022721227222272322724227252272622727227282272922730227312273222733227342273522736227372273822739227402274122742227432274422745227462274722748227492275022751227522275322754227552275622757227582275922760227612276222763227642276522766227672276822769227702277122772227732277422775227762277722778227792278022781227822278322784227852278622787227882278922790227912279222793227942279522796227972279822799228002280122802228032280422805228062280722808228092281022811228122281322814228152281622817228182281922820228212282222823228242282522826228272282822829228302283122832228332283422835228362283722838228392284022841228422284322844228452284622847228482284922850228512285222853228542285522856228572285822859228602286122862228632286422865228662286722868228692287022871228722287322874228752287622877228782287922880228812288222883228842288522886228872288822889228902289122892228932289422895228962289722898228992290022901229022290322904229052290622907229082290922910229112291222913229142291522916229172291822919229202292122922229232292422925229262292722928229292293022931229322293322934229352293622937229382293922940229412294222943229442294522946229472294822949229502295122952229532295422955229562295722958229592296022961229622296322964229652296622967229682296922970229712297222973229742297522976229772297822979229802298122982229832298422985229862298722988229892299022991229922299322994229952299622997229982299923000230012300223003230042300523006230072300823009230102301123012230132301423015230162301723018230192302023021230222302323024230252302623027230282302923030230312303223033230342303523036230372303823039230402304123042230432304423045230462304723048230492305023051230522305323054230552305623057230582305923060230612306223063230642306523066230672306823069230702307123072230732307423075230762307723078230792308023081230822308323084230852308623087230882308923090230912309223093230942309523096230972309823099231002310123102231032310423105231062310723108231092311023111231122311323114231152311623117231182311923120231212312223123231242312523126231272312823129231302313123132231332313423135231362313723138231392314023141231422314323144231452314623147231482314923150231512315223153231542315523156231572315823159231602316123162231632316423165231662316723168231692317023171231722317323174231752317623177231782317923180231812318223183231842318523186231872318823189231902319123192231932319423195231962319723198231992320023201232022320323204232052320623207232082320923210232112321223213232142321523216232172321823219232202322123222232232322423225232262322723228232292323023231232322323323234232352323623237232382323923240232412324223243232442324523246232472324823249232502325123252232532325423255232562325723258232592326023261232622326323264232652326623267232682326923270232712327223273232742327523276232772327823279232802328123282232832328423285232862328723288232892329023291232922329323294232952329623297232982329923300233012330223303233042330523306233072330823309233102331123312233132331423315233162331723318233192332023321233222332323324233252332623327233282332923330233312333223333233342333523336233372333823339233402334123342233432334423345233462334723348233492335023351233522335323354233552335623357233582335923360233612336223363233642336523366233672336823369233702337123372233732337423375233762337723378233792338023381233822338323384233852338623387233882338923390233912339223393233942339523396233972339823399234002340123402234032340423405234062340723408234092341023411234122341323414234152341623417234182341923420234212342223423234242342523426234272342823429234302343123432234332343423435234362343723438234392344023441234422344323444234452344623447234482344923450234512345223453234542345523456234572345823459234602346123462234632346423465234662346723468234692347023471234722347323474234752347623477234782347923480234812348223483234842348523486234872348823489234902349123492234932349423495234962349723498234992350023501235022350323504235052350623507235082350923510235112351223513235142351523516235172351823519235202352123522235232352423525235262352723528235292353023531235322353323534235352353623537235382353923540235412354223543235442354523546235472354823549235502355123552235532355423555235562355723558235592356023561235622356323564235652356623567235682356923570235712357223573235742357523576235772357823579235802358123582235832358423585235862358723588235892359023591235922359323594235952359623597235982359923600236012360223603236042360523606236072360823609236102361123612236132361423615236162361723618236192362023621236222362323624236252362623627236282362923630236312363223633236342363523636236372363823639236402364123642236432364423645236462364723648236492365023651236522365323654236552365623657236582365923660236612366223663236642366523666236672366823669236702367123672236732367423675236762367723678236792368023681236822368323684236852368623687236882368923690236912369223693236942369523696236972369823699237002370123702237032370423705237062370723708237092371023711237122371323714237152371623717237182371923720237212372223723237242372523726237272372823729237302373123732237332373423735237362373723738237392374023741237422374323744237452374623747237482374923750237512375223753237542375523756237572375823759237602376123762237632376423765237662376723768237692377023771237722377323774237752377623777237782377923780237812378223783237842378523786237872378823789237902379123792237932379423795237962379723798237992380023801238022380323804238052380623807238082380923810238112381223813238142381523816238172381823819238202382123822238232382423825238262382723828238292383023831238322383323834238352383623837238382383923840238412384223843238442384523846238472384823849238502385123852238532385423855238562385723858238592386023861238622386323864238652386623867238682386923870238712387223873238742387523876238772387823879238802388123882238832388423885238862388723888238892389023891238922389323894238952389623897238982389923900239012390223903239042390523906239072390823909239102391123912239132391423915239162391723918239192392023921239222392323924239252392623927239282392923930239312393223933239342393523936239372393823939239402394123942239432394423945239462394723948239492395023951239522395323954239552395623957239582395923960239612396223963239642396523966239672396823969239702397123972239732397423975239762397723978239792398023981239822398323984239852398623987239882398923990239912399223993239942399523996239972399823999240002400124002240032400424005240062400724008240092401024011240122401324014240152401624017240182401924020240212402224023240242402524026240272402824029240302403124032240332403424035240362403724038240392404024041240422404324044240452404624047240482404924050240512405224053240542405524056240572405824059240602406124062240632406424065240662406724068240692407024071240722407324074240752407624077240782407924080240812408224083240842408524086240872408824089240902409124092240932409424095240962409724098240992410024101241022410324104241052410624107241082410924110241112411224113241142411524116241172411824119241202412124122241232412424125241262412724128241292413024131241322413324134241352413624137241382413924140241412414224143241442414524146241472414824149241502415124152241532415424155241562415724158241592416024161241622416324164241652416624167241682416924170241712417224173241742417524176241772417824179241802418124182241832418424185241862418724188241892419024191241922419324194241952419624197241982419924200242012420224203242042420524206242072420824209242102421124212242132421424215242162421724218242192422024221242222422324224242252422624227242282422924230242312423224233242342423524236242372423824239242402424124242242432424424245242462424724248242492425024251242522425324254242552425624257242582425924260242612426224263242642426524266242672426824269242702427124272242732427424275242762427724278242792428024281242822428324284242852428624287242882428924290242912429224293242942429524296242972429824299243002430124302243032430424305243062430724308243092431024311243122431324314243152431624317243182431924320243212432224323243242432524326243272432824329243302433124332243332433424335243362433724338243392434024341243422434324344243452434624347243482434924350243512435224353243542435524356243572435824359243602436124362243632436424365243662436724368243692437024371243722437324374243752437624377243782437924380243812438224383243842438524386243872438824389243902439124392243932439424395243962439724398243992440024401244022440324404244052440624407244082440924410244112441224413244142441524416244172441824419244202442124422244232442424425244262442724428244292443024431244322443324434244352443624437244382443924440244412444224443244442444524446244472444824449244502445124452244532445424455244562445724458244592446024461244622446324464244652446624467244682446924470244712447224473244742447524476244772447824479244802448124482244832448424485244862448724488244892449024491244922449324494244952449624497244982449924500245012450224503245042450524506245072450824509245102451124512245132451424515245162451724518245192452024521245222452324524245252452624527245282452924530245312453224533245342453524536245372453824539245402454124542245432454424545245462454724548245492455024551245522455324554245552455624557245582455924560245612456224563245642456524566245672456824569245702457124572245732457424575245762457724578245792458024581245822458324584245852458624587245882458924590245912459224593245942459524596245972459824599246002460124602246032460424605246062460724608246092461024611246122461324614246152461624617246182461924620246212462224623246242462524626246272462824629246302463124632246332463424635246362463724638246392464024641246422464324644246452464624647246482464924650246512465224653246542465524656246572465824659246602466124662246632466424665246662466724668246692467024671246722467324674246752467624677246782467924680246812468224683246842468524686246872468824689246902469124692246932469424695246962469724698246992470024701247022470324704247052470624707247082470924710247112471224713247142471524716247172471824719247202472124722247232472424725247262472724728247292473024731247322473324734247352473624737247382473924740247412474224743247442474524746247472474824749247502475124752247532475424755247562475724758247592476024761247622476324764247652476624767247682476924770247712477224773247742477524776247772477824779247802478124782247832478424785247862478724788247892479024791247922479324794247952479624797247982479924800248012480224803248042480524806248072480824809248102481124812248132481424815248162481724818248192482024821248222482324824248252482624827248282482924830248312483224833248342483524836248372483824839248402484124842248432484424845248462484724848248492485024851248522485324854248552485624857248582485924860248612486224863248642486524866248672486824869248702487124872248732487424875248762487724878248792488024881248822488324884248852488624887248882488924890248912489224893248942489524896248972489824899249002490124902249032490424905249062490724908249092491024911249122491324914249152491624917249182491924920249212492224923249242492524926249272492824929249302493124932249332493424935249362493724938249392494024941249422494324944249452494624947249482494924950249512495224953249542495524956249572495824959249602496124962249632496424965249662496724968249692497024971249722497324974249752497624977249782497924980249812498224983249842498524986249872498824989249902499124992249932499424995249962499724998249992500025001250022500325004250052500625007250082500925010250112501225013250142501525016250172501825019250202502125022250232502425025250262502725028250292503025031250322503325034250352503625037250382503925040250412504225043250442504525046250472504825049250502505125052250532505425055250562505725058250592506025061250622506325064250652506625067250682506925070250712507225073250742507525076250772507825079250802508125082250832508425085250862508725088250892509025091250922509325094250952509625097250982509925100251012510225103251042510525106251072510825109251102511125112251132511425115251162511725118251192512025121251222512325124251252512625127251282512925130251312513225133251342513525136251372513825139251402514125142251432514425145251462514725148251492515025151251522515325154251552515625157251582515925160251612516225163251642516525166251672516825169251702517125172251732517425175251762517725178251792518025181251822518325184251852518625187251882518925190251912519225193251942519525196251972519825199252002520125202252032520425205252062520725208252092521025211252122521325214252152521625217252182521925220252212522225223252242522525226252272522825229252302523125232252332523425235252362523725238252392524025241252422524325244252452524625247252482524925250252512525225253252542525525256252572525825259252602526125262252632526425265252662526725268252692527025271252722527325274252752527625277252782527925280252812528225283252842528525286252872528825289252902529125292252932529425295252962529725298252992530025301253022530325304253052530625307253082530925310253112531225313253142531525316253172531825319253202532125322253232532425325253262532725328253292533025331253322533325334253352533625337253382533925340253412534225343253442534525346253472534825349253502535125352253532535425355253562535725358253592536025361253622536325364253652536625367253682536925370253712537225373253742537525376253772537825379253802538125382253832538425385253862538725388253892539025391253922539325394253952539625397253982539925400254012540225403254042540525406254072540825409254102541125412254132541425415254162541725418254192542025421254222542325424254252542625427254282542925430254312543225433254342543525436254372543825439254402544125442254432544425445254462544725448254492545025451254522545325454254552545625457254582545925460254612546225463254642546525466254672546825469254702547125472254732547425475254762547725478254792548025481254822548325484254852548625487254882548925490254912549225493254942549525496254972549825499255002550125502255032550425505255062550725508255092551025511255122551325514255152551625517255182551925520255212552225523255242552525526255272552825529255302553125532255332553425535255362553725538255392554025541255422554325544255452554625547255482554925550255512555225553255542555525556255572555825559255602556125562255632556425565255662556725568255692557025571255722557325574255752557625577255782557925580255812558225583255842558525586255872558825589255902559125592255932559425595255962559725598255992560025601256022560325604256052560625607256082560925610256112561225613256142561525616256172561825619256202562125622256232562425625256262562725628256292563025631256322563325634256352563625637256382563925640256412564225643256442564525646256472564825649256502565125652256532565425655256562565725658256592566025661256622566325664256652566625667256682566925670256712567225673256742567525676256772567825679256802568125682256832568425685256862568725688256892569025691256922569325694256952569625697256982569925700257012570225703257042570525706257072570825709257102571125712257132571425715257162571725718257192572025721257222572325724257252572625727257282572925730257312573225733257342573525736257372573825739257402574125742257432574425745257462574725748257492575025751257522575325754257552575625757257582575925760257612576225763257642576525766257672576825769257702577125772257732577425775257762577725778257792578025781257822578325784257852578625787257882578925790257912579225793257942579525796257972579825799258002580125802258032580425805258062580725808258092581025811258122581325814258152581625817258182581925820258212582225823258242582525826258272582825829258302583125832258332583425835258362583725838258392584025841258422584325844258452584625847258482584925850258512585225853258542585525856258572585825859258602586125862258632586425865258662586725868258692587025871258722587325874258752587625877258782587925880258812588225883258842588525886258872588825889258902589125892258932589425895258962589725898258992590025901259022590325904259052590625907259082590925910259112591225913259142591525916259172591825919259202592125922259232592425925259262592725928259292593025931259322593325934259352593625937259382593925940259412594225943259442594525946259472594825949259502595125952259532595425955259562595725958259592596025961259622596325964259652596625967259682596925970259712597225973259742597525976259772597825979259802598125982259832598425985259862598725988259892599025991259922599325994259952599625997259982599926000260012600226003260042600526006260072600826009260102601126012260132601426015260162601726018260192602026021260222602326024260252602626027260282602926030260312603226033260342603526036260372603826039260402604126042260432604426045260462604726048260492605026051260522605326054260552605626057260582605926060260612606226063260642606526066260672606826069260702607126072260732607426075260762607726078260792608026081260822608326084260852608626087260882608926090260912609226093260942609526096260972609826099261002610126102261032610426105261062610726108261092611026111261122611326114261152611626117261182611926120261212612226123261242612526126261272612826129261302613126132261332613426135261362613726138261392614026141261422614326144261452614626147261482614926150261512615226153261542615526156261572615826159261602616126162261632616426165261662616726168261692617026171261722617326174261752617626177261782617926180261812618226183261842618526186261872618826189261902619126192261932619426195261962619726198261992620026201262022620326204262052620626207262082620926210262112621226213262142621526216262172621826219262202622126222262232622426225262262622726228262292623026231262322623326234262352623626237262382623926240262412624226243262442624526246262472624826249262502625126252262532625426255262562625726258262592626026261262622626326264262652626626267262682626926270262712627226273262742627526276262772627826279262802628126282262832628426285262862628726288262892629026291262922629326294262952629626297262982629926300263012630226303263042630526306263072630826309263102631126312263132631426315263162631726318263192632026321263222632326324263252632626327263282632926330263312633226333263342633526336263372633826339263402634126342263432634426345263462634726348263492635026351263522635326354263552635626357263582635926360263612636226363263642636526366263672636826369263702637126372263732637426375263762637726378263792638026381263822638326384263852638626387263882638926390263912639226393263942639526396263972639826399264002640126402264032640426405264062640726408264092641026411264122641326414264152641626417264182641926420264212642226423264242642526426264272642826429264302643126432264332643426435264362643726438264392644026441264422644326444264452644626447264482644926450264512645226453264542645526456264572645826459264602646126462264632646426465264662646726468264692647026471264722647326474264752647626477264782647926480264812648226483264842648526486264872648826489264902649126492264932649426495264962649726498264992650026501265022650326504265052650626507265082650926510265112651226513265142651526516265172651826519265202652126522265232652426525265262652726528265292653026531265322653326534265352653626537265382653926540265412654226543265442654526546265472654826549265502655126552265532655426555265562655726558265592656026561265622656326564265652656626567265682656926570265712657226573265742657526576265772657826579265802658126582265832658426585265862658726588265892659026591265922659326594265952659626597265982659926600266012660226603266042660526606266072660826609266102661126612266132661426615266162661726618266192662026621266222662326624266252662626627266282662926630266312663226633266342663526636266372663826639266402664126642266432664426645266462664726648266492665026651266522665326654266552665626657266582665926660266612666226663266642666526666266672666826669266702667126672266732667426675266762667726678266792668026681266822668326684266852668626687266882668926690266912669226693266942669526696266972669826699267002670126702267032670426705267062670726708267092671026711267122671326714267152671626717267182671926720267212672226723267242672526726267272672826729267302673126732267332673426735267362673726738267392674026741267422674326744267452674626747267482674926750267512675226753267542675526756267572675826759267602676126762267632676426765267662676726768267692677026771267722677326774267752677626777267782677926780267812678226783267842678526786267872678826789267902679126792267932679426795267962679726798267992680026801268022680326804268052680626807268082680926810268112681226813268142681526816268172681826819268202682126822268232682426825268262682726828268292683026831268322683326834268352683626837268382683926840268412684226843268442684526846268472684826849268502685126852268532685426855268562685726858268592686026861268622686326864268652686626867268682686926870268712687226873268742687526876268772687826879268802688126882268832688426885268862688726888268892689026891268922689326894268952689626897268982689926900269012690226903269042690526906269072690826909269102691126912269132691426915269162691726918269192692026921269222692326924269252692626927269282692926930269312693226933269342693526936269372693826939269402694126942269432694426945269462694726948269492695026951269522695326954269552695626957269582695926960269612696226963269642696526966269672696826969269702697126972269732697426975269762697726978269792698026981269822698326984269852698626987269882698926990269912699226993269942699526996269972699826999270002700127002270032700427005270062700727008270092701027011270122701327014270152701627017270182701927020270212702227023270242702527026270272702827029270302703127032270332703427035270362703727038270392704027041270422704327044270452704627047270482704927050270512705227053270542705527056270572705827059270602706127062270632706427065270662706727068270692707027071270722707327074270752707627077270782707927080270812708227083270842708527086270872708827089270902709127092270932709427095270962709727098270992710027101271022710327104271052710627107271082710927110271112711227113271142711527116271172711827119271202712127122271232712427125271262712727128271292713027131271322713327134271352713627137271382713927140271412714227143271442714527146271472714827149271502715127152271532715427155271562715727158271592716027161271622716327164271652716627167271682716927170271712717227173271742717527176271772717827179271802718127182271832718427185271862718727188271892719027191271922719327194271952719627197271982719927200272012720227203272042720527206272072720827209272102721127212272132721427215272162721727218272192722027221272222722327224272252722627227272282722927230272312723227233272342723527236272372723827239272402724127242272432724427245272462724727248272492725027251272522725327254272552725627257272582725927260272612726227263272642726527266272672726827269272702727127272272732727427275272762727727278272792728027281272822728327284272852728627287272882728927290272912729227293272942729527296272972729827299273002730127302273032730427305273062730727308273092731027311273122731327314273152731627317273182731927320273212732227323273242732527326273272732827329273302733127332273332733427335273362733727338273392734027341273422734327344273452734627347273482734927350273512735227353273542735527356273572735827359273602736127362273632736427365273662736727368273692737027371273722737327374273752737627377273782737927380273812738227383273842738527386273872738827389273902739127392273932739427395273962739727398273992740027401274022740327404274052740627407274082740927410274112741227413274142741527416274172741827419274202742127422274232742427425274262742727428274292743027431274322743327434274352743627437274382743927440274412744227443274442744527446274472744827449274502745127452274532745427455274562745727458274592746027461274622746327464274652746627467274682746927470274712747227473274742747527476274772747827479274802748127482274832748427485274862748727488274892749027491274922749327494274952749627497274982749927500275012750227503275042750527506275072750827509275102751127512275132751427515275162751727518275192752027521275222752327524275252752627527275282752927530275312753227533275342753527536275372753827539275402754127542275432754427545275462754727548275492755027551275522755327554275552755627557275582755927560275612756227563275642756527566275672756827569275702757127572275732757427575275762757727578275792758027581275822758327584275852758627587275882758927590275912759227593275942759527596275972759827599276002760127602276032760427605276062760727608276092761027611276122761327614276152761627617276182761927620276212762227623276242762527626276272762827629276302763127632276332763427635276362763727638276392764027641276422764327644276452764627647276482764927650276512765227653276542765527656276572765827659276602766127662276632766427665276662766727668276692767027671276722767327674276752767627677276782767927680276812768227683276842768527686276872768827689276902769127692276932769427695276962769727698276992770027701277022770327704277052770627707277082770927710277112771227713277142771527716277172771827719277202772127722277232772427725277262772727728277292773027731277322773327734277352773627737277382773927740277412774227743277442774527746277472774827749277502775127752277532775427755277562775727758277592776027761277622776327764277652776627767277682776927770277712777227773277742777527776277772777827779277802778127782277832778427785277862778727788277892779027791277922779327794277952779627797277982779927800278012780227803278042780527806278072780827809278102781127812278132781427815278162781727818278192782027821278222782327824278252782627827278282782927830278312783227833278342783527836278372783827839278402784127842278432784427845278462784727848278492785027851278522785327854278552785627857278582785927860278612786227863278642786527866278672786827869278702787127872278732787427875278762787727878278792788027881278822788327884278852788627887278882788927890278912789227893278942789527896278972789827899279002790127902279032790427905279062790727908279092791027911279122791327914279152791627917279182791927920279212792227923279242792527926279272792827929279302793127932279332793427935279362793727938279392794027941279422794327944279452794627947279482794927950279512795227953279542795527956279572795827959279602796127962279632796427965279662796727968279692797027971279722797327974279752797627977279782797927980279812798227983279842798527986279872798827989279902799127992279932799427995279962799727998279992800028001280022800328004280052800628007280082800928010280112801228013280142801528016280172801828019280202802128022280232802428025280262802728028280292803028031280322803328034280352803628037280382803928040280412804228043280442804528046280472804828049280502805128052280532805428055280562805728058280592806028061280622806328064280652806628067280682806928070280712807228073280742807528076280772807828079280802808128082280832808428085280862808728088280892809028091280922809328094280952809628097280982809928100281012810228103281042810528106281072810828109281102811128112281132811428115281162811728118281192812028121281222812328124281252812628127281282812928130281312813228133281342813528136281372813828139281402814128142281432814428145281462814728148281492815028151281522815328154281552815628157281582815928160281612816228163281642816528166281672816828169281702817128172281732817428175281762817728178281792818028181281822818328184281852818628187281882818928190281912819228193281942819528196281972819828199282002820128202282032820428205282062820728208282092821028211282122821328214282152821628217282182821928220282212822228223282242822528226282272822828229282302823128232282332823428235282362823728238282392824028241282422824328244282452824628247282482824928250282512825228253282542825528256282572825828259282602826128262282632826428265282662826728268282692827028271282722827328274282752827628277282782827928280282812828228283282842828528286282872828828289282902829128292282932829428295282962829728298282992830028301283022830328304283052830628307283082830928310283112831228313283142831528316283172831828319283202832128322283232832428325283262832728328283292833028331283322833328334283352833628337283382833928340283412834228343283442834528346283472834828349283502835128352283532835428355283562835728358283592836028361283622836328364283652836628367283682836928370283712837228373283742837528376283772837828379283802838128382283832838428385283862838728388283892839028391283922839328394283952839628397283982839928400284012840228403284042840528406284072840828409284102841128412284132841428415284162841728418284192842028421284222842328424284252842628427284282842928430284312843228433284342843528436284372843828439284402844128442284432844428445284462844728448284492845028451284522845328454284552845628457284582845928460284612846228463284642846528466284672846828469284702847128472284732847428475284762847728478284792848028481284822848328484284852848628487284882848928490284912849228493284942849528496284972849828499285002850128502285032850428505285062850728508285092851028511285122851328514285152851628517285182851928520285212852228523285242852528526285272852828529285302853128532285332853428535285362853728538285392854028541285422854328544285452854628547285482854928550285512855228553285542855528556285572855828559285602856128562285632856428565285662856728568285692857028571285722857328574285752857628577285782857928580285812858228583285842858528586285872858828589285902859128592285932859428595285962859728598285992860028601286022860328604286052860628607286082860928610286112861228613286142861528616286172861828619286202862128622286232862428625286262862728628286292863028631286322863328634286352863628637286382863928640286412864228643286442864528646286472864828649286502865128652286532865428655286562865728658286592866028661286622866328664286652866628667286682866928670286712867228673286742867528676286772867828679286802868128682286832868428685286862868728688286892869028691286922869328694286952869628697286982869928700287012870228703287042870528706287072870828709287102871128712287132871428715287162871728718287192872028721287222872328724287252872628727287282872928730287312873228733287342873528736287372873828739287402874128742287432874428745287462874728748287492875028751287522875328754287552875628757287582875928760287612876228763287642876528766287672876828769287702877128772287732877428775287762877728778287792878028781287822878328784287852878628787287882878928790287912879228793287942879528796287972879828799288002880128802288032880428805288062880728808288092881028811288122881328814288152881628817288182881928820288212882228823288242882528826288272882828829288302883128832288332883428835288362883728838288392884028841288422884328844288452884628847288482884928850288512885228853288542885528856288572885828859288602886128862288632886428865288662886728868288692887028871288722887328874288752887628877288782887928880288812888228883288842888528886288872888828889288902889128892288932889428895288962889728898288992890028901289022890328904289052890628907289082890928910289112891228913289142891528916289172891828919289202892128922289232892428925289262892728928289292893028931289322893328934289352893628937289382893928940289412894228943289442894528946289472894828949289502895128952289532895428955289562895728958289592896028961289622896328964289652896628967289682896928970289712897228973289742897528976289772897828979289802898128982289832898428985289862898728988289892899028991289922899328994289952899628997289982899929000290012900229003290042900529006290072900829009290102901129012290132901429015290162901729018290192902029021290222902329024290252902629027290282902929030290312903229033290342903529036290372903829039290402904129042290432904429045290462904729048290492905029051290522905329054290552905629057290582905929060290612906229063290642906529066290672906829069290702907129072290732907429075290762907729078290792908029081290822908329084290852908629087290882908929090290912909229093290942909529096290972909829099291002910129102291032910429105291062910729108291092911029111291122911329114291152911629117291182911929120291212912229123291242912529126291272912829129291302913129132291332913429135291362913729138291392914029141291422914329144291452914629147291482914929150291512915229153291542915529156291572915829159291602916129162291632916429165291662916729168291692917029171291722917329174291752917629177291782917929180291812918229183291842918529186291872918829189291902919129192291932919429195291962919729198291992920029201292022920329204292052920629207292082920929210292112921229213292142921529216292172921829219292202922129222292232922429225292262922729228292292923029231292322923329234292352923629237292382923929240292412924229243292442924529246292472924829249292502925129252292532925429255292562925729258292592926029261292622926329264292652926629267292682926929270292712927229273292742927529276292772927829279292802928129282292832928429285292862928729288292892929029291292922929329294292952929629297292982929929300293012930229303293042930529306293072930829309293102931129312293132931429315293162931729318293192932029321293222932329324293252932629327293282932929330293312933229333293342933529336293372933829339293402934129342293432934429345293462934729348293492935029351293522935329354293552935629357293582935929360293612936229363293642936529366293672936829369293702937129372293732937429375293762937729378293792938029381293822938329384293852938629387293882938929390293912939229393293942939529396293972939829399294002940129402294032940429405294062940729408294092941029411294122941329414294152941629417294182941929420294212942229423294242942529426294272942829429294302943129432294332943429435294362943729438294392944029441294422944329444294452944629447294482944929450294512945229453294542945529456294572945829459294602946129462294632946429465294662946729468294692947029471294722947329474294752947629477294782947929480294812948229483294842948529486294872948829489294902949129492294932949429495294962949729498294992950029501295022950329504295052950629507295082950929510295112951229513295142951529516295172951829519295202952129522295232952429525295262952729528295292953029531295322953329534295352953629537295382953929540295412954229543295442954529546295472954829549295502955129552295532955429555295562955729558295592956029561295622956329564295652956629567295682956929570295712957229573295742957529576295772957829579295802958129582295832958429585295862958729588295892959029591295922959329594295952959629597295982959929600296012960229603296042960529606296072960829609296102961129612296132961429615296162961729618296192962029621296222962329624296252962629627296282962929630296312963229633296342963529636296372963829639296402964129642296432964429645296462964729648296492965029651296522965329654296552965629657296582965929660296612966229663296642966529666296672966829669296702967129672296732967429675296762967729678296792968029681296822968329684296852968629687296882968929690296912969229693296942969529696296972969829699297002970129702297032970429705297062970729708297092971029711297122971329714297152971629717297182971929720297212972229723297242972529726297272972829729297302973129732297332973429735297362973729738297392974029741297422974329744297452974629747297482974929750297512975229753297542975529756297572975829759297602976129762297632976429765297662976729768297692977029771297722977329774297752977629777297782977929780297812978229783297842978529786297872978829789297902979129792297932979429795297962979729798297992980029801298022980329804298052980629807298082980929810298112981229813298142981529816298172981829819298202982129822298232982429825298262982729828298292983029831298322983329834298352983629837298382983929840298412984229843298442984529846298472984829849298502985129852298532985429855298562985729858298592986029861298622986329864298652986629867298682986929870 |
- /**
- * @license React
- * react-dom.development.js
- *
- * Copyright (c) Facebook, Inc. and its affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */
- (function (global, factory) {
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react')) :
- typeof define === 'function' && define.amd ? define(['exports', 'react'], factory) :
- (global = global || self, factory(global.ReactDOM = {}, global.React));
- }(this, (function (exports, React) {
- 'use strict';
- var ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
- var suppressWarning = false;
- function setSuppressWarning(newSuppressWarning) {
- {
- suppressWarning = newSuppressWarning;
- }
- } // In DEV, calls to console.warn and console.error get replaced
- // by calls to these methods by a Babel plugin.
- //
- // In PROD (or in packages without access to React internals),
- // they are left as they are instead.
- function warn(format) {
- {
- if (!suppressWarning) {
- for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
- args[_key - 1] = arguments[_key];
- }
- printWarning('warn', format, args);
- }
- }
- }
- function error(format) {
- {
- if (!suppressWarning) {
- for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
- args[_key2 - 1] = arguments[_key2];
- }
- printWarning('error', format, args);
- }
- }
- }
- function printWarning(level, format, args) {
- // When changing this logic, you might want to also
- // update consoleWithStackDev.www.js as well.
- {
- var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;
- var stack = ReactDebugCurrentFrame.getStackAddendum();
- if (stack !== '') {
- format += '%s';
- args = args.concat([stack]);
- } // eslint-disable-next-line react-internal/safe-string-coercion
- var argsWithFormat = args.map(function (item) {
- return String(item);
- }); // Careful: RN currently depends on this prefix
- argsWithFormat.unshift('Warning: ' + format); // We intentionally don't use spread (or .apply) directly because it
- // breaks IE9: https://github.com/facebook/react/issues/13610
- // eslint-disable-next-line react-internal/no-production-logging
- Function.prototype.apply.call(console[level], console, argsWithFormat);
- }
- }
- var FunctionComponent = 0;
- var ClassComponent = 1;
- var IndeterminateComponent = 2; // Before we know whether it is function or class
- var HostRoot = 3; // Root of a host tree. Could be nested inside another node.
- var HostPortal = 4; // A subtree. Could be an entry point to a different renderer.
- var HostComponent = 5;
- var HostText = 6;
- var Fragment = 7;
- var Mode = 8;
- var ContextConsumer = 9;
- var ContextProvider = 10;
- var ForwardRef = 11;
- var Profiler = 12;
- var SuspenseComponent = 13;
- var MemoComponent = 14;
- var SimpleMemoComponent = 15;
- var LazyComponent = 16;
- var IncompleteClassComponent = 17;
- var DehydratedFragment = 18;
- var SuspenseListComponent = 19;
- var ScopeComponent = 21;
- var OffscreenComponent = 22;
- var LegacyHiddenComponent = 23;
- var CacheComponent = 24;
- var TracingMarkerComponent = 25;
- // -----------------------------------------------------------------------------
- var enableClientRenderFallbackOnTextMismatch = true; // TODO: Need to review this code one more time before landing
- // the react-reconciler package.
- var enableNewReconciler = false; // Support legacy Primer support on internal FB www
- var enableLazyContextPropagation = false; // FB-only usage. The new API has different semantics.
- var enableLegacyHidden = false; // Enables unstable_avoidThisFallback feature in Fiber
- var enableSuspenseAvoidThisFallback = false; // Enables unstable_avoidThisFallback feature in Fizz
- // React DOM Chopping Block
- //
- // Similar to main Chopping Block but only flags related to React DOM. These are
- // grouped because we will likely batch all of them into a single major release.
- // -----------------------------------------------------------------------------
- // Disable support for comment nodes as React DOM containers. Already disabled
- // in open source, but www codebase still relies on it. Need to remove.
- var disableCommentsAsDOMContainers = true; // Disable javascript: URL strings in href for XSS protection.
- // and client rendering, mostly to allow JSX attributes to apply to the custom
- // element's object properties instead of only HTML attributes.
- // https://github.com/facebook/react/issues/11347
- var enableCustomElementPropertySupport = false; // Disables children for <textarea> elements
- var warnAboutStringRefs = false; // -----------------------------------------------------------------------------
- // Debugging and DevTools
- // -----------------------------------------------------------------------------
- // Adds user timing marks for e.g. state updates, suspense, and work loop stuff,
- // for an experimental timeline tool.
- var enableSchedulingProfiler = true; // Helps identify side effects in render-phase lifecycle hooks and setState
- var enableProfilerTimer = true; // Record durations for commit and passive effects phases.
- var enableProfilerCommitHooks = true; // Phase param passed to onRender callback differentiates between an "update" and a "cascading-update".
- var allNativeEvents = new Set();
- /**
- * Mapping from registration name to event name
- */
- var registrationNameDependencies = {};
- /**
- * Mapping from lowercase registration names to the properly cased version,
- * used to warn in the case of missing event handlers. Available
- * only in true.
- * @type {Object}
- */
- var possibleRegistrationNames = {}; // Trust the developer to only use possibleRegistrationNames in true
- function registerTwoPhaseEvent(registrationName, dependencies) {
- registerDirectEvent(registrationName, dependencies);
- registerDirectEvent(registrationName + 'Capture', dependencies);
- }
- function registerDirectEvent(registrationName, dependencies) {
- {
- if (registrationNameDependencies[registrationName]) {
- error('EventRegistry: More than one plugin attempted to publish the same ' + 'registration name, `%s`.', registrationName);
- }
- }
- registrationNameDependencies[registrationName] = dependencies;
- {
- var lowerCasedName = registrationName.toLowerCase();
- possibleRegistrationNames[lowerCasedName] = registrationName;
- if (registrationName === 'onDoubleClick') {
- possibleRegistrationNames.ondblclick = registrationName;
- }
- }
- for (var i = 0; i < dependencies.length; i++) {
- allNativeEvents.add(dependencies[i]);
- }
- }
- var canUseDOM = !!(typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined');
- var hasOwnProperty = Object.prototype.hasOwnProperty;
- /*
- * The `'' + value` pattern (used in in perf-sensitive code) throws for Symbol
- * and Temporal.* types. See https://github.com/facebook/react/pull/22064.
- *
- * The functions in this module will throw an easier-to-understand,
- * easier-to-debug exception with a clear errors message message explaining the
- * problem. (Instead of a confusing exception thrown inside the implementation
- * of the `value` object).
- */
- // $FlowFixMe only called in DEV, so void return is not possible.
- function typeName(value) {
- {
- // toStringTag is needed for namespaced types like Temporal.Instant
- var hasToStringTag = typeof Symbol === 'function' && Symbol.toStringTag;
- var type = hasToStringTag && value[Symbol.toStringTag] || value.constructor.name || 'Object';
- return type;
- }
- } // $FlowFixMe only called in DEV, so void return is not possible.
- function willCoercionThrow(value) {
- {
- try {
- testStringCoercion(value);
- return false;
- } catch (e) {
- return true;
- }
- }
- }
- function testStringCoercion(value) {
- // If you ended up here by following an exception call stack, here's what's
- // happened: you supplied an object or symbol value to React (as a prop, key,
- // DOM attribute, CSS property, string ref, etc.) and when React tried to
- // coerce it to a string using `'' + value`, an exception was thrown.
- //
- // The most common types that will cause this exception are `Symbol` instances
- // and Temporal objects like `Temporal.Instant`. But any object that has a
- // `valueOf` or `[Symbol.toPrimitive]` method that throws will also cause this
- // exception. (Library authors do this to prevent users from using built-in
- // numeric operators like `+` or comparison operators like `>=` because custom
- // methods are needed to perform accurate arithmetic or comparison.)
- //
- // To fix the problem, coerce this object or symbol value to a string before
- // passing it to React. The most reliable way is usually `String(value)`.
- //
- // To find which value is throwing, check the browser or debugger console.
- // Before this exception was thrown, there should be `console.error` output
- // that shows the type (Symbol, Temporal.PlainDate, etc.) that caused the
- // problem and how that type was used: key, atrribute, input value prop, etc.
- // In most cases, this console output also shows the component and its
- // ancestor components where the exception happened.
- //
- // eslint-disable-next-line react-internal/safe-string-coercion
- return '' + value;
- }
- function checkAttributeStringCoercion(value, attributeName) {
- {
- if (willCoercionThrow(value)) {
- error('The provided `%s` attribute is an unsupported type %s.' + ' This value must be coerced to a string before before using it here.', attributeName, typeName(value));
- return testStringCoercion(value); // throw (to help callers find troubleshooting comments)
- }
- }
- }
- function checkKeyStringCoercion(value) {
- {
- if (willCoercionThrow(value)) {
- error('The provided key is an unsupported type %s.' + ' This value must be coerced to a string before before using it here.', typeName(value));
- return testStringCoercion(value); // throw (to help callers find troubleshooting comments)
- }
- }
- }
- function checkPropStringCoercion(value, propName) {
- {
- if (willCoercionThrow(value)) {
- error('The provided `%s` prop is an unsupported type %s.' + ' This value must be coerced to a string before before using it here.', propName, typeName(value));
- return testStringCoercion(value); // throw (to help callers find troubleshooting comments)
- }
- }
- }
- function checkCSSPropertyStringCoercion(value, propName) {
- {
- if (willCoercionThrow(value)) {
- error('The provided `%s` CSS property is an unsupported type %s.' + ' This value must be coerced to a string before before using it here.', propName, typeName(value));
- return testStringCoercion(value); // throw (to help callers find troubleshooting comments)
- }
- }
- }
- function checkHtmlStringCoercion(value) {
- {
- if (willCoercionThrow(value)) {
- error('The provided HTML markup uses a value of unsupported type %s.' + ' This value must be coerced to a string before before using it here.', typeName(value));
- return testStringCoercion(value); // throw (to help callers find troubleshooting comments)
- }
- }
- }
- function checkFormFieldValueStringCoercion(value) {
- {
- if (willCoercionThrow(value)) {
- error('Form field values (value, checked, defaultValue, or defaultChecked props)' + ' must be strings, not %s.' + ' This value must be coerced to a string before before using it here.', typeName(value));
- return testStringCoercion(value); // throw (to help callers find troubleshooting comments)
- }
- }
- }
- // A reserved attribute.
- // It is handled by React separately and shouldn't be written to the DOM.
- var RESERVED = 0; // A simple string attribute.
- // Attributes that aren't in the filter are presumed to have this type.
- var STRING = 1; // A string attribute that accepts booleans in React. In HTML, these are called
- // "enumerated" attributes with "true" and "false" as possible values.
- // When true, it should be set to a "true" string.
- // When false, it should be set to a "false" string.
- var BOOLEANISH_STRING = 2; // A real boolean attribute.
- // When true, it should be present (set either to an empty string or its name).
- // When false, it should be omitted.
- var BOOLEAN = 3; // An attribute that can be used as a flag as well as with a value.
- // When true, it should be present (set either to an empty string or its name).
- // When false, it should be omitted.
- // For any other value, should be present with that value.
- var OVERLOADED_BOOLEAN = 4; // An attribute that must be numeric or parse as a numeric.
- // When falsy, it should be removed.
- var NUMERIC = 5; // An attribute that must be positive numeric or parse as a positive numeric.
- // When falsy, it should be removed.
- var POSITIVE_NUMERIC = 6;
- /* eslint-disable max-len */
- var ATTRIBUTE_NAME_START_CHAR = ":A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD";
- /* eslint-enable max-len */
- var ATTRIBUTE_NAME_CHAR = ATTRIBUTE_NAME_START_CHAR + "\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040";
- var VALID_ATTRIBUTE_NAME_REGEX = new RegExp('^[' + ATTRIBUTE_NAME_START_CHAR + '][' + ATTRIBUTE_NAME_CHAR + ']*$');
- var illegalAttributeNameCache = {};
- var validatedAttributeNameCache = {};
- function isAttributeNameSafe(attributeName) {
- if (hasOwnProperty.call(validatedAttributeNameCache, attributeName)) {
- return true;
- }
- if (hasOwnProperty.call(illegalAttributeNameCache, attributeName)) {
- return false;
- }
- if (VALID_ATTRIBUTE_NAME_REGEX.test(attributeName)) {
- validatedAttributeNameCache[attributeName] = true;
- return true;
- }
- illegalAttributeNameCache[attributeName] = true;
- {
- error('Invalid attribute name: `%s`', attributeName);
- }
- return false;
- }
- function shouldIgnoreAttribute(name, propertyInfo, isCustomComponentTag) {
- if (propertyInfo !== null) {
- return propertyInfo.type === RESERVED;
- }
- if (isCustomComponentTag) {
- return false;
- }
- if (name.length > 2 && (name[0] === 'o' || name[0] === 'O') && (name[1] === 'n' || name[1] === 'N')) {
- return true;
- }
- return false;
- }
- function shouldRemoveAttributeWithWarning(name, value, propertyInfo, isCustomComponentTag) {
- if (propertyInfo !== null && propertyInfo.type === RESERVED) {
- return false;
- }
- switch (typeof value) {
- case 'function': // $FlowIssue symbol is perfectly valid here
- case 'symbol':
- // eslint-disable-line
- return true;
- case 'boolean':
- {
- if (isCustomComponentTag) {
- return false;
- }
- if (propertyInfo !== null) {
- return !propertyInfo.acceptsBooleans;
- } else {
- var prefix = name.toLowerCase().slice(0, 5);
- return prefix !== 'data-' && prefix !== 'aria-';
- }
- }
- default:
- return false;
- }
- }
- function shouldRemoveAttribute(name, value, propertyInfo, isCustomComponentTag) {
- if (value === null || typeof value === 'undefined') {
- return true;
- }
- if (shouldRemoveAttributeWithWarning(name, value, propertyInfo, isCustomComponentTag)) {
- return true;
- }
- if (isCustomComponentTag) {
- return false;
- }
- if (propertyInfo !== null) {
- switch (propertyInfo.type) {
- case BOOLEAN:
- return !value;
- case OVERLOADED_BOOLEAN:
- return value === false;
- case NUMERIC:
- return isNaN(value);
- case POSITIVE_NUMERIC:
- return isNaN(value) || value < 1;
- }
- }
- return false;
- }
- function getPropertyInfo(name) {
- return properties.hasOwnProperty(name) ? properties[name] : null;
- }
- function PropertyInfoRecord(name, type, mustUseProperty, attributeName, attributeNamespace, sanitizeURL, removeEmptyString) {
- this.acceptsBooleans = type === BOOLEANISH_STRING || type === BOOLEAN || type === OVERLOADED_BOOLEAN;
- this.attributeName = attributeName;
- this.attributeNamespace = attributeNamespace;
- this.mustUseProperty = mustUseProperty;
- this.propertyName = name;
- this.type = type;
- this.sanitizeURL = sanitizeURL;
- this.removeEmptyString = removeEmptyString;
- } // When adding attributes to this list, be sure to also add them to
- // the `possibleStandardNames` module to ensure casing and incorrect
- // name warnings.
- var properties = {}; // These props are reserved by React. They shouldn't be written to the DOM.
- var reservedProps = ['children', 'dangerouslySetInnerHTML', // TODO: This prevents the assignment of defaultValue to regular
- // elements (not just inputs). Now that ReactDOMInput assigns to the
- // defaultValue property -- do we need this?
- 'defaultValue', 'defaultChecked', 'innerHTML', 'suppressContentEditableWarning', 'suppressHydrationWarning', 'style'];
- reservedProps.forEach(function (name) {
- properties[name] = new PropertyInfoRecord(name, RESERVED, false, // mustUseProperty
- name, // attributeName
- null, // attributeNamespace
- false, // sanitizeURL
- false);
- }); // A few React string attributes have a different name.
- // This is a mapping from React prop names to the attribute names.
- [['acceptCharset', 'accept-charset'], ['className', 'class'], ['htmlFor', 'for'], ['httpEquiv', 'http-equiv']].forEach(function (_ref) {
- var name = _ref[0],
- attributeName = _ref[1];
- properties[name] = new PropertyInfoRecord(name, STRING, false, // mustUseProperty
- attributeName, // attributeName
- null, // attributeNamespace
- false, // sanitizeURL
- false);
- }); // These are "enumerated" HTML attributes that accept "true" and "false".
- // In React, we let users pass `true` and `false` even though technically
- // these aren't boolean attributes (they are coerced to strings).
- ['contentEditable', 'draggable', 'spellCheck', 'value'].forEach(function (name) {
- properties[name] = new PropertyInfoRecord(name, BOOLEANISH_STRING, false, // mustUseProperty
- name.toLowerCase(), // attributeName
- null, // attributeNamespace
- false, // sanitizeURL
- false);
- }); // These are "enumerated" SVG attributes that accept "true" and "false".
- // In React, we let users pass `true` and `false` even though technically
- // these aren't boolean attributes (they are coerced to strings).
- // Since these are SVG attributes, their attribute names are case-sensitive.
- ['autoReverse', 'externalResourcesRequired', 'focusable', 'preserveAlpha'].forEach(function (name) {
- properties[name] = new PropertyInfoRecord(name, BOOLEANISH_STRING, false, // mustUseProperty
- name, // attributeName
- null, // attributeNamespace
- false, // sanitizeURL
- false);
- }); // These are HTML boolean attributes.
- ['allowFullScreen', 'async', // Note: there is a special case that prevents it from being written to the DOM
- // on the client side because the browsers are inconsistent. Instead we call focus().
- 'autoFocus', 'autoPlay', 'controls', 'default', 'defer', 'disabled', 'disablePictureInPicture', 'disableRemotePlayback', 'formNoValidate', 'hidden', 'loop', 'noModule', 'noValidate', 'open', 'playsInline', 'readOnly', 'required', 'reversed', 'scoped', 'seamless', // Microdata
- 'itemScope'].forEach(function (name) {
- properties[name] = new PropertyInfoRecord(name, BOOLEAN, false, // mustUseProperty
- name.toLowerCase(), // attributeName
- null, // attributeNamespace
- false, // sanitizeURL
- false);
- }); // These are the few React props that we set as DOM properties
- // rather than attributes. These are all booleans.
- ['checked', // Note: `option.selected` is not updated if `select.multiple` is
- // disabled with `removeAttribute`. We have special logic for handling this.
- 'multiple', 'muted', 'selected' // NOTE: if you add a camelCased prop to this list,
- // you'll need to set attributeName to name.toLowerCase()
- // instead in the assignment below.
- ].forEach(function (name) {
- properties[name] = new PropertyInfoRecord(name, BOOLEAN, true, // mustUseProperty
- name, // attributeName
- null, // attributeNamespace
- false, // sanitizeURL
- false);
- }); // These are HTML attributes that are "overloaded booleans": they behave like
- // booleans, but can also accept a string value.
- ['capture', 'download' // NOTE: if you add a camelCased prop to this list,
- // you'll need to set attributeName to name.toLowerCase()
- // instead in the assignment below.
- ].forEach(function (name) {
- properties[name] = new PropertyInfoRecord(name, OVERLOADED_BOOLEAN, false, // mustUseProperty
- name, // attributeName
- null, // attributeNamespace
- false, // sanitizeURL
- false);
- }); // These are HTML attributes that must be positive numbers.
- ['cols', 'rows', 'size', 'span' // NOTE: if you add a camelCased prop to this list,
- // you'll need to set attributeName to name.toLowerCase()
- // instead in the assignment below.
- ].forEach(function (name) {
- properties[name] = new PropertyInfoRecord(name, POSITIVE_NUMERIC, false, // mustUseProperty
- name, // attributeName
- null, // attributeNamespace
- false, // sanitizeURL
- false);
- }); // These are HTML attributes that must be numbers.
- ['rowSpan', 'start'].forEach(function (name) {
- properties[name] = new PropertyInfoRecord(name, NUMERIC, false, // mustUseProperty
- name.toLowerCase(), // attributeName
- null, // attributeNamespace
- false, // sanitizeURL
- false);
- });
- var CAMELIZE = /[\-\:]([a-z])/g;
- var capitalize = function (token) {
- return token[1].toUpperCase();
- }; // This is a list of all SVG attributes that need special casing, namespacing,
- // or boolean value assignment. Regular attributes that just accept strings
- // and have the same names are omitted, just like in the HTML attribute filter.
- // Some of these attributes can be hard to find. This list was created by
- // scraping the MDN documentation.
- ['accent-height', 'alignment-baseline', 'arabic-form', 'baseline-shift', 'cap-height', 'clip-path', 'clip-rule', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'dominant-baseline', 'enable-background', 'fill-opacity', 'fill-rule', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'glyph-name', 'glyph-orientation-horizontal', 'glyph-orientation-vertical', 'horiz-adv-x', 'horiz-origin-x', 'image-rendering', 'letter-spacing', 'lighting-color', 'marker-end', 'marker-mid', 'marker-start', 'overline-position', 'overline-thickness', 'paint-order', 'panose-1', 'pointer-events', 'rendering-intent', 'shape-rendering', 'stop-color', 'stop-opacity', 'strikethrough-position', 'strikethrough-thickness', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'text-anchor', 'text-decoration', 'text-rendering', 'underline-position', 'underline-thickness', 'unicode-bidi', 'unicode-range', 'units-per-em', 'v-alphabetic', 'v-hanging', 'v-ideographic', 'v-mathematical', 'vector-effect', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'word-spacing', 'writing-mode', 'xmlns:xlink', 'x-height' // NOTE: if you add a camelCased prop to this list,
- // you'll need to set attributeName to name.toLowerCase()
- // instead in the assignment below.
- ].forEach(function (attributeName) {
- var name = attributeName.replace(CAMELIZE, capitalize);
- properties[name] = new PropertyInfoRecord(name, STRING, false, // mustUseProperty
- attributeName, null, // attributeNamespace
- false, // sanitizeURL
- false);
- }); // String SVG attributes with the xlink namespace.
- ['xlink:actuate', 'xlink:arcrole', 'xlink:role', 'xlink:show', 'xlink:title', 'xlink:type' // NOTE: if you add a camelCased prop to this list,
- // you'll need to set attributeName to name.toLowerCase()
- // instead in the assignment below.
- ].forEach(function (attributeName) {
- var name = attributeName.replace(CAMELIZE, capitalize);
- properties[name] = new PropertyInfoRecord(name, STRING, false, // mustUseProperty
- attributeName, 'http://www.w3.org/1999/xlink', false, // sanitizeURL
- false);
- }); // String SVG attributes with the xml namespace.
- ['xml:base', 'xml:lang', 'xml:space' // NOTE: if you add a camelCased prop to this list,
- // you'll need to set attributeName to name.toLowerCase()
- // instead in the assignment below.
- ].forEach(function (attributeName) {
- var name = attributeName.replace(CAMELIZE, capitalize);
- properties[name] = new PropertyInfoRecord(name, STRING, false, // mustUseProperty
- attributeName, 'http://www.w3.org/XML/1998/namespace', false, // sanitizeURL
- false);
- }); // These attribute exists both in HTML and SVG.
- // The attribute name is case-sensitive in SVG so we can't just use
- // the React name like we do for attributes that exist only in HTML.
- ['tabIndex', 'crossOrigin'].forEach(function (attributeName) {
- properties[attributeName] = new PropertyInfoRecord(attributeName, STRING, false, // mustUseProperty
- attributeName.toLowerCase(), // attributeName
- null, // attributeNamespace
- false, // sanitizeURL
- false);
- }); // These attributes accept URLs. These must not allow javascript: URLS.
- // These will also need to accept Trusted Types object in the future.
- var xlinkHref = 'xlinkHref';
- properties[xlinkHref] = new PropertyInfoRecord('xlinkHref', STRING, false, // mustUseProperty
- 'xlink:href', 'http://www.w3.org/1999/xlink', true, // sanitizeURL
- false);
- ['src', 'href', 'action', 'formAction'].forEach(function (attributeName) {
- properties[attributeName] = new PropertyInfoRecord(attributeName, STRING, false, // mustUseProperty
- attributeName.toLowerCase(), // attributeName
- null, // attributeNamespace
- true, // sanitizeURL
- true);
- });
- // and any newline or tab are filtered out as if they're not part of the URL.
- // https://url.spec.whatwg.org/#url-parsing
- // Tab or newline are defined as \r\n\t:
- // https://infra.spec.whatwg.org/#ascii-tab-or-newline
- // A C0 control is a code point in the range \u0000 NULL to \u001F
- // INFORMATION SEPARATOR ONE, inclusive:
- // https://infra.spec.whatwg.org/#c0-control-or-space
- /* eslint-disable max-len */
- var isJavaScriptProtocol = /^[\u0000-\u001F ]*j[\r\n\t]*a[\r\n\t]*v[\r\n\t]*a[\r\n\t]*s[\r\n\t]*c[\r\n\t]*r[\r\n\t]*i[\r\n\t]*p[\r\n\t]*t[\r\n\t]*\:/i;
- var didWarn = false;
- function sanitizeURL(url) {
- {
- if (!didWarn && isJavaScriptProtocol.test(url)) {
- didWarn = true;
- error('A future version of React will block javascript: URLs as a security precaution. ' + 'Use event handlers instead if you can. If you need to generate unsafe HTML try ' + 'using dangerouslySetInnerHTML instead. React was passed %s.', JSON.stringify(url));
- }
- }
- }
- /**
- * Get the value for a property on a node. Only used in DEV for SSR validation.
- * The "expected" argument is used as a hint of what the expected value is.
- * Some properties have multiple equivalent values.
- */
- function getValueForProperty(node, name, expected, propertyInfo) {
- {
- if (propertyInfo.mustUseProperty) {
- var propertyName = propertyInfo.propertyName;
- return node[propertyName];
- } else {
- // This check protects multiple uses of `expected`, which is why the
- // react-internal/safe-string-coercion rule is disabled in several spots
- // below.
- {
- checkAttributeStringCoercion(expected, name);
- }
- if (propertyInfo.sanitizeURL) {
- // If we haven't fully disabled javascript: URLs, and if
- // the hydration is successful of a javascript: URL, we
- // still want to warn on the client.
- // eslint-disable-next-line react-internal/safe-string-coercion
- sanitizeURL('' + expected);
- }
- var attributeName = propertyInfo.attributeName;
- var stringValue = null;
- if (propertyInfo.type === OVERLOADED_BOOLEAN) {
- if (node.hasAttribute(attributeName)) {
- var value = node.getAttribute(attributeName);
- if (value === '') {
- return true;
- }
- if (shouldRemoveAttribute(name, expected, propertyInfo, false)) {
- return value;
- } // eslint-disable-next-line react-internal/safe-string-coercion
- if (value === '' + expected) {
- return expected;
- }
- return value;
- }
- } else if (node.hasAttribute(attributeName)) {
- if (shouldRemoveAttribute(name, expected, propertyInfo, false)) {
- // We had an attribute but shouldn't have had one, so read it
- // for the error message.
- return node.getAttribute(attributeName);
- }
- if (propertyInfo.type === BOOLEAN) {
- // If this was a boolean, it doesn't matter what the value is
- // the fact that we have it is the same as the expected.
- return expected;
- } // Even if this property uses a namespace we use getAttribute
- // because we assume its namespaced name is the same as our config.
- // To use getAttributeNS we need the local name which we don't have
- // in our config atm.
- stringValue = node.getAttribute(attributeName);
- }
- if (shouldRemoveAttribute(name, expected, propertyInfo, false)) {
- return stringValue === null ? expected : stringValue; // eslint-disable-next-line react-internal/safe-string-coercion
- } else if (stringValue === '' + expected) {
- return expected;
- } else {
- return stringValue;
- }
- }
- }
- }
- /**
- * Get the value for a attribute on a node. Only used in DEV for SSR validation.
- * The third argument is used as a hint of what the expected value is. Some
- * attributes have multiple equivalent values.
- */
- function getValueForAttribute(node, name, expected, isCustomComponentTag) {
- {
- if (!isAttributeNameSafe(name)) {
- return;
- }
- if (!node.hasAttribute(name)) {
- return expected === undefined ? undefined : null;
- }
- var value = node.getAttribute(name);
- {
- checkAttributeStringCoercion(expected, name);
- }
- if (value === '' + expected) {
- return expected;
- }
- return value;
- }
- }
- /**
- * Sets the value for a property on a node.
- *
- * @param {DOMElement} node
- * @param {string} name
- * @param {*} value
- */
- function setValueForProperty(node, name, value, isCustomComponentTag) {
- var propertyInfo = getPropertyInfo(name);
- if (shouldIgnoreAttribute(name, propertyInfo, isCustomComponentTag)) {
- return;
- }
- if (shouldRemoveAttribute(name, value, propertyInfo, isCustomComponentTag)) {
- value = null;
- }
- if (isCustomComponentTag || propertyInfo === null) {
- if (isAttributeNameSafe(name)) {
- var _attributeName = name;
- if (value === null) {
- node.removeAttribute(_attributeName);
- } else {
- {
- checkAttributeStringCoercion(value, name);
- }
- node.setAttribute(_attributeName, '' + value);
- }
- }
- return;
- }
- var mustUseProperty = propertyInfo.mustUseProperty;
- if (mustUseProperty) {
- var propertyName = propertyInfo.propertyName;
- if (value === null) {
- var type = propertyInfo.type;
- node[propertyName] = type === BOOLEAN ? false : '';
- } else {
- // Contrary to `setAttribute`, object properties are properly
- // `toString`ed by IE8/9.
- node[propertyName] = value;
- }
- return;
- } // The rest are treated as attributes with special cases.
- var attributeName = propertyInfo.attributeName,
- attributeNamespace = propertyInfo.attributeNamespace;
- if (value === null) {
- node.removeAttribute(attributeName);
- } else {
- var _type = propertyInfo.type;
- var attributeValue;
- if (_type === BOOLEAN || _type === OVERLOADED_BOOLEAN && value === true) {
- // If attribute type is boolean, we know for sure it won't be an execution sink
- // and we won't require Trusted Type here.
- attributeValue = '';
- } else {
- // `setAttribute` with objects becomes only `[object]` in IE8/9,
- // ('' + value) makes it output the correct toString()-value.
- {
- {
- checkAttributeStringCoercion(value, attributeName);
- }
- attributeValue = '' + value;
- }
- if (propertyInfo.sanitizeURL) {
- sanitizeURL(attributeValue.toString());
- }
- }
- if (attributeNamespace) {
- node.setAttributeNS(attributeNamespace, attributeName, attributeValue);
- } else {
- node.setAttribute(attributeName, attributeValue);
- }
- }
- }
- // ATTENTION
- // When adding new symbols to this file,
- // Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols'
- // The Symbol used to tag the ReactElement-like types.
- var REACT_ELEMENT_TYPE = Symbol.for('react.element');
- var REACT_PORTAL_TYPE = Symbol.for('react.portal');
- var REACT_FRAGMENT_TYPE = Symbol.for('react.fragment');
- var REACT_STRICT_MODE_TYPE = Symbol.for('react.strict_mode');
- var REACT_PROFILER_TYPE = Symbol.for('react.profiler');
- var REACT_PROVIDER_TYPE = Symbol.for('react.provider');
- var REACT_CONTEXT_TYPE = Symbol.for('react.context');
- var REACT_FORWARD_REF_TYPE = Symbol.for('react.forward_ref');
- var REACT_SUSPENSE_TYPE = Symbol.for('react.suspense');
- var REACT_SUSPENSE_LIST_TYPE = Symbol.for('react.suspense_list');
- var REACT_MEMO_TYPE = Symbol.for('react.memo');
- var REACT_LAZY_TYPE = Symbol.for('react.lazy');
- var REACT_SCOPE_TYPE = Symbol.for('react.scope');
- var REACT_DEBUG_TRACING_MODE_TYPE = Symbol.for('react.debug_trace_mode');
- var REACT_OFFSCREEN_TYPE = Symbol.for('react.offscreen');
- var REACT_LEGACY_HIDDEN_TYPE = Symbol.for('react.legacy_hidden');
- var REACT_CACHE_TYPE = Symbol.for('react.cache');
- var REACT_TRACING_MARKER_TYPE = Symbol.for('react.tracing_marker');
- var MAYBE_ITERATOR_SYMBOL = Symbol.iterator;
- var FAUX_ITERATOR_SYMBOL = '@@iterator';
- function getIteratorFn(maybeIterable) {
- if (maybeIterable === null || typeof maybeIterable !== 'object') {
- return null;
- }
- var maybeIterator = MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL];
- if (typeof maybeIterator === 'function') {
- return maybeIterator;
- }
- return null;
- }
- var assign = Object.assign;
- // Helpers to patch console.logs to avoid logging during side-effect free
- // replaying on render function. This currently only patches the object
- // lazily which won't cover if the log function was extracted eagerly.
- // We could also eagerly patch the method.
- var disabledDepth = 0;
- var prevLog;
- var prevInfo;
- var prevWarn;
- var prevError;
- var prevGroup;
- var prevGroupCollapsed;
- var prevGroupEnd;
- function disabledLog() { }
- disabledLog.__reactDisabledLog = true;
- function disableLogs() {
- {
- if (disabledDepth === 0) {
- /* eslint-disable react-internal/no-production-logging */
- prevLog = console.log;
- prevInfo = console.info;
- prevWarn = console.warn;
- prevError = console.error;
- prevGroup = console.group;
- prevGroupCollapsed = console.groupCollapsed;
- prevGroupEnd = console.groupEnd; // https://github.com/facebook/react/issues/19099
- var props = {
- configurable: true,
- enumerable: true,
- value: disabledLog,
- writable: true
- }; // $FlowFixMe Flow thinks console is immutable.
- Object.defineProperties(console, {
- info: props,
- log: props,
- warn: props,
- error: props,
- group: props,
- groupCollapsed: props,
- groupEnd: props
- });
- /* eslint-enable react-internal/no-production-logging */
- }
- disabledDepth++;
- }
- }
- function reenableLogs() {
- {
- disabledDepth--;
- if (disabledDepth === 0) {
- /* eslint-disable react-internal/no-production-logging */
- var props = {
- configurable: true,
- enumerable: true,
- writable: true
- }; // $FlowFixMe Flow thinks console is immutable.
- Object.defineProperties(console, {
- log: assign({}, props, {
- value: prevLog
- }),
- info: assign({}, props, {
- value: prevInfo
- }),
- warn: assign({}, props, {
- value: prevWarn
- }),
- error: assign({}, props, {
- value: prevError
- }),
- group: assign({}, props, {
- value: prevGroup
- }),
- groupCollapsed: assign({}, props, {
- value: prevGroupCollapsed
- }),
- groupEnd: assign({}, props, {
- value: prevGroupEnd
- })
- });
- /* eslint-enable react-internal/no-production-logging */
- }
- if (disabledDepth < 0) {
- error('disabledDepth fell below zero. ' + 'This is a bug in React. Please file an issue.');
- }
- }
- }
- var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher;
- var prefix;
- function describeBuiltInComponentFrame(name, source, ownerFn) {
- {
- if (prefix === undefined) {
- // Extract the VM specific prefix used by each line.
- try {
- throw Error();
- } catch (x) {
- var match = x.stack.trim().match(/\n( *(at )?)/);
- prefix = match && match[1] || '';
- }
- } // We use the prefix to ensure our stacks line up with native stack frames.
- return '\n' + prefix + name;
- }
- }
- var reentry = false;
- var componentFrameCache;
- {
- var PossiblyWeakMap = typeof WeakMap === 'function' ? WeakMap : Map;
- componentFrameCache = new PossiblyWeakMap();
- }
- function describeNativeComponentFrame(fn, construct) {
- // If something asked for a stack inside a fake render, it should get ignored.
- if (!fn || reentry) {
- return '';
- }
- {
- var frame = componentFrameCache.get(fn);
- if (frame !== undefined) {
- return frame;
- }
- }
- var control;
- reentry = true;
- var previousPrepareStackTrace = Error.prepareStackTrace; // $FlowFixMe It does accept undefined.
- Error.prepareStackTrace = undefined;
- var previousDispatcher;
- {
- previousDispatcher = ReactCurrentDispatcher.current; // Set the dispatcher in DEV because this might be call in the render function
- // for warnings.
- ReactCurrentDispatcher.current = null;
- disableLogs();
- }
- try {
- // This should throw.
- if (construct) {
- // Something should be setting the props in the constructor.
- var Fake = function () {
- throw Error();
- }; // $FlowFixMe
- Object.defineProperty(Fake.prototype, 'props', {
- set: function () {
- // We use a throwing setter instead of frozen or non-writable props
- // because that won't throw in a non-strict mode function.
- throw Error();
- }
- });
- if (typeof Reflect === 'object' && Reflect.construct) {
- // We construct a different control for this case to include any extra
- // frames added by the construct call.
- try {
- Reflect.construct(Fake, []);
- } catch (x) {
- control = x;
- }
- Reflect.construct(fn, [], Fake);
- } else {
- try {
- Fake.call();
- } catch (x) {
- control = x;
- }
- fn.call(Fake.prototype);
- }
- } else {
- try {
- throw Error();
- } catch (x) {
- control = x;
- }
- fn();
- }
- } catch (sample) {
- // This is inlined manually because closure doesn't do it for us.
- if (sample && control && typeof sample.stack === 'string') {
- // This extracts the first frame from the sample that isn't also in the control.
- // Skipping one frame that we assume is the frame that calls the two.
- var sampleLines = sample.stack.split('\n');
- var controlLines = control.stack.split('\n');
- var s = sampleLines.length - 1;
- var c = controlLines.length - 1;
- while (s >= 1 && c >= 0 && sampleLines[s] !== controlLines[c]) {
- // We expect at least one stack frame to be shared.
- // Typically this will be the root most one. However, stack frames may be
- // cut off due to maximum stack limits. In this case, one maybe cut off
- // earlier than the other. We assume that the sample is longer or the same
- // and there for cut off earlier. So we should find the root most frame in
- // the sample somewhere in the control.
- c--;
- }
- for (; s >= 1 && c >= 0; s--, c--) {
- // Next we find the first one that isn't the same which should be the
- // frame that called our sample function and the control.
- if (sampleLines[s] !== controlLines[c]) {
- // In V8, the first line is describing the message but other VMs don't.
- // If we're about to return the first line, and the control is also on the same
- // line, that's a pretty good indicator that our sample threw at same line as
- // the control. I.e. before we entered the sample frame. So we ignore this result.
- // This can happen if you passed a class to function component, or non-function.
- if (s !== 1 || c !== 1) {
- do {
- s--;
- c--; // We may still have similar intermediate frames from the construct call.
- // The next one that isn't the same should be our match though.
- if (c < 0 || sampleLines[s] !== controlLines[c]) {
- // V8 adds a "new" prefix for native classes. Let's remove it to make it prettier.
- var _frame = '\n' + sampleLines[s].replace(' at new ', ' at '); // If our component frame is labeled "<anonymous>"
- // but we have a user-provided "displayName"
- // splice it in to make the stack more readable.
- if (fn.displayName && _frame.includes('<anonymous>')) {
- _frame = _frame.replace('<anonymous>', fn.displayName);
- }
- {
- if (typeof fn === 'function') {
- componentFrameCache.set(fn, _frame);
- }
- } // Return the line we found.
- return _frame;
- }
- } while (s >= 1 && c >= 0);
- }
- break;
- }
- }
- }
- } finally {
- reentry = false;
- {
- ReactCurrentDispatcher.current = previousDispatcher;
- reenableLogs();
- }
- Error.prepareStackTrace = previousPrepareStackTrace;
- } // Fallback to just using the name if we couldn't make it throw.
- var name = fn ? fn.displayName || fn.name : '';
- var syntheticFrame = name ? describeBuiltInComponentFrame(name) : '';
- {
- if (typeof fn === 'function') {
- componentFrameCache.set(fn, syntheticFrame);
- }
- }
- return syntheticFrame;
- }
- function describeClassComponentFrame(ctor, source, ownerFn) {
- {
- return describeNativeComponentFrame(ctor, true);
- }
- }
- function describeFunctionComponentFrame(fn, source, ownerFn) {
- {
- return describeNativeComponentFrame(fn, false);
- }
- }
- function shouldConstruct(Component) {
- var prototype = Component.prototype;
- return !!(prototype && prototype.isReactComponent);
- }
- function describeUnknownElementTypeFrameInDEV(type, source, ownerFn) {
- if (type == null) {
- return '';
- }
- if (typeof type === 'function') {
- {
- return describeNativeComponentFrame(type, shouldConstruct(type));
- }
- }
- if (typeof type === 'string') {
- return describeBuiltInComponentFrame(type);
- }
- switch (type) {
- case REACT_SUSPENSE_TYPE:
- return describeBuiltInComponentFrame('Suspense');
- case REACT_SUSPENSE_LIST_TYPE:
- return describeBuiltInComponentFrame('SuspenseList');
- }
- if (typeof type === 'object') {
- switch (type.$$typeof) {
- case REACT_FORWARD_REF_TYPE:
- return describeFunctionComponentFrame(type.render);
- case REACT_MEMO_TYPE:
- // Memo may contain any component type so we recursively resolve it.
- return describeUnknownElementTypeFrameInDEV(type.type, source, ownerFn);
- case REACT_LAZY_TYPE:
- {
- var lazyComponent = type;
- var payload = lazyComponent._payload;
- var init = lazyComponent._init;
- try {
- // Lazy may contain any component type so we recursively resolve it.
- return describeUnknownElementTypeFrameInDEV(init(payload), source, ownerFn);
- } catch (x) { }
- }
- }
- }
- return '';
- }
- function describeFiber(fiber) {
- var owner = fiber._debugOwner ? fiber._debugOwner.type : null;
- var source = fiber._debugSource;
- switch (fiber.tag) {
- case HostComponent:
- return describeBuiltInComponentFrame(fiber.type);
- case LazyComponent:
- return describeBuiltInComponentFrame('Lazy');
- case SuspenseComponent:
- return describeBuiltInComponentFrame('Suspense');
- case SuspenseListComponent:
- return describeBuiltInComponentFrame('SuspenseList');
- case FunctionComponent:
- case IndeterminateComponent:
- case SimpleMemoComponent:
- return describeFunctionComponentFrame(fiber.type);
- case ForwardRef:
- return describeFunctionComponentFrame(fiber.type.render);
- case ClassComponent:
- return describeClassComponentFrame(fiber.type);
- default:
- return '';
- }
- }
- function getStackByFiberInDevAndProd(workInProgress) {
- try {
- var info = '';
- var node = workInProgress;
- do {
- info += describeFiber(node);
- node = node.return;
- } while (node);
- return info;
- } catch (x) {
- return '\nError generating stack: ' + x.message + '\n' + x.stack;
- }
- }
- function getWrappedName(outerType, innerType, wrapperName) {
- var displayName = outerType.displayName;
- if (displayName) {
- return displayName;
- }
- var functionName = innerType.displayName || innerType.name || '';
- return functionName !== '' ? wrapperName + "(" + functionName + ")" : wrapperName;
- } // Keep in sync with react-reconciler/getComponentNameFromFiber
- function getContextName(type) {
- return type.displayName || 'Context';
- } // Note that the reconciler package should generally prefer to use getComponentNameFromFiber() instead.
- function getComponentNameFromType(type) {
- if (type == null) {
- // Host root, text node or just invalid type.
- return null;
- }
- {
- if (typeof type.tag === 'number') {
- error('Received an unexpected object in getComponentNameFromType(). ' + 'This is likely a bug in React. Please file an issue.');
- }
- }
- if (typeof type === 'function') {
- return type.displayName || type.name || null;
- }
- if (typeof type === 'string') {
- return type;
- }
- switch (type) {
- case REACT_FRAGMENT_TYPE:
- return 'Fragment';
- case REACT_PORTAL_TYPE:
- return 'Portal';
- case REACT_PROFILER_TYPE:
- return 'Profiler';
- case REACT_STRICT_MODE_TYPE:
- return 'StrictMode';
- case REACT_SUSPENSE_TYPE:
- return 'Suspense';
- case REACT_SUSPENSE_LIST_TYPE:
- return 'SuspenseList';
- }
- if (typeof type === 'object') {
- switch (type.$$typeof) {
- case REACT_CONTEXT_TYPE:
- var context = type;
- return getContextName(context) + '.Consumer';
- case REACT_PROVIDER_TYPE:
- var provider = type;
- return getContextName(provider._context) + '.Provider';
- case REACT_FORWARD_REF_TYPE:
- return getWrappedName(type, type.render, 'ForwardRef');
- case REACT_MEMO_TYPE:
- var outerName = type.displayName || null;
- if (outerName !== null) {
- return outerName;
- }
- return getComponentNameFromType(type.type) || 'Memo';
- case REACT_LAZY_TYPE:
- {
- var lazyComponent = type;
- var payload = lazyComponent._payload;
- var init = lazyComponent._init;
- try {
- return getComponentNameFromType(init(payload));
- } catch (x) {
- return null;
- }
- }
- // eslint-disable-next-line no-fallthrough
- }
- }
- return null;
- }
- function getWrappedName$1(outerType, innerType, wrapperName) {
- var functionName = innerType.displayName || innerType.name || '';
- return outerType.displayName || (functionName !== '' ? wrapperName + "(" + functionName + ")" : wrapperName);
- } // Keep in sync with shared/getComponentNameFromType
- function getContextName$1(type) {
- return type.displayName || 'Context';
- }
- function getComponentNameFromFiber(fiber) {
- var tag = fiber.tag,
- type = fiber.type;
- switch (tag) {
- case CacheComponent:
- return 'Cache';
- case ContextConsumer:
- var context = type;
- return getContextName$1(context) + '.Consumer';
- case ContextProvider:
- var provider = type;
- return getContextName$1(provider._context) + '.Provider';
- case DehydratedFragment:
- return 'DehydratedFragment';
- case ForwardRef:
- return getWrappedName$1(type, type.render, 'ForwardRef');
- case Fragment:
- return 'Fragment';
- case HostComponent:
- // Host component type is the display name (e.g. "div", "View")
- return type;
- case HostPortal:
- return 'Portal';
- case HostRoot:
- return 'Root';
- case HostText:
- return 'Text';
- case LazyComponent:
- // Name comes from the type in this case; we don't have a tag.
- return getComponentNameFromType(type);
- case Mode:
- if (type === REACT_STRICT_MODE_TYPE) {
- // Don't be less specific than shared/getComponentNameFromType
- return 'StrictMode';
- }
- return 'Mode';
- case OffscreenComponent:
- return 'Offscreen';
- case Profiler:
- return 'Profiler';
- case ScopeComponent:
- return 'Scope';
- case SuspenseComponent:
- return 'Suspense';
- case SuspenseListComponent:
- return 'SuspenseList';
- case TracingMarkerComponent:
- return 'TracingMarker';
- // The display name for this tags come from the user-provided type:
- case ClassComponent:
- case FunctionComponent:
- case IncompleteClassComponent:
- case IndeterminateComponent:
- case MemoComponent:
- case SimpleMemoComponent:
- if (typeof type === 'function') {
- return type.displayName || type.name || null;
- }
- if (typeof type === 'string') {
- return type;
- }
- break;
- }
- return null;
- }
- var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;
- var current = null;
- var isRendering = false;
- function getCurrentFiberOwnerNameInDevOrNull() {
- {
- if (current === null) {
- return null;
- }
- var owner = current._debugOwner;
- if (owner !== null && typeof owner !== 'undefined') {
- return getComponentNameFromFiber(owner);
- }
- }
- return null;
- }
- function getCurrentFiberStackInDev() {
- {
- if (current === null) {
- return '';
- } // Safe because if current fiber exists, we are reconciling,
- // and it is guaranteed to be the work-in-progress version.
- return getStackByFiberInDevAndProd(current);
- }
- }
- function resetCurrentFiber() {
- {
- ReactDebugCurrentFrame.getCurrentStack = null;
- current = null;
- isRendering = false;
- }
- }
- function setCurrentFiber(fiber) {
- {
- ReactDebugCurrentFrame.getCurrentStack = fiber === null ? null : getCurrentFiberStackInDev;
- current = fiber;
- isRendering = false;
- }
- }
- function getCurrentFiber() {
- {
- return current;
- }
- }
- function setIsRendering(rendering) {
- {
- isRendering = rendering;
- }
- }
- // Flow does not allow string concatenation of most non-string types. To work
- // around this limitation, we use an opaque type that can only be obtained by
- // passing the value through getToStringValue first.
- function toString(value) {
- // The coercion safety check is performed in getToStringValue().
- // eslint-disable-next-line react-internal/safe-string-coercion
- return '' + value;
- }
- function getToStringValue(value) {
- switch (typeof value) {
- case 'boolean':
- case 'number':
- case 'string':
- case 'undefined':
- return value;
- case 'object':
- {
- checkFormFieldValueStringCoercion(value);
- }
- return value;
- default:
- // function, symbol are assigned as empty strings
- return '';
- }
- }
- var hasReadOnlyValue = {
- button: true,
- checkbox: true,
- image: true,
- hidden: true,
- radio: true,
- reset: true,
- submit: true
- };
- function checkControlledValueProps(tagName, props) {
- {
- if (!(hasReadOnlyValue[props.type] || props.onChange || props.onInput || props.readOnly || props.disabled || props.value == null)) {
- error('You provided a `value` prop to a form field without an ' + '`onChange` handler. This will render a read-only field. If ' + 'the field should be mutable use `defaultValue`. Otherwise, ' + 'set either `onChange` or `readOnly`.');
- }
- if (!(props.onChange || props.readOnly || props.disabled || props.checked == null)) {
- error('You provided a `checked` prop to a form field without an ' + '`onChange` handler. This will render a read-only field. If ' + 'the field should be mutable use `defaultChecked`. Otherwise, ' + 'set either `onChange` or `readOnly`.');
- }
- }
- }
- function isCheckable(elem) {
- var type = elem.type;
- var nodeName = elem.nodeName;
- return nodeName && nodeName.toLowerCase() === 'input' && (type === 'checkbox' || type === 'radio');
- }
- function getTracker(node) {
- return node._valueTracker;
- }
- function detachTracker(node) {
- node._valueTracker = null;
- }
- function getValueFromNode(node) {
- var value = '';
- if (!node) {
- return value;
- }
- if (isCheckable(node)) {
- value = node.checked ? 'true' : 'false';
- } else {
- value = node.value;
- }
- return value;
- }
- function trackValueOnNode(node) {
- var valueField = isCheckable(node) ? 'checked' : 'value';
- var descriptor = Object.getOwnPropertyDescriptor(node.constructor.prototype, valueField);
- {
- checkFormFieldValueStringCoercion(node[valueField]);
- }
- var currentValue = '' + node[valueField]; // if someone has already defined a value or Safari, then bail
- // and don't track value will cause over reporting of changes,
- // but it's better then a hard failure
- // (needed for certain tests that spyOn input values and Safari)
- if (node.hasOwnProperty(valueField) || typeof descriptor === 'undefined' || typeof descriptor.get !== 'function' || typeof descriptor.set !== 'function') {
- return;
- }
- var get = descriptor.get,
- set = descriptor.set;
- Object.defineProperty(node, valueField, {
- configurable: true,
- get: function () {
- return get.call(this);
- },
- set: function (value) {
- {
- checkFormFieldValueStringCoercion(value);
- }
- currentValue = '' + value;
- set.call(this, value);
- }
- }); // We could've passed this the first time
- // but it triggers a bug in IE11 and Edge 14/15.
- // Calling defineProperty() again should be equivalent.
- // https://github.com/facebook/react/issues/11768
- Object.defineProperty(node, valueField, {
- enumerable: descriptor.enumerable
- });
- var tracker = {
- getValue: function () {
- return currentValue;
- },
- setValue: function (value) {
- {
- checkFormFieldValueStringCoercion(value);
- }
- currentValue = '' + value;
- },
- stopTracking: function () {
- detachTracker(node);
- delete node[valueField];
- }
- };
- return tracker;
- }
- function track(node) {
- if (getTracker(node)) {
- return;
- } // TODO: Once it's just Fiber we can move this to node._wrapperState
- node._valueTracker = trackValueOnNode(node);
- }
- function updateValueIfChanged(node) {
- if (!node) {
- return false;
- }
- var tracker = getTracker(node); // if there is no tracker at this point it's unlikely
- // that trying again will succeed
- if (!tracker) {
- return true;
- }
- var lastValue = tracker.getValue();
- var nextValue = getValueFromNode(node);
- if (nextValue !== lastValue) {
- tracker.setValue(nextValue);
- return true;
- }
- return false;
- }
- function getActiveElement(doc) {
- doc = doc || (typeof document !== 'undefined' ? document : undefined);
- if (typeof doc === 'undefined') {
- return null;
- }
- try {
- return doc.activeElement || doc.body;
- } catch (e) {
- return doc.body;
- }
- }
- var didWarnValueDefaultValue = false;
- var didWarnCheckedDefaultChecked = false;
- var didWarnControlledToUncontrolled = false;
- var didWarnUncontrolledToControlled = false;
- function isControlled(props) {
- var usesChecked = props.type === 'checkbox' || props.type === 'radio';
- return usesChecked ? props.checked != null : props.value != null;
- }
- /**
- * Implements an <input> host component that allows setting these optional
- * props: `checked`, `value`, `defaultChecked`, and `defaultValue`.
- *
- * If `checked` or `value` are not supplied (or null/undefined), user actions
- * that affect the checked state or value will trigger updates to the element.
- *
- * If they are supplied (and not null/undefined), the rendered element will not
- * trigger updates to the element. Instead, the props must change in order for
- * the rendered element to be updated.
- *
- * The rendered element will be initialized as unchecked (or `defaultChecked`)
- * with an empty value (or `defaultValue`).
- *
- * See http://www.w3.org/TR/2012/WD-html5-20121025/the-input-element.html
- */
- function getHostProps(element, props) {
- var node = element;
- var checked = props.checked;
- var hostProps = assign({}, props, {
- defaultChecked: undefined,
- defaultValue: undefined,
- value: undefined,
- checked: checked != null ? checked : node._wrapperState.initialChecked
- });
- return hostProps;
- }
- function initWrapperState(element, props) {
- {
- checkControlledValueProps('input', props);
- if (props.checked !== undefined && props.defaultChecked !== undefined && !didWarnCheckedDefaultChecked) {
- error('%s contains an input of type %s with both checked and defaultChecked props. ' + 'Input elements must be either controlled or uncontrolled ' + '(specify either the checked prop, or the defaultChecked prop, but not ' + 'both). Decide between using a controlled or uncontrolled input ' + 'element and remove one of these props. More info: ' + 'https://reactjs.org/link/controlled-components', getCurrentFiberOwnerNameInDevOrNull() || 'A component', props.type);
- didWarnCheckedDefaultChecked = true;
- }
- if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValueDefaultValue) {
- error('%s contains an input of type %s with both value and defaultValue props. ' + 'Input elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled input ' + 'element and remove one of these props. More info: ' + 'https://reactjs.org/link/controlled-components', getCurrentFiberOwnerNameInDevOrNull() || 'A component', props.type);
- didWarnValueDefaultValue = true;
- }
- }
- var node = element;
- var defaultValue = props.defaultValue == null ? '' : props.defaultValue;
- node._wrapperState = {
- initialChecked: props.checked != null ? props.checked : props.defaultChecked,
- initialValue: getToStringValue(props.value != null ? props.value : defaultValue),
- controlled: isControlled(props)
- };
- }
- function updateChecked(element, props) {
- var node = element;
- var checked = props.checked;
- if (checked != null) {
- setValueForProperty(node, 'checked', checked, false);
- }
- }
- function updateWrapper(element, props) {
- var node = element;
- {
- var controlled = isControlled(props);
- if (!node._wrapperState.controlled && controlled && !didWarnUncontrolledToControlled) {
- error('A component is changing an uncontrolled input to be controlled. ' + 'This is likely caused by the value changing from undefined to ' + 'a defined value, which should not happen. ' + 'Decide between using a controlled or uncontrolled input ' + 'element for the lifetime of the component. More info: https://reactjs.org/link/controlled-components');
- didWarnUncontrolledToControlled = true;
- }
- if (node._wrapperState.controlled && !controlled && !didWarnControlledToUncontrolled) {
- error('A component is changing a controlled input to be uncontrolled. ' + 'This is likely caused by the value changing from a defined to ' + 'undefined, which should not happen. ' + 'Decide between using a controlled or uncontrolled input ' + 'element for the lifetime of the component. More info: https://reactjs.org/link/controlled-components');
- didWarnControlledToUncontrolled = true;
- }
- }
- updateChecked(element, props);
- var value = getToStringValue(props.value);
- var type = props.type;
- if (value != null) {
- if (type === 'number') {
- if (value === 0 && node.value === '' || // We explicitly want to coerce to number here if possible.
- // eslint-disable-next-line
- node.value != value) {
- node.value = toString(value);
- }
- } else if (node.value !== toString(value)) {
- node.value = toString(value);
- }
- } else if (type === 'submit' || type === 'reset') {
- // Submit/reset inputs need the attribute removed completely to avoid
- // blank-text buttons.
- node.removeAttribute('value');
- return;
- }
- {
- // When syncing the value attribute, the value comes from a cascade of
- // properties:
- // 1. The value React property
- // 2. The defaultValue React property
- // 3. Otherwise there should be no change
- if (props.hasOwnProperty('value')) {
- setDefaultValue(node, props.type, value);
- } else if (props.hasOwnProperty('defaultValue')) {
- setDefaultValue(node, props.type, getToStringValue(props.defaultValue));
- }
- }
- {
- // When syncing the checked attribute, it only changes when it needs
- // to be removed, such as transitioning from a checkbox into a text input
- if (props.checked == null && props.defaultChecked != null) {
- node.defaultChecked = !!props.defaultChecked;
- }
- }
- }
- function postMountWrapper(element, props, isHydrating) {
- var node = element; // Do not assign value if it is already set. This prevents user text input
- // from being lost during SSR hydration.
- if (props.hasOwnProperty('value') || props.hasOwnProperty('defaultValue')) {
- var type = props.type;
- var isButton = type === 'submit' || type === 'reset'; // Avoid setting value attribute on submit/reset inputs as it overrides the
- // default value provided by the browser. See: #12872
- if (isButton && (props.value === undefined || props.value === null)) {
- return;
- }
- var initialValue = toString(node._wrapperState.initialValue); // Do not assign value if it is already set. This prevents user text input
- // from being lost during SSR hydration.
- if (!isHydrating) {
- {
- // When syncing the value attribute, the value property should use
- // the wrapperState._initialValue property. This uses:
- //
- // 1. The value React property when present
- // 2. The defaultValue React property when present
- // 3. An empty string
- if (initialValue !== node.value) {
- node.value = initialValue;
- }
- }
- }
- {
- // Otherwise, the value attribute is synchronized to the property,
- // so we assign defaultValue to the same thing as the value property
- // assignment step above.
- node.defaultValue = initialValue;
- }
- } // Normally, we'd just do `node.checked = node.checked` upon initial mount, less this bug
- // this is needed to work around a chrome bug where setting defaultChecked
- // will sometimes influence the value of checked (even after detachment).
- // Reference: https://bugs.chromium.org/p/chromium/issues/detail?id=608416
- // We need to temporarily unset name to avoid disrupting radio button groups.
- var name = node.name;
- if (name !== '') {
- node.name = '';
- }
- {
- // When syncing the checked attribute, both the checked property and
- // attribute are assigned at the same time using defaultChecked. This uses:
- //
- // 1. The checked React property when present
- // 2. The defaultChecked React property when present
- // 3. Otherwise, false
- node.defaultChecked = !node.defaultChecked;
- node.defaultChecked = !!node._wrapperState.initialChecked;
- }
- if (name !== '') {
- node.name = name;
- }
- }
- function restoreControlledState(element, props) {
- var node = element;
- updateWrapper(node, props);
- updateNamedCousins(node, props);
- }
- function updateNamedCousins(rootNode, props) {
- var name = props.name;
- if (props.type === 'radio' && name != null) {
- var queryRoot = rootNode;
- while (queryRoot.parentNode) {
- queryRoot = queryRoot.parentNode;
- } // If `rootNode.form` was non-null, then we could try `form.elements`,
- // but that sometimes behaves strangely in IE8. We could also try using
- // `form.getElementsByName`, but that will only return direct children
- // and won't include inputs that use the HTML5 `form=` attribute. Since
- // the input might not even be in a form. It might not even be in the
- // document. Let's just use the local `querySelectorAll` to ensure we don't
- // miss anything.
- {
- checkAttributeStringCoercion(name, 'name');
- }
- var group = queryRoot.querySelectorAll('input[name=' + JSON.stringify('' + name) + '][type="radio"]');
- for (var i = 0; i < group.length; i++) {
- var otherNode = group[i];
- if (otherNode === rootNode || otherNode.form !== rootNode.form) {
- continue;
- } // This will throw if radio buttons rendered by different copies of React
- // and the same name are rendered into the same form (same as #1939).
- // That's probably okay; we don't support it just as we don't support
- // mixing React radio buttons with non-React ones.
- var otherProps = getFiberCurrentPropsFromNode(otherNode);
- if (!otherProps) {
- throw new Error('ReactDOMInput: Mixing React and non-React radio inputs with the ' + 'same `name` is not supported.');
- } // We need update the tracked value on the named cousin since the value
- // was changed but the input saw no event or value set
- updateValueIfChanged(otherNode); // If this is a controlled radio button group, forcing the input that
- // was previously checked to update will cause it to be come re-checked
- // as appropriate.
- updateWrapper(otherNode, otherProps);
- }
- }
- } // In Chrome, assigning defaultValue to certain input types triggers input validation.
- // For number inputs, the display value loses trailing decimal points. For email inputs,
- // Chrome raises "The specified value <x> is not a valid email address".
- //
- // Here we check to see if the defaultValue has actually changed, avoiding these problems
- // when the user is inputting text
- //
- // https://github.com/facebook/react/issues/7253
- function setDefaultValue(node, type, value) {
- if ( // Focused number inputs synchronize on blur. See ChangeEventPlugin.js
- type !== 'number' || getActiveElement(node.ownerDocument) !== node) {
- if (value == null) {
- node.defaultValue = toString(node._wrapperState.initialValue);
- } else if (node.defaultValue !== toString(value)) {
- node.defaultValue = toString(value);
- }
- }
- }
- var didWarnSelectedSetOnOption = false;
- var didWarnInvalidChild = false;
- var didWarnInvalidInnerHTML = false;
- /**
- * Implements an <option> host component that warns when `selected` is set.
- */
- function validateProps(element, props) {
- {
- // If a value is not provided, then the children must be simple.
- if (props.value == null) {
- if (typeof props.children === 'object' && props.children !== null) {
- React.Children.forEach(props.children, function (child) {
- if (child == null) {
- return;
- }
- if (typeof child === 'string' || typeof child === 'number') {
- return;
- }
- if (!didWarnInvalidChild) {
- didWarnInvalidChild = true;
- error('Cannot infer the option value of complex children. ' + 'Pass a `value` prop or use a plain string as children to <option>.');
- }
- });
- } else if (props.dangerouslySetInnerHTML != null) {
- if (!didWarnInvalidInnerHTML) {
- didWarnInvalidInnerHTML = true;
- error('Pass a `value` prop if you set dangerouslyInnerHTML so React knows ' + 'which value should be selected.');
- }
- }
- } // TODO: Remove support for `selected` in <option>.
- if (props.selected != null && !didWarnSelectedSetOnOption) {
- error('Use the `defaultValue` or `value` props on <select> instead of ' + 'setting `selected` on <option>.');
- didWarnSelectedSetOnOption = true;
- }
- }
- }
- function postMountWrapper$1(element, props) {
- // value="" should make a value attribute (#6219)
- if (props.value != null) {
- element.setAttribute('value', toString(getToStringValue(props.value)));
- }
- }
- var isArrayImpl = Array.isArray; // eslint-disable-next-line no-redeclare
- function isArray(a) {
- return isArrayImpl(a);
- }
- var didWarnValueDefaultValue$1;
- {
- didWarnValueDefaultValue$1 = false;
- }
- function getDeclarationErrorAddendum() {
- var ownerName = getCurrentFiberOwnerNameInDevOrNull();
- if (ownerName) {
- return '\n\nCheck the render method of `' + ownerName + '`.';
- }
- return '';
- }
- var valuePropNames = ['value', 'defaultValue'];
- /**
- * Validation function for `value` and `defaultValue`.
- */
- function checkSelectPropTypes(props) {
- {
- checkControlledValueProps('select', props);
- for (var i = 0; i < valuePropNames.length; i++) {
- var propName = valuePropNames[i];
- if (props[propName] == null) {
- continue;
- }
- var propNameIsArray = isArray(props[propName]);
- if (props.multiple && !propNameIsArray) {
- error('The `%s` prop supplied to <select> must be an array if ' + '`multiple` is true.%s', propName, getDeclarationErrorAddendum());
- } else if (!props.multiple && propNameIsArray) {
- error('The `%s` prop supplied to <select> must be a scalar ' + 'value if `multiple` is false.%s', propName, getDeclarationErrorAddendum());
- }
- }
- }
- }
- function updateOptions(node, multiple, propValue, setDefaultSelected) {
- var options = node.options;
- if (multiple) {
- var selectedValues = propValue;
- var selectedValue = {};
- for (var i = 0; i < selectedValues.length; i++) {
- // Prefix to avoid chaos with special keys.
- selectedValue['$' + selectedValues[i]] = true;
- }
- for (var _i = 0; _i < options.length; _i++) {
- var selected = selectedValue.hasOwnProperty('$' + options[_i].value);
- if (options[_i].selected !== selected) {
- options[_i].selected = selected;
- }
- if (selected && setDefaultSelected) {
- options[_i].defaultSelected = true;
- }
- }
- } else {
- // Do not set `select.value` as exact behavior isn't consistent across all
- // browsers for all cases.
- var _selectedValue = toString(getToStringValue(propValue));
- var defaultSelected = null;
- for (var _i2 = 0; _i2 < options.length; _i2++) {
- if (options[_i2].value === _selectedValue) {
- options[_i2].selected = true;
- if (setDefaultSelected) {
- options[_i2].defaultSelected = true;
- }
- return;
- }
- if (defaultSelected === null && !options[_i2].disabled) {
- defaultSelected = options[_i2];
- }
- }
- if (defaultSelected !== null) {
- defaultSelected.selected = true;
- }
- }
- }
- /**
- * Implements a <select> host component that allows optionally setting the
- * props `value` and `defaultValue`. If `multiple` is false, the prop must be a
- * stringable. If `multiple` is true, the prop must be an array of stringables.
- *
- * If `value` is not supplied (or null/undefined), user actions that change the
- * selected option will trigger updates to the rendered options.
- *
- * If it is supplied (and not null/undefined), the rendered options will not
- * update in response to user actions. Instead, the `value` prop must change in
- * order for the rendered options to update.
- *
- * If `defaultValue` is provided, any options with the supplied values will be
- * selected.
- */
- function getHostProps$1(element, props) {
- return assign({}, props, {
- value: undefined
- });
- }
- function initWrapperState$1(element, props) {
- var node = element;
- {
- checkSelectPropTypes(props);
- }
- node._wrapperState = {
- wasMultiple: !!props.multiple
- };
- {
- if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValueDefaultValue$1) {
- error('Select elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled select ' + 'element and remove one of these props. More info: ' + 'https://reactjs.org/link/controlled-components');
- didWarnValueDefaultValue$1 = true;
- }
- }
- }
- function postMountWrapper$2(element, props) {
- var node = element;
- node.multiple = !!props.multiple;
- var value = props.value;
- if (value != null) {
- updateOptions(node, !!props.multiple, value, false);
- } else if (props.defaultValue != null) {
- updateOptions(node, !!props.multiple, props.defaultValue, true);
- }
- }
- function postUpdateWrapper(element, props) {
- var node = element;
- var wasMultiple = node._wrapperState.wasMultiple;
- node._wrapperState.wasMultiple = !!props.multiple;
- var value = props.value;
- if (value != null) {
- updateOptions(node, !!props.multiple, value, false);
- } else if (wasMultiple !== !!props.multiple) {
- // For simplicity, reapply `defaultValue` if `multiple` is toggled.
- if (props.defaultValue != null) {
- updateOptions(node, !!props.multiple, props.defaultValue, true);
- } else {
- // Revert the select back to its default unselected state.
- updateOptions(node, !!props.multiple, props.multiple ? [] : '', false);
- }
- }
- }
- function restoreControlledState$1(element, props) {
- var node = element;
- var value = props.value;
- if (value != null) {
- updateOptions(node, !!props.multiple, value, false);
- }
- }
- var didWarnValDefaultVal = false;
- /**
- * Implements a <textarea> host component that allows setting `value`, and
- * `defaultValue`. This differs from the traditional DOM API because value is
- * usually set as PCDATA children.
- *
- * If `value` is not supplied (or null/undefined), user actions that affect the
- * value will trigger updates to the element.
- *
- * If `value` is supplied (and not null/undefined), the rendered element will
- * not trigger updates to the element. Instead, the `value` prop must change in
- * order for the rendered element to be updated.
- *
- * The rendered element will be initialized with an empty value, the prop
- * `defaultValue` if specified, or the children content (deprecated).
- */
- function getHostProps$2(element, props) {
- var node = element;
- if (props.dangerouslySetInnerHTML != null) {
- throw new Error('`dangerouslySetInnerHTML` does not make sense on <textarea>.');
- } // Always set children to the same thing. In IE9, the selection range will
- // get reset if `textContent` is mutated. We could add a check in setTextContent
- // to only set the value if/when the value differs from the node value (which would
- // completely solve this IE9 bug), but Sebastian+Sophie seemed to like this
- // solution. The value can be a boolean or object so that's why it's forced
- // to be a string.
- var hostProps = assign({}, props, {
- value: undefined,
- defaultValue: undefined,
- children: toString(node._wrapperState.initialValue)
- });
- return hostProps;
- }
- function initWrapperState$2(element, props) {
- var node = element;
- {
- checkControlledValueProps('textarea', props);
- if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValDefaultVal) {
- error('%s contains a textarea with both value and defaultValue props. ' + 'Textarea elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled textarea ' + 'and remove one of these props. More info: ' + 'https://reactjs.org/link/controlled-components', getCurrentFiberOwnerNameInDevOrNull() || 'A component');
- didWarnValDefaultVal = true;
- }
- }
- var initialValue = props.value; // Only bother fetching default value if we're going to use it
- if (initialValue == null) {
- var children = props.children,
- defaultValue = props.defaultValue;
- if (children != null) {
- {
- error('Use the `defaultValue` or `value` props instead of setting ' + 'children on <textarea>.');
- }
- {
- if (defaultValue != null) {
- throw new Error('If you supply `defaultValue` on a <textarea>, do not pass children.');
- }
- if (isArray(children)) {
- if (children.length > 1) {
- throw new Error('<textarea> can only have at most one child.');
- }
- children = children[0];
- }
- defaultValue = children;
- }
- }
- if (defaultValue == null) {
- defaultValue = '';
- }
- initialValue = defaultValue;
- }
- node._wrapperState = {
- initialValue: getToStringValue(initialValue)
- };
- }
- function updateWrapper$1(element, props) {
- var node = element;
- var value = getToStringValue(props.value);
- var defaultValue = getToStringValue(props.defaultValue);
- if (value != null) {
- // Cast `value` to a string to ensure the value is set correctly. While
- // browsers typically do this as necessary, jsdom doesn't.
- var newValue = toString(value); // To avoid side effects (such as losing text selection), only set value if changed
- if (newValue !== node.value) {
- node.value = newValue;
- }
- if (props.defaultValue == null && node.defaultValue !== newValue) {
- node.defaultValue = newValue;
- }
- }
- if (defaultValue != null) {
- node.defaultValue = toString(defaultValue);
- }
- }
- function postMountWrapper$3(element, props) {
- var node = element; // This is in postMount because we need access to the DOM node, which is not
- // available until after the component has mounted.
- var textContent = node.textContent; // Only set node.value if textContent is equal to the expected
- // initial value. In IE10/IE11 there is a bug where the placeholder attribute
- // will populate textContent as well.
- // https://developer.microsoft.com/microsoft-edge/platform/issues/101525/
- if (textContent === node._wrapperState.initialValue) {
- if (textContent !== '' && textContent !== null) {
- node.value = textContent;
- }
- }
- }
- function restoreControlledState$2(element, props) {
- // DOM component is still mounted; update
- updateWrapper$1(element, props);
- }
- var HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
- var MATH_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';
- var SVG_NAMESPACE = 'http://www.w3.org/2000/svg'; // Assumes there is no parent namespace.
- function getIntrinsicNamespace(type) {
- switch (type) {
- case 'svg':
- return SVG_NAMESPACE;
- case 'math':
- return MATH_NAMESPACE;
- default:
- return HTML_NAMESPACE;
- }
- }
- function getChildNamespace(parentNamespace, type) {
- if (parentNamespace == null || parentNamespace === HTML_NAMESPACE) {
- // No (or default) parent namespace: potential entry point.
- return getIntrinsicNamespace(type);
- }
- if (parentNamespace === SVG_NAMESPACE && type === 'foreignObject') {
- // We're leaving SVG.
- return HTML_NAMESPACE;
- } // By default, pass namespace below.
- return parentNamespace;
- }
- /* globals MSApp */
- /**
- * Create a function which has 'unsafe' privileges (required by windows8 apps)
- */
- var createMicrosoftUnsafeLocalFunction = function (func) {
- if (typeof MSApp !== 'undefined' && MSApp.execUnsafeLocalFunction) {
- return function (arg0, arg1, arg2, arg3) {
- MSApp.execUnsafeLocalFunction(function () {
- return func(arg0, arg1, arg2, arg3);
- });
- };
- } else {
- return func;
- }
- };
- var reusableSVGContainer;
- /**
- * Set the innerHTML property of a node
- *
- * @param {DOMElement} node
- * @param {string} html
- * @internal
- */
- var setInnerHTML = createMicrosoftUnsafeLocalFunction(function (node, html) {
- if (node.namespaceURI === SVG_NAMESPACE) {
- if (!('innerHTML' in node)) {
- // IE does not have innerHTML for SVG nodes, so instead we inject the
- // new markup in a temp node and then move the child nodes across into
- // the target node
- reusableSVGContainer = reusableSVGContainer || document.createElement('div');
- reusableSVGContainer.innerHTML = '<svg>' + html.valueOf().toString() + '</svg>';
- var svgNode = reusableSVGContainer.firstChild;
- while (node.firstChild) {
- node.removeChild(node.firstChild);
- }
- while (svgNode.firstChild) {
- node.appendChild(svgNode.firstChild);
- }
- return;
- }
- }
- node.innerHTML = html;
- });
- /**
- * HTML nodeType values that represent the type of the node
- */
- var ELEMENT_NODE = 1;
- var TEXT_NODE = 3;
- var COMMENT_NODE = 8;
- var DOCUMENT_NODE = 9;
- var DOCUMENT_FRAGMENT_NODE = 11;
- /**
- * Set the textContent property of a node. For text updates, it's faster
- * to set the `nodeValue` of the Text node directly instead of using
- * `.textContent` which will remove the existing node and create a new one.
- *
- * @param {DOMElement} node
- * @param {string} text
- * @internal
- */
- var setTextContent = function (node, text) {
- if (text) {
- var firstChild = node.firstChild;
- if (firstChild && firstChild === node.lastChild && firstChild.nodeType === TEXT_NODE) {
- firstChild.nodeValue = text;
- return;
- }
- }
- node.textContent = text;
- };
- // List derived from Gecko source code:
- // https://github.com/mozilla/gecko-dev/blob/4e638efc71/layout/style/test/property_database.js
- var shorthandToLonghand = {
- animation: ['animationDelay', 'animationDirection', 'animationDuration', 'animationFillMode', 'animationIterationCount', 'animationName', 'animationPlayState', 'animationTimingFunction'],
- background: ['backgroundAttachment', 'backgroundClip', 'backgroundColor', 'backgroundImage', 'backgroundOrigin', 'backgroundPositionX', 'backgroundPositionY', 'backgroundRepeat', 'backgroundSize'],
- backgroundPosition: ['backgroundPositionX', 'backgroundPositionY'],
- border: ['borderBottomColor', 'borderBottomStyle', 'borderBottomWidth', 'borderImageOutset', 'borderImageRepeat', 'borderImageSlice', 'borderImageSource', 'borderImageWidth', 'borderLeftColor', 'borderLeftStyle', 'borderLeftWidth', 'borderRightColor', 'borderRightStyle', 'borderRightWidth', 'borderTopColor', 'borderTopStyle', 'borderTopWidth'],
- borderBlockEnd: ['borderBlockEndColor', 'borderBlockEndStyle', 'borderBlockEndWidth'],
- borderBlockStart: ['borderBlockStartColor', 'borderBlockStartStyle', 'borderBlockStartWidth'],
- borderBottom: ['borderBottomColor', 'borderBottomStyle', 'borderBottomWidth'],
- borderColor: ['borderBottomColor', 'borderLeftColor', 'borderRightColor', 'borderTopColor'],
- borderImage: ['borderImageOutset', 'borderImageRepeat', 'borderImageSlice', 'borderImageSource', 'borderImageWidth'],
- borderInlineEnd: ['borderInlineEndColor', 'borderInlineEndStyle', 'borderInlineEndWidth'],
- borderInlineStart: ['borderInlineStartColor', 'borderInlineStartStyle', 'borderInlineStartWidth'],
- borderLeft: ['borderLeftColor', 'borderLeftStyle', 'borderLeftWidth'],
- borderRadius: ['borderBottomLeftRadius', 'borderBottomRightRadius', 'borderTopLeftRadius', 'borderTopRightRadius'],
- borderRight: ['borderRightColor', 'borderRightStyle', 'borderRightWidth'],
- borderStyle: ['borderBottomStyle', 'borderLeftStyle', 'borderRightStyle', 'borderTopStyle'],
- borderTop: ['borderTopColor', 'borderTopStyle', 'borderTopWidth'],
- borderWidth: ['borderBottomWidth', 'borderLeftWidth', 'borderRightWidth', 'borderTopWidth'],
- columnRule: ['columnRuleColor', 'columnRuleStyle', 'columnRuleWidth'],
- columns: ['columnCount', 'columnWidth'],
- flex: ['flexBasis', 'flexGrow', 'flexShrink'],
- flexFlow: ['flexDirection', 'flexWrap'],
- font: ['fontFamily', 'fontFeatureSettings', 'fontKerning', 'fontLanguageOverride', 'fontSize', 'fontSizeAdjust', 'fontStretch', 'fontStyle', 'fontVariant', 'fontVariantAlternates', 'fontVariantCaps', 'fontVariantEastAsian', 'fontVariantLigatures', 'fontVariantNumeric', 'fontVariantPosition', 'fontWeight', 'lineHeight'],
- fontVariant: ['fontVariantAlternates', 'fontVariantCaps', 'fontVariantEastAsian', 'fontVariantLigatures', 'fontVariantNumeric', 'fontVariantPosition'],
- gap: ['columnGap', 'rowGap'],
- grid: ['gridAutoColumns', 'gridAutoFlow', 'gridAutoRows', 'gridTemplateAreas', 'gridTemplateColumns', 'gridTemplateRows'],
- gridArea: ['gridColumnEnd', 'gridColumnStart', 'gridRowEnd', 'gridRowStart'],
- gridColumn: ['gridColumnEnd', 'gridColumnStart'],
- gridColumnGap: ['columnGap'],
- gridGap: ['columnGap', 'rowGap'],
- gridRow: ['gridRowEnd', 'gridRowStart'],
- gridRowGap: ['rowGap'],
- gridTemplate: ['gridTemplateAreas', 'gridTemplateColumns', 'gridTemplateRows'],
- listStyle: ['listStyleImage', 'listStylePosition', 'listStyleType'],
- margin: ['marginBottom', 'marginLeft', 'marginRight', 'marginTop'],
- marker: ['markerEnd', 'markerMid', 'markerStart'],
- mask: ['maskClip', 'maskComposite', 'maskImage', 'maskMode', 'maskOrigin', 'maskPositionX', 'maskPositionY', 'maskRepeat', 'maskSize'],
- maskPosition: ['maskPositionX', 'maskPositionY'],
- outline: ['outlineColor', 'outlineStyle', 'outlineWidth'],
- overflow: ['overflowX', 'overflowY'],
- padding: ['paddingBottom', 'paddingLeft', 'paddingRight', 'paddingTop'],
- placeContent: ['alignContent', 'justifyContent'],
- placeItems: ['alignItems', 'justifyItems'],
- placeSelf: ['alignSelf', 'justifySelf'],
- textDecoration: ['textDecorationColor', 'textDecorationLine', 'textDecorationStyle'],
- textEmphasis: ['textEmphasisColor', 'textEmphasisStyle'],
- transition: ['transitionDelay', 'transitionDuration', 'transitionProperty', 'transitionTimingFunction'],
- wordWrap: ['overflowWrap']
- };
- /**
- * CSS properties which accept numbers but are not in units of "px".
- */
- var isUnitlessNumber = {
- animationIterationCount: true,
- aspectRatio: true,
- borderImageOutset: true,
- borderImageSlice: true,
- borderImageWidth: true,
- boxFlex: true,
- boxFlexGroup: true,
- boxOrdinalGroup: true,
- columnCount: true,
- columns: true,
- flex: true,
- flexGrow: true,
- flexPositive: true,
- flexShrink: true,
- flexNegative: true,
- flexOrder: true,
- gridArea: true,
- gridRow: true,
- gridRowEnd: true,
- gridRowSpan: true,
- gridRowStart: true,
- gridColumn: true,
- gridColumnEnd: true,
- gridColumnSpan: true,
- gridColumnStart: true,
- fontWeight: true,
- lineClamp: true,
- lineHeight: true,
- opacity: true,
- order: true,
- orphans: true,
- tabSize: true,
- widows: true,
- zIndex: true,
- zoom: true,
- // SVG-related properties
- fillOpacity: true,
- floodOpacity: true,
- stopOpacity: true,
- strokeDasharray: true,
- strokeDashoffset: true,
- strokeMiterlimit: true,
- strokeOpacity: true,
- strokeWidth: true
- };
- /**
- * @param {string} prefix vendor-specific prefix, eg: Webkit
- * @param {string} key style name, eg: transitionDuration
- * @return {string} style name prefixed with `prefix`, properly camelCased, eg:
- * WebkitTransitionDuration
- */
- function prefixKey(prefix, key) {
- return prefix + key.charAt(0).toUpperCase() + key.substring(1);
- }
- /**
- * Support style names that may come passed in prefixed by adding permutations
- * of vendor prefixes.
- */
- var prefixes = ['Webkit', 'ms', 'Moz', 'O']; // Using Object.keys here, or else the vanilla for-in loop makes IE8 go into an
- // infinite loop, because it iterates over the newly added props too.
- Object.keys(isUnitlessNumber).forEach(function (prop) {
- prefixes.forEach(function (prefix) {
- isUnitlessNumber[prefixKey(prefix, prop)] = isUnitlessNumber[prop];
- });
- });
- /**
- * Convert a value into the proper css writable value. The style name `name`
- * should be logical (no hyphens), as specified
- * in `CSSProperty.isUnitlessNumber`.
- *
- * @param {string} name CSS property name such as `topMargin`.
- * @param {*} value CSS property value such as `10px`.
- * @return {string} Normalized style value with dimensions applied.
- */
- function dangerousStyleValue(name, value, isCustomProperty) {
- // Note that we've removed escapeTextForBrowser() calls here since the
- // whole string will be escaped when the attribute is injected into
- // the markup. If you provide unsafe user data here they can inject
- // arbitrary CSS which may be problematic (I couldn't repro this):
- // https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet
- // http://www.thespanner.co.uk/2007/11/26/ultimate-xss-css-injection/
- // This is not an XSS hole but instead a potential CSS injection issue
- // which has lead to a greater discussion about how we're going to
- // trust URLs moving forward. See #2115901
- var isEmpty = value == null || typeof value === 'boolean' || value === '';
- if (isEmpty) {
- return '';
- }
- if (!isCustomProperty && typeof value === 'number' && value !== 0 && !(isUnitlessNumber.hasOwnProperty(name) && isUnitlessNumber[name])) {
- return value + 'px'; // Presumes implicit 'px' suffix for unitless numbers
- }
- {
- checkCSSPropertyStringCoercion(value, name);
- }
- return ('' + value).trim();
- }
- var uppercasePattern = /([A-Z])/g;
- var msPattern = /^ms-/;
- /**
- * Hyphenates a camelcased CSS property name, for example:
- *
- * > hyphenateStyleName('backgroundColor')
- * < "background-color"
- * > hyphenateStyleName('MozTransition')
- * < "-moz-transition"
- * > hyphenateStyleName('msTransition')
- * < "-ms-transition"
- *
- * As Modernizr suggests (http://modernizr.com/docs/#prefixed), an `ms` prefix
- * is converted to `-ms-`.
- */
- function hyphenateStyleName(name) {
- return name.replace(uppercasePattern, '-$1').toLowerCase().replace(msPattern, '-ms-');
- }
- var warnValidStyle = function () { };
- {
- // 'msTransform' is correct, but the other prefixes should be capitalized
- var badVendoredStyleNamePattern = /^(?:webkit|moz|o)[A-Z]/;
- var msPattern$1 = /^-ms-/;
- var hyphenPattern = /-(.)/g; // style values shouldn't contain a semicolon
- var badStyleValueWithSemicolonPattern = /;\s*$/;
- var warnedStyleNames = {};
- var warnedStyleValues = {};
- var warnedForNaNValue = false;
- var warnedForInfinityValue = false;
- var camelize = function (string) {
- return string.replace(hyphenPattern, function (_, character) {
- return character.toUpperCase();
- });
- };
- var warnHyphenatedStyleName = function (name) {
- if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {
- return;
- }
- warnedStyleNames[name] = true;
- error('Unsupported style property %s. Did you mean %s?', name, // As Andi Smith suggests
- // (http://www.andismith.com/blog/2012/02/modernizr-prefixed/), an `-ms` prefix
- // is converted to lowercase `ms`.
- camelize(name.replace(msPattern$1, 'ms-')));
- };
- var warnBadVendoredStyleName = function (name) {
- if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {
- return;
- }
- warnedStyleNames[name] = true;
- error('Unsupported vendor-prefixed style property %s. Did you mean %s?', name, name.charAt(0).toUpperCase() + name.slice(1));
- };
- var warnStyleValueWithSemicolon = function (name, value) {
- if (warnedStyleValues.hasOwnProperty(value) && warnedStyleValues[value]) {
- return;
- }
- warnedStyleValues[value] = true;
- error("Style property values shouldn't contain a semicolon. " + 'Try "%s: %s" instead.', name, value.replace(badStyleValueWithSemicolonPattern, ''));
- };
- var warnStyleValueIsNaN = function (name, value) {
- if (warnedForNaNValue) {
- return;
- }
- warnedForNaNValue = true;
- error('`NaN` is an invalid value for the `%s` css style property.', name);
- };
- var warnStyleValueIsInfinity = function (name, value) {
- if (warnedForInfinityValue) {
- return;
- }
- warnedForInfinityValue = true;
- error('`Infinity` is an invalid value for the `%s` css style property.', name);
- };
- warnValidStyle = function (name, value) {
- if (name.indexOf('-') > -1) {
- warnHyphenatedStyleName(name);
- } else if (badVendoredStyleNamePattern.test(name)) {
- warnBadVendoredStyleName(name);
- } else if (badStyleValueWithSemicolonPattern.test(value)) {
- warnStyleValueWithSemicolon(name, value);
- }
- if (typeof value === 'number') {
- if (isNaN(value)) {
- warnStyleValueIsNaN(name, value);
- } else if (!isFinite(value)) {
- warnStyleValueIsInfinity(name, value);
- }
- }
- };
- }
- var warnValidStyle$1 = warnValidStyle;
- /**
- * Operations for dealing with CSS properties.
- */
- /**
- * This creates a string that is expected to be equivalent to the style
- * attribute generated by server-side rendering. It by-passes warnings and
- * security checks so it's not safe to use this value for anything other than
- * comparison. It is only used in DEV for SSR validation.
- */
- function createDangerousStringForStyles(styles) {
- {
- var serialized = '';
- var delimiter = '';
- for (var styleName in styles) {
- if (!styles.hasOwnProperty(styleName)) {
- continue;
- }
- var styleValue = styles[styleName];
- if (styleValue != null) {
- var isCustomProperty = styleName.indexOf('--') === 0;
- serialized += delimiter + (isCustomProperty ? styleName : hyphenateStyleName(styleName)) + ':';
- serialized += dangerousStyleValue(styleName, styleValue, isCustomProperty);
- delimiter = ';';
- }
- }
- return serialized || null;
- }
- }
- /**
- * Sets the value for multiple styles on a node. If a value is specified as
- * '' (empty string), the corresponding style property will be unset.
- *
- * @param {DOMElement} node
- * @param {object} styles
- */
- function setValueForStyles(node, styles) {
- var style = node.style;
- for (var styleName in styles) {
- if (!styles.hasOwnProperty(styleName)) {
- continue;
- }
- var isCustomProperty = styleName.indexOf('--') === 0;
- {
- if (!isCustomProperty) {
- warnValidStyle$1(styleName, styles[styleName]);
- }
- }
- var styleValue = dangerousStyleValue(styleName, styles[styleName], isCustomProperty);
- if (styleName === 'float') {
- styleName = 'cssFloat';
- }
- if (isCustomProperty) {
- style.setProperty(styleName, styleValue);
- } else {
- style[styleName] = styleValue;
- }
- }
- }
- function isValueEmpty(value) {
- return value == null || typeof value === 'boolean' || value === '';
- }
- /**
- * Given {color: 'red', overflow: 'hidden'} returns {
- * color: 'color',
- * overflowX: 'overflow',
- * overflowY: 'overflow',
- * }. This can be read as "the overflowY property was set by the overflow
- * shorthand". That is, the values are the property that each was derived from.
- */
- function expandShorthandMap(styles) {
- var expanded = {};
- for (var key in styles) {
- var longhands = shorthandToLonghand[key] || [key];
- for (var i = 0; i < longhands.length; i++) {
- expanded[longhands[i]] = key;
- }
- }
- return expanded;
- }
- /**
- * When mixing shorthand and longhand property names, we warn during updates if
- * we expect an incorrect result to occur. In particular, we warn for:
- *
- * Updating a shorthand property (longhand gets overwritten):
- * {font: 'foo', fontVariant: 'bar'} -> {font: 'baz', fontVariant: 'bar'}
- * becomes .style.font = 'baz'
- * Removing a shorthand property (longhand gets lost too):
- * {font: 'foo', fontVariant: 'bar'} -> {fontVariant: 'bar'}
- * becomes .style.font = ''
- * Removing a longhand property (should revert to shorthand; doesn't):
- * {font: 'foo', fontVariant: 'bar'} -> {font: 'foo'}
- * becomes .style.fontVariant = ''
- */
- function validateShorthandPropertyCollisionInDev(styleUpdates, nextStyles) {
- {
- if (!nextStyles) {
- return;
- }
- var expandedUpdates = expandShorthandMap(styleUpdates);
- var expandedStyles = expandShorthandMap(nextStyles);
- var warnedAbout = {};
- for (var key in expandedUpdates) {
- var originalKey = expandedUpdates[key];
- var correctOriginalKey = expandedStyles[key];
- if (correctOriginalKey && originalKey !== correctOriginalKey) {
- var warningKey = originalKey + ',' + correctOriginalKey;
- if (warnedAbout[warningKey]) {
- continue;
- }
- warnedAbout[warningKey] = true;
- error('%s a style property during rerender (%s) when a ' + 'conflicting property is set (%s) can lead to styling bugs. To ' + "avoid this, don't mix shorthand and non-shorthand properties " + 'for the same value; instead, replace the shorthand with ' + 'separate values.', isValueEmpty(styleUpdates[originalKey]) ? 'Removing' : 'Updating', originalKey, correctOriginalKey);
- }
- }
- }
- }
- // For HTML, certain tags should omit their close tag. We keep a list for
- // those special-case tags.
- var omittedCloseTags = {
- area: true,
- base: true,
- br: true,
- col: true,
- embed: true,
- hr: true,
- img: true,
- input: true,
- keygen: true,
- link: true,
- meta: true,
- param: true,
- source: true,
- track: true,
- wbr: true // NOTE: menuitem's close tag should be omitted, but that causes problems.
- };
- // `omittedCloseTags` except that `menuitem` should still have its closing tag.
- var voidElementTags = assign({
- menuitem: true
- }, omittedCloseTags);
- var HTML = '__html';
- function assertValidProps(tag, props) {
- if (!props) {
- return;
- } // Note the use of `==` which checks for null or undefined.
- if (voidElementTags[tag]) {
- if (props.children != null || props.dangerouslySetInnerHTML != null) {
- throw new Error(tag + " is a void element tag and must neither have `children` nor " + 'use `dangerouslySetInnerHTML`.');
- }
- }
- if (props.dangerouslySetInnerHTML != null) {
- if (props.children != null) {
- throw new Error('Can only set one of `children` or `props.dangerouslySetInnerHTML`.');
- }
- if (typeof props.dangerouslySetInnerHTML !== 'object' || !(HTML in props.dangerouslySetInnerHTML)) {
- throw new Error('`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. ' + 'Please visit https://reactjs.org/link/dangerously-set-inner-html ' + 'for more information.');
- }
- }
- {
- if (!props.suppressContentEditableWarning && props.contentEditable && props.children != null) {
- error('A component is `contentEditable` and contains `children` managed by ' + 'React. It is now your responsibility to guarantee that none of ' + 'those nodes are unexpectedly modified or duplicated. This is ' + 'probably not intentional.');
- }
- }
- if (props.style != null && typeof props.style !== 'object') {
- throw new Error('The `style` prop expects a mapping from style properties to values, ' + "not a string. For example, style={{marginRight: spacing + 'em'}} when " + 'using JSX.');
- }
- }
- function isCustomComponent(tagName, props) {
- if (tagName.indexOf('-') === -1) {
- return typeof props.is === 'string';
- }
- switch (tagName) {
- // These are reserved SVG and MathML elements.
- // We don't mind this list too much because we expect it to never grow.
- // The alternative is to track the namespace in a few places which is convoluted.
- // https://w3c.github.io/webcomponents/spec/custom/#custom-elements-core-concepts
- case 'annotation-xml':
- case 'color-profile':
- case 'font-face':
- case 'font-face-src':
- case 'font-face-uri':
- case 'font-face-format':
- case 'font-face-name':
- case 'missing-glyph':
- return false;
- default:
- return true;
- }
- }
- // When adding attributes to the HTML or SVG allowed attribute list, be sure to
- // also add them to this module to ensure casing and incorrect name
- // warnings.
- var possibleStandardNames = {
- // HTML
- accept: 'accept',
- acceptcharset: 'acceptCharset',
- 'accept-charset': 'acceptCharset',
- accesskey: 'accessKey',
- action: 'action',
- allowfullscreen: 'allowFullScreen',
- alt: 'alt',
- as: 'as',
- async: 'async',
- autocapitalize: 'autoCapitalize',
- autocomplete: 'autoComplete',
- autocorrect: 'autoCorrect',
- autofocus: 'autoFocus',
- autoplay: 'autoPlay',
- autosave: 'autoSave',
- capture: 'capture',
- cellpadding: 'cellPadding',
- cellspacing: 'cellSpacing',
- challenge: 'challenge',
- charset: 'charSet',
- checked: 'checked',
- children: 'children',
- cite: 'cite',
- class: 'className',
- classid: 'classID',
- classname: 'className',
- cols: 'cols',
- colspan: 'colSpan',
- content: 'content',
- contenteditable: 'contentEditable',
- contextmenu: 'contextMenu',
- controls: 'controls',
- controlslist: 'controlsList',
- coords: 'coords',
- crossorigin: 'crossOrigin',
- dangerouslysetinnerhtml: 'dangerouslySetInnerHTML',
- data: 'data',
- datetime: 'dateTime',
- default: 'default',
- defaultchecked: 'defaultChecked',
- defaultvalue: 'defaultValue',
- defer: 'defer',
- dir: 'dir',
- disabled: 'disabled',
- disablepictureinpicture: 'disablePictureInPicture',
- disableremoteplayback: 'disableRemotePlayback',
- download: 'download',
- draggable: 'draggable',
- enctype: 'encType',
- enterkeyhint: 'enterKeyHint',
- for: 'htmlFor',
- form: 'form',
- formmethod: 'formMethod',
- formaction: 'formAction',
- formenctype: 'formEncType',
- formnovalidate: 'formNoValidate',
- formtarget: 'formTarget',
- frameborder: 'frameBorder',
- headers: 'headers',
- height: 'height',
- hidden: 'hidden',
- high: 'high',
- href: 'href',
- hreflang: 'hrefLang',
- htmlfor: 'htmlFor',
- httpequiv: 'httpEquiv',
- 'http-equiv': 'httpEquiv',
- icon: 'icon',
- id: 'id',
- imagesizes: 'imageSizes',
- imagesrcset: 'imageSrcSet',
- innerhtml: 'innerHTML',
- inputmode: 'inputMode',
- integrity: 'integrity',
- is: 'is',
- itemid: 'itemID',
- itemprop: 'itemProp',
- itemref: 'itemRef',
- itemscope: 'itemScope',
- itemtype: 'itemType',
- keyparams: 'keyParams',
- keytype: 'keyType',
- kind: 'kind',
- label: 'label',
- lang: 'lang',
- list: 'list',
- loop: 'loop',
- low: 'low',
- manifest: 'manifest',
- marginwidth: 'marginWidth',
- marginheight: 'marginHeight',
- max: 'max',
- maxlength: 'maxLength',
- media: 'media',
- mediagroup: 'mediaGroup',
- method: 'method',
- min: 'min',
- minlength: 'minLength',
- multiple: 'multiple',
- muted: 'muted',
- name: 'name',
- nomodule: 'noModule',
- nonce: 'nonce',
- novalidate: 'noValidate',
- open: 'open',
- optimum: 'optimum',
- pattern: 'pattern',
- placeholder: 'placeholder',
- playsinline: 'playsInline',
- poster: 'poster',
- preload: 'preload',
- profile: 'profile',
- radiogroup: 'radioGroup',
- readonly: 'readOnly',
- referrerpolicy: 'referrerPolicy',
- rel: 'rel',
- required: 'required',
- reversed: 'reversed',
- role: 'role',
- rows: 'rows',
- rowspan: 'rowSpan',
- sandbox: 'sandbox',
- scope: 'scope',
- scoped: 'scoped',
- scrolling: 'scrolling',
- seamless: 'seamless',
- selected: 'selected',
- shape: 'shape',
- size: 'size',
- sizes: 'sizes',
- span: 'span',
- spellcheck: 'spellCheck',
- src: 'src',
- srcdoc: 'srcDoc',
- srclang: 'srcLang',
- srcset: 'srcSet',
- start: 'start',
- step: 'step',
- style: 'style',
- summary: 'summary',
- tabindex: 'tabIndex',
- target: 'target',
- title: 'title',
- type: 'type',
- usemap: 'useMap',
- value: 'value',
- width: 'width',
- wmode: 'wmode',
- wrap: 'wrap',
- // SVG
- about: 'about',
- accentheight: 'accentHeight',
- 'accent-height': 'accentHeight',
- accumulate: 'accumulate',
- additive: 'additive',
- alignmentbaseline: 'alignmentBaseline',
- 'alignment-baseline': 'alignmentBaseline',
- allowreorder: 'allowReorder',
- alphabetic: 'alphabetic',
- amplitude: 'amplitude',
- arabicform: 'arabicForm',
- 'arabic-form': 'arabicForm',
- ascent: 'ascent',
- attributename: 'attributeName',
- attributetype: 'attributeType',
- autoreverse: 'autoReverse',
- azimuth: 'azimuth',
- basefrequency: 'baseFrequency',
- baselineshift: 'baselineShift',
- 'baseline-shift': 'baselineShift',
- baseprofile: 'baseProfile',
- bbox: 'bbox',
- begin: 'begin',
- bias: 'bias',
- by: 'by',
- calcmode: 'calcMode',
- capheight: 'capHeight',
- 'cap-height': 'capHeight',
- clip: 'clip',
- clippath: 'clipPath',
- 'clip-path': 'clipPath',
- clippathunits: 'clipPathUnits',
- cliprule: 'clipRule',
- 'clip-rule': 'clipRule',
- color: 'color',
- colorinterpolation: 'colorInterpolation',
- 'color-interpolation': 'colorInterpolation',
- colorinterpolationfilters: 'colorInterpolationFilters',
- 'color-interpolation-filters': 'colorInterpolationFilters',
- colorprofile: 'colorProfile',
- 'color-profile': 'colorProfile',
- colorrendering: 'colorRendering',
- 'color-rendering': 'colorRendering',
- contentscripttype: 'contentScriptType',
- contentstyletype: 'contentStyleType',
- cursor: 'cursor',
- cx: 'cx',
- cy: 'cy',
- d: 'd',
- datatype: 'datatype',
- decelerate: 'decelerate',
- descent: 'descent',
- diffuseconstant: 'diffuseConstant',
- direction: 'direction',
- display: 'display',
- divisor: 'divisor',
- dominantbaseline: 'dominantBaseline',
- 'dominant-baseline': 'dominantBaseline',
- dur: 'dur',
- dx: 'dx',
- dy: 'dy',
- edgemode: 'edgeMode',
- elevation: 'elevation',
- enablebackground: 'enableBackground',
- 'enable-background': 'enableBackground',
- end: 'end',
- exponent: 'exponent',
- externalresourcesrequired: 'externalResourcesRequired',
- fill: 'fill',
- fillopacity: 'fillOpacity',
- 'fill-opacity': 'fillOpacity',
- fillrule: 'fillRule',
- 'fill-rule': 'fillRule',
- filter: 'filter',
- filterres: 'filterRes',
- filterunits: 'filterUnits',
- floodopacity: 'floodOpacity',
- 'flood-opacity': 'floodOpacity',
- floodcolor: 'floodColor',
- 'flood-color': 'floodColor',
- focusable: 'focusable',
- fontfamily: 'fontFamily',
- 'font-family': 'fontFamily',
- fontsize: 'fontSize',
- 'font-size': 'fontSize',
- fontsizeadjust: 'fontSizeAdjust',
- 'font-size-adjust': 'fontSizeAdjust',
- fontstretch: 'fontStretch',
- 'font-stretch': 'fontStretch',
- fontstyle: 'fontStyle',
- 'font-style': 'fontStyle',
- fontvariant: 'fontVariant',
- 'font-variant': 'fontVariant',
- fontweight: 'fontWeight',
- 'font-weight': 'fontWeight',
- format: 'format',
- from: 'from',
- fx: 'fx',
- fy: 'fy',
- g1: 'g1',
- g2: 'g2',
- glyphname: 'glyphName',
- 'glyph-name': 'glyphName',
- glyphorientationhorizontal: 'glyphOrientationHorizontal',
- 'glyph-orientation-horizontal': 'glyphOrientationHorizontal',
- glyphorientationvertical: 'glyphOrientationVertical',
- 'glyph-orientation-vertical': 'glyphOrientationVertical',
- glyphref: 'glyphRef',
- gradienttransform: 'gradientTransform',
- gradientunits: 'gradientUnits',
- hanging: 'hanging',
- horizadvx: 'horizAdvX',
- 'horiz-adv-x': 'horizAdvX',
- horizoriginx: 'horizOriginX',
- 'horiz-origin-x': 'horizOriginX',
- ideographic: 'ideographic',
- imagerendering: 'imageRendering',
- 'image-rendering': 'imageRendering',
- in2: 'in2',
- in: 'in',
- inlist: 'inlist',
- intercept: 'intercept',
- k1: 'k1',
- k2: 'k2',
- k3: 'k3',
- k4: 'k4',
- k: 'k',
- kernelmatrix: 'kernelMatrix',
- kernelunitlength: 'kernelUnitLength',
- kerning: 'kerning',
- keypoints: 'keyPoints',
- keysplines: 'keySplines',
- keytimes: 'keyTimes',
- lengthadjust: 'lengthAdjust',
- letterspacing: 'letterSpacing',
- 'letter-spacing': 'letterSpacing',
- lightingcolor: 'lightingColor',
- 'lighting-color': 'lightingColor',
- limitingconeangle: 'limitingConeAngle',
- local: 'local',
- markerend: 'markerEnd',
- 'marker-end': 'markerEnd',
- markerheight: 'markerHeight',
- markermid: 'markerMid',
- 'marker-mid': 'markerMid',
- markerstart: 'markerStart',
- 'marker-start': 'markerStart',
- markerunits: 'markerUnits',
- markerwidth: 'markerWidth',
- mask: 'mask',
- maskcontentunits: 'maskContentUnits',
- maskunits: 'maskUnits',
- mathematical: 'mathematical',
- mode: 'mode',
- numoctaves: 'numOctaves',
- offset: 'offset',
- opacity: 'opacity',
- operator: 'operator',
- order: 'order',
- orient: 'orient',
- orientation: 'orientation',
- origin: 'origin',
- overflow: 'overflow',
- overlineposition: 'overlinePosition',
- 'overline-position': 'overlinePosition',
- overlinethickness: 'overlineThickness',
- 'overline-thickness': 'overlineThickness',
- paintorder: 'paintOrder',
- 'paint-order': 'paintOrder',
- panose1: 'panose1',
- 'panose-1': 'panose1',
- pathlength: 'pathLength',
- patterncontentunits: 'patternContentUnits',
- patterntransform: 'patternTransform',
- patternunits: 'patternUnits',
- pointerevents: 'pointerEvents',
- 'pointer-events': 'pointerEvents',
- points: 'points',
- pointsatx: 'pointsAtX',
- pointsaty: 'pointsAtY',
- pointsatz: 'pointsAtZ',
- prefix: 'prefix',
- preservealpha: 'preserveAlpha',
- preserveaspectratio: 'preserveAspectRatio',
- primitiveunits: 'primitiveUnits',
- property: 'property',
- r: 'r',
- radius: 'radius',
- refx: 'refX',
- refy: 'refY',
- renderingintent: 'renderingIntent',
- 'rendering-intent': 'renderingIntent',
- repeatcount: 'repeatCount',
- repeatdur: 'repeatDur',
- requiredextensions: 'requiredExtensions',
- requiredfeatures: 'requiredFeatures',
- resource: 'resource',
- restart: 'restart',
- result: 'result',
- results: 'results',
- rotate: 'rotate',
- rx: 'rx',
- ry: 'ry',
- scale: 'scale',
- security: 'security',
- seed: 'seed',
- shaperendering: 'shapeRendering',
- 'shape-rendering': 'shapeRendering',
- slope: 'slope',
- spacing: 'spacing',
- specularconstant: 'specularConstant',
- specularexponent: 'specularExponent',
- speed: 'speed',
- spreadmethod: 'spreadMethod',
- startoffset: 'startOffset',
- stddeviation: 'stdDeviation',
- stemh: 'stemh',
- stemv: 'stemv',
- stitchtiles: 'stitchTiles',
- stopcolor: 'stopColor',
- 'stop-color': 'stopColor',
- stopopacity: 'stopOpacity',
- 'stop-opacity': 'stopOpacity',
- strikethroughposition: 'strikethroughPosition',
- 'strikethrough-position': 'strikethroughPosition',
- strikethroughthickness: 'strikethroughThickness',
- 'strikethrough-thickness': 'strikethroughThickness',
- string: 'string',
- stroke: 'stroke',
- strokedasharray: 'strokeDasharray',
- 'stroke-dasharray': 'strokeDasharray',
- strokedashoffset: 'strokeDashoffset',
- 'stroke-dashoffset': 'strokeDashoffset',
- strokelinecap: 'strokeLinecap',
- 'stroke-linecap': 'strokeLinecap',
- strokelinejoin: 'strokeLinejoin',
- 'stroke-linejoin': 'strokeLinejoin',
- strokemiterlimit: 'strokeMiterlimit',
- 'stroke-miterlimit': 'strokeMiterlimit',
- strokewidth: 'strokeWidth',
- 'stroke-width': 'strokeWidth',
- strokeopacity: 'strokeOpacity',
- 'stroke-opacity': 'strokeOpacity',
- suppresscontenteditablewarning: 'suppressContentEditableWarning',
- suppresshydrationwarning: 'suppressHydrationWarning',
- surfacescale: 'surfaceScale',
- systemlanguage: 'systemLanguage',
- tablevalues: 'tableValues',
- targetx: 'targetX',
- targety: 'targetY',
- textanchor: 'textAnchor',
- 'text-anchor': 'textAnchor',
- textdecoration: 'textDecoration',
- 'text-decoration': 'textDecoration',
- textlength: 'textLength',
- textrendering: 'textRendering',
- 'text-rendering': 'textRendering',
- to: 'to',
- transform: 'transform',
- typeof: 'typeof',
- u1: 'u1',
- u2: 'u2',
- underlineposition: 'underlinePosition',
- 'underline-position': 'underlinePosition',
- underlinethickness: 'underlineThickness',
- 'underline-thickness': 'underlineThickness',
- unicode: 'unicode',
- unicodebidi: 'unicodeBidi',
- 'unicode-bidi': 'unicodeBidi',
- unicoderange: 'unicodeRange',
- 'unicode-range': 'unicodeRange',
- unitsperem: 'unitsPerEm',
- 'units-per-em': 'unitsPerEm',
- unselectable: 'unselectable',
- valphabetic: 'vAlphabetic',
- 'v-alphabetic': 'vAlphabetic',
- values: 'values',
- vectoreffect: 'vectorEffect',
- 'vector-effect': 'vectorEffect',
- version: 'version',
- vertadvy: 'vertAdvY',
- 'vert-adv-y': 'vertAdvY',
- vertoriginx: 'vertOriginX',
- 'vert-origin-x': 'vertOriginX',
- vertoriginy: 'vertOriginY',
- 'vert-origin-y': 'vertOriginY',
- vhanging: 'vHanging',
- 'v-hanging': 'vHanging',
- videographic: 'vIdeographic',
- 'v-ideographic': 'vIdeographic',
- viewbox: 'viewBox',
- viewtarget: 'viewTarget',
- visibility: 'visibility',
- vmathematical: 'vMathematical',
- 'v-mathematical': 'vMathematical',
- vocab: 'vocab',
- widths: 'widths',
- wordspacing: 'wordSpacing',
- 'word-spacing': 'wordSpacing',
- writingmode: 'writingMode',
- 'writing-mode': 'writingMode',
- x1: 'x1',
- x2: 'x2',
- x: 'x',
- xchannelselector: 'xChannelSelector',
- xheight: 'xHeight',
- 'x-height': 'xHeight',
- xlinkactuate: 'xlinkActuate',
- 'xlink:actuate': 'xlinkActuate',
- xlinkarcrole: 'xlinkArcrole',
- 'xlink:arcrole': 'xlinkArcrole',
- xlinkhref: 'xlinkHref',
- 'xlink:href': 'xlinkHref',
- xlinkrole: 'xlinkRole',
- 'xlink:role': 'xlinkRole',
- xlinkshow: 'xlinkShow',
- 'xlink:show': 'xlinkShow',
- xlinktitle: 'xlinkTitle',
- 'xlink:title': 'xlinkTitle',
- xlinktype: 'xlinkType',
- 'xlink:type': 'xlinkType',
- xmlbase: 'xmlBase',
- 'xml:base': 'xmlBase',
- xmllang: 'xmlLang',
- 'xml:lang': 'xmlLang',
- xmlns: 'xmlns',
- 'xml:space': 'xmlSpace',
- xmlnsxlink: 'xmlnsXlink',
- 'xmlns:xlink': 'xmlnsXlink',
- xmlspace: 'xmlSpace',
- y1: 'y1',
- y2: 'y2',
- y: 'y',
- ychannelselector: 'yChannelSelector',
- z: 'z',
- zoomandpan: 'zoomAndPan'
- };
- var ariaProperties = {
- 'aria-current': 0,
- // state
- 'aria-description': 0,
- 'aria-details': 0,
- 'aria-disabled': 0,
- // state
- 'aria-hidden': 0,
- // state
- 'aria-invalid': 0,
- // state
- 'aria-keyshortcuts': 0,
- 'aria-label': 0,
- 'aria-roledescription': 0,
- // Widget Attributes
- 'aria-autocomplete': 0,
- 'aria-checked': 0,
- 'aria-expanded': 0,
- 'aria-haspopup': 0,
- 'aria-level': 0,
- 'aria-modal': 0,
- 'aria-multiline': 0,
- 'aria-multiselectable': 0,
- 'aria-orientation': 0,
- 'aria-placeholder': 0,
- 'aria-pressed': 0,
- 'aria-readonly': 0,
- 'aria-required': 0,
- 'aria-selected': 0,
- 'aria-sort': 0,
- 'aria-valuemax': 0,
- 'aria-valuemin': 0,
- 'aria-valuenow': 0,
- 'aria-valuetext': 0,
- // Live Region Attributes
- 'aria-atomic': 0,
- 'aria-busy': 0,
- 'aria-live': 0,
- 'aria-relevant': 0,
- // Drag-and-Drop Attributes
- 'aria-dropeffect': 0,
- 'aria-grabbed': 0,
- // Relationship Attributes
- 'aria-activedescendant': 0,
- 'aria-colcount': 0,
- 'aria-colindex': 0,
- 'aria-colspan': 0,
- 'aria-controls': 0,
- 'aria-describedby': 0,
- 'aria-errormessage': 0,
- 'aria-flowto': 0,
- 'aria-labelledby': 0,
- 'aria-owns': 0,
- 'aria-posinset': 0,
- 'aria-rowcount': 0,
- 'aria-rowindex': 0,
- 'aria-rowspan': 0,
- 'aria-setsize': 0
- };
- var warnedProperties = {};
- var rARIA = new RegExp('^(aria)-[' + ATTRIBUTE_NAME_CHAR + ']*$');
- var rARIACamel = new RegExp('^(aria)[A-Z][' + ATTRIBUTE_NAME_CHAR + ']*$');
- function validateProperty(tagName, name) {
- {
- if (hasOwnProperty.call(warnedProperties, name) && warnedProperties[name]) {
- return true;
- }
- if (rARIACamel.test(name)) {
- var ariaName = 'aria-' + name.slice(4).toLowerCase();
- var correctName = ariaProperties.hasOwnProperty(ariaName) ? ariaName : null; // If this is an aria-* attribute, but is not listed in the known DOM
- // DOM properties, then it is an invalid aria-* attribute.
- if (correctName == null) {
- error('Invalid ARIA attribute `%s`. ARIA attributes follow the pattern aria-* and must be lowercase.', name);
- warnedProperties[name] = true;
- return true;
- } // aria-* attributes should be lowercase; suggest the lowercase version.
- if (name !== correctName) {
- error('Invalid ARIA attribute `%s`. Did you mean `%s`?', name, correctName);
- warnedProperties[name] = true;
- return true;
- }
- }
- if (rARIA.test(name)) {
- var lowerCasedName = name.toLowerCase();
- var standardName = ariaProperties.hasOwnProperty(lowerCasedName) ? lowerCasedName : null; // If this is an aria-* attribute, but is not listed in the known DOM
- // DOM properties, then it is an invalid aria-* attribute.
- if (standardName == null) {
- warnedProperties[name] = true;
- return false;
- } // aria-* attributes should be lowercase; suggest the lowercase version.
- if (name !== standardName) {
- error('Unknown ARIA attribute `%s`. Did you mean `%s`?', name, standardName);
- warnedProperties[name] = true;
- return true;
- }
- }
- }
- return true;
- }
- function warnInvalidARIAProps(type, props) {
- {
- var invalidProps = [];
- for (var key in props) {
- var isValid = validateProperty(type, key);
- if (!isValid) {
- invalidProps.push(key);
- }
- }
- var unknownPropString = invalidProps.map(function (prop) {
- return '`' + prop + '`';
- }).join(', ');
- if (invalidProps.length === 1) {
- error('Invalid aria prop %s on <%s> tag. ' + 'For details, see https://reactjs.org/link/invalid-aria-props', unknownPropString, type);
- } else if (invalidProps.length > 1) {
- error('Invalid aria props %s on <%s> tag. ' + 'For details, see https://reactjs.org/link/invalid-aria-props', unknownPropString, type);
- }
- }
- }
- function validateProperties(type, props) {
- if (isCustomComponent(type, props)) {
- return;
- }
- warnInvalidARIAProps(type, props);
- }
- var didWarnValueNull = false;
- function validateProperties$1(type, props) {
- {
- if (type !== 'input' && type !== 'textarea' && type !== 'select') {
- return;
- }
- if (props != null && props.value === null && !didWarnValueNull) {
- didWarnValueNull = true;
- if (type === 'select' && props.multiple) {
- error('`value` prop on `%s` should not be null. ' + 'Consider using an empty array when `multiple` is set to `true` ' + 'to clear the component or `undefined` for uncontrolled components.', type);
- } else {
- error('`value` prop on `%s` should not be null. ' + 'Consider using an empty string to clear the component or `undefined` ' + 'for uncontrolled components.', type);
- }
- }
- }
- }
- var validateProperty$1 = function () { };
- {
- var warnedProperties$1 = {};
- var EVENT_NAME_REGEX = /^on./;
- var INVALID_EVENT_NAME_REGEX = /^on[^A-Z]/;
- var rARIA$1 = new RegExp('^(aria)-[' + ATTRIBUTE_NAME_CHAR + ']*$');
- var rARIACamel$1 = new RegExp('^(aria)[A-Z][' + ATTRIBUTE_NAME_CHAR + ']*$');
- validateProperty$1 = function (tagName, name, value, eventRegistry) {
- if (hasOwnProperty.call(warnedProperties$1, name) && warnedProperties$1[name]) {
- return true;
- }
- var lowerCasedName = name.toLowerCase();
- if (lowerCasedName === 'onfocusin' || lowerCasedName === 'onfocusout') {
- error('React uses onFocus and onBlur instead of onFocusIn and onFocusOut. ' + 'All React events are normalized to bubble, so onFocusIn and onFocusOut ' + 'are not needed/supported by React.');
- warnedProperties$1[name] = true;
- return true;
- } // We can't rely on the event system being injected on the server.
- if (eventRegistry != null) {
- var registrationNameDependencies = eventRegistry.registrationNameDependencies,
- possibleRegistrationNames = eventRegistry.possibleRegistrationNames;
- if (registrationNameDependencies.hasOwnProperty(name)) {
- return true;
- }
- var registrationName = possibleRegistrationNames.hasOwnProperty(lowerCasedName) ? possibleRegistrationNames[lowerCasedName] : null;
- if (registrationName != null) {
- error('Invalid event handler property `%s`. Did you mean `%s`?', name, registrationName);
- warnedProperties$1[name] = true;
- return true;
- }
- if (EVENT_NAME_REGEX.test(name)) {
- error('Unknown event handler property `%s`. It will be ignored.', name);
- warnedProperties$1[name] = true;
- return true;
- }
- } else if (EVENT_NAME_REGEX.test(name)) {
- // If no event plugins have been injected, we are in a server environment.
- // So we can't tell if the event name is correct for sure, but we can filter
- // out known bad ones like `onclick`. We can't suggest a specific replacement though.
- if (INVALID_EVENT_NAME_REGEX.test(name)) {
- error('Invalid event handler property `%s`. ' + 'React events use the camelCase naming convention, for example `onClick`.', name);
- }
- warnedProperties$1[name] = true;
- return true;
- } // Let the ARIA attribute hook validate ARIA attributes
- if (rARIA$1.test(name) || rARIACamel$1.test(name)) {
- return true;
- }
- if (lowerCasedName === 'innerhtml') {
- error('Directly setting property `innerHTML` is not permitted. ' + 'For more information, lookup documentation on `dangerouslySetInnerHTML`.');
- warnedProperties$1[name] = true;
- return true;
- }
- if (lowerCasedName === 'aria') {
- error('The `aria` attribute is reserved for future use in React. ' + 'Pass individual `aria-` attributes instead.');
- warnedProperties$1[name] = true;
- return true;
- }
- if (lowerCasedName === 'is' && value !== null && value !== undefined && typeof value !== 'string') {
- error('Received a `%s` for a string attribute `is`. If this is expected, cast ' + 'the value to a string.', typeof value);
- warnedProperties$1[name] = true;
- return true;
- }
- if (typeof value === 'number' && isNaN(value)) {
- error('Received NaN for the `%s` attribute. If this is expected, cast ' + 'the value to a string.', name);
- warnedProperties$1[name] = true;
- return true;
- }
- var propertyInfo = getPropertyInfo(name);
- var isReserved = propertyInfo !== null && propertyInfo.type === RESERVED; // Known attributes should match the casing specified in the property config.
- if (possibleStandardNames.hasOwnProperty(lowerCasedName)) {
- var standardName = possibleStandardNames[lowerCasedName];
- if (standardName !== name) {
- error('Invalid DOM property `%s`. Did you mean `%s`?', name, standardName);
- warnedProperties$1[name] = true;
- return true;
- }
- } else if (!isReserved && name !== lowerCasedName) {
- // Unknown attributes should have lowercase casing since that's how they
- // will be cased anyway with server rendering.
- error('React does not recognize the `%s` prop on a DOM element. If you ' + 'intentionally want it to appear in the DOM as a custom ' + 'attribute, spell it as lowercase `%s` instead. ' + 'If you accidentally passed it from a parent component, remove ' + 'it from the DOM element.', name, lowerCasedName);
- warnedProperties$1[name] = true;
- return true;
- }
- if (typeof value === 'boolean' && shouldRemoveAttributeWithWarning(name, value, propertyInfo, false)) {
- if (value) {
- error('Received `%s` for a non-boolean attribute `%s`.\n\n' + 'If you want to write it to the DOM, pass a string instead: ' + '%s="%s" or %s={value.toString()}.', value, name, name, value, name);
- } else {
- error('Received `%s` for a non-boolean attribute `%s`.\n\n' + 'If you want to write it to the DOM, pass a string instead: ' + '%s="%s" or %s={value.toString()}.\n\n' + 'If you used to conditionally omit it with %s={condition && value}, ' + 'pass %s={condition ? value : undefined} instead.', value, name, name, value, name, name, name);
- }
- warnedProperties$1[name] = true;
- return true;
- } // Now that we've validated casing, do not validate
- // data types for reserved props
- if (isReserved) {
- return true;
- } // Warn when a known attribute is a bad type
- if (shouldRemoveAttributeWithWarning(name, value, propertyInfo, false)) {
- warnedProperties$1[name] = true;
- return false;
- } // Warn when passing the strings 'false' or 'true' into a boolean prop
- if ((value === 'false' || value === 'true') && propertyInfo !== null && propertyInfo.type === BOOLEAN) {
- error('Received the string `%s` for the boolean attribute `%s`. ' + '%s ' + 'Did you mean %s={%s}?', value, name, value === 'false' ? 'The browser will interpret it as a truthy value.' : 'Although this works, it will not work as expected if you pass the string "false".', name, value);
- warnedProperties$1[name] = true;
- return true;
- }
- return true;
- };
- }
- var warnUnknownProperties = function (type, props, eventRegistry) {
- {
- var unknownProps = [];
- for (var key in props) {
- var isValid = validateProperty$1(type, key, props[key], eventRegistry);
- if (!isValid) {
- unknownProps.push(key);
- }
- }
- var unknownPropString = unknownProps.map(function (prop) {
- return '`' + prop + '`';
- }).join(', ');
- if (unknownProps.length === 1) {
- error('Invalid value for prop %s on <%s> tag. Either remove it from the element, ' + 'or pass a string or number value to keep it in the DOM. ' + 'For details, see https://reactjs.org/link/attribute-behavior ', unknownPropString, type);
- } else if (unknownProps.length > 1) {
- error('Invalid values for props %s on <%s> tag. Either remove them from the element, ' + 'or pass a string or number value to keep them in the DOM. ' + 'For details, see https://reactjs.org/link/attribute-behavior ', unknownPropString, type);
- }
- }
- };
- function validateProperties$2(type, props, eventRegistry) {
- if (isCustomComponent(type, props)) {
- return;
- }
- warnUnknownProperties(type, props, eventRegistry);
- }
- var IS_EVENT_HANDLE_NON_MANAGED_NODE = 1;
- var IS_NON_DELEGATED = 1 << 1;
- var IS_CAPTURE_PHASE = 1 << 2;
- // set to LEGACY_FB_SUPPORT. LEGACY_FB_SUPPORT only gets set when
- // we call willDeferLaterForLegacyFBSupport, thus not bailing out
- // will result in endless cycles like an infinite loop.
- // We also don't want to defer during event replaying.
- var SHOULD_NOT_PROCESS_POLYFILL_EVENT_PLUGINS = IS_EVENT_HANDLE_NON_MANAGED_NODE | IS_NON_DELEGATED | IS_CAPTURE_PHASE;
- // This exists to avoid circular dependency between ReactDOMEventReplaying
- // and DOMPluginEventSystem.
- var currentReplayingEvent = null;
- function setReplayingEvent(event) {
- {
- if (currentReplayingEvent !== null) {
- error('Expected currently replaying event to be null. This error ' + 'is likely caused by a bug in React. Please file an issue.');
- }
- }
- currentReplayingEvent = event;
- }
- function resetReplayingEvent() {
- {
- if (currentReplayingEvent === null) {
- error('Expected currently replaying event to not be null. This error ' + 'is likely caused by a bug in React. Please file an issue.');
- }
- }
- currentReplayingEvent = null;
- }
- function isReplayingEvent(event) {
- return event === currentReplayingEvent;
- }
- /**
- * Gets the target node from a native browser event by accounting for
- * inconsistencies in browser DOM APIs.
- *
- * @param {object} nativeEvent Native browser event.
- * @return {DOMEventTarget} Target node.
- */
- function getEventTarget(nativeEvent) {
- // Fallback to nativeEvent.srcElement for IE9
- // https://github.com/facebook/react/issues/12506
- var target = nativeEvent.target || nativeEvent.srcElement || window; // Normalize SVG <use> element events #4963
- if (target.correspondingUseElement) {
- target = target.correspondingUseElement;
- } // Safari may fire events on text nodes (Node.TEXT_NODE is 3).
- // @see http://www.quirksmode.org/js/events_properties.html
- return target.nodeType === TEXT_NODE ? target.parentNode : target;
- }
- var restoreImpl = null;
- var restoreTarget = null;
- var restoreQueue = null;
- function restoreStateOfTarget(target) {
- // We perform this translation at the end of the event loop so that we
- // always receive the correct fiber here
- var internalInstance = getInstanceFromNode(target);
- if (!internalInstance) {
- // Unmounted
- return;
- }
- if (typeof restoreImpl !== 'function') {
- throw new Error('setRestoreImplementation() needs to be called to handle a target for controlled ' + 'events. This error is likely caused by a bug in React. Please file an issue.');
- }
- var stateNode = internalInstance.stateNode; // Guard against Fiber being unmounted.
- if (stateNode) {
- var _props = getFiberCurrentPropsFromNode(stateNode);
- restoreImpl(internalInstance.stateNode, internalInstance.type, _props);
- }
- }
- function setRestoreImplementation(impl) {
- restoreImpl = impl;
- }
- function enqueueStateRestore(target) {
- if (restoreTarget) {
- if (restoreQueue) {
- restoreQueue.push(target);
- } else {
- restoreQueue = [target];
- }
- } else {
- restoreTarget = target;
- }
- }
- function needsStateRestore() {
- return restoreTarget !== null || restoreQueue !== null;
- }
- function restoreStateIfNeeded() {
- if (!restoreTarget) {
- return;
- }
- var target = restoreTarget;
- var queuedTargets = restoreQueue;
- restoreTarget = null;
- restoreQueue = null;
- restoreStateOfTarget(target);
- if (queuedTargets) {
- for (var i = 0; i < queuedTargets.length; i++) {
- restoreStateOfTarget(queuedTargets[i]);
- }
- }
- }
- // the renderer. Such as when we're dispatching events or if third party
- // libraries need to call batchedUpdates. Eventually, this API will go away when
- // everything is batched by default. We'll then have a similar API to opt-out of
- // scheduled work and instead do synchronous work.
- // Defaults
- var batchedUpdatesImpl = function (fn, bookkeeping) {
- return fn(bookkeeping);
- };
- var flushSyncImpl = function () { };
- var isInsideEventHandler = false;
- function finishEventHandler() {
- // Here we wait until all updates have propagated, which is important
- // when using controlled components within layers:
- // https://github.com/facebook/react/issues/1698
- // Then we restore state of any controlled component.
- var controlledComponentsHavePendingUpdates = needsStateRestore();
- if (controlledComponentsHavePendingUpdates) {
- // If a controlled event was fired, we may need to restore the state of
- // the DOM node back to the controlled value. This is necessary when React
- // bails out of the update without touching the DOM.
- // TODO: Restore state in the microtask, after the discrete updates flush,
- // instead of early flushing them here.
- flushSyncImpl();
- restoreStateIfNeeded();
- }
- }
- function batchedUpdates(fn, a, b) {
- if (isInsideEventHandler) {
- // If we are currently inside another batch, we need to wait until it
- // fully completes before restoring state.
- return fn(a, b);
- }
- isInsideEventHandler = true;
- try {
- return batchedUpdatesImpl(fn, a, b);
- } finally {
- isInsideEventHandler = false;
- finishEventHandler();
- }
- } // TODO: Replace with flushSync
- function setBatchingImplementation(_batchedUpdatesImpl, _discreteUpdatesImpl, _flushSyncImpl) {
- batchedUpdatesImpl = _batchedUpdatesImpl;
- flushSyncImpl = _flushSyncImpl;
- }
- function isInteractive(tag) {
- return tag === 'button' || tag === 'input' || tag === 'select' || tag === 'textarea';
- }
- function shouldPreventMouseEvent(name, type, props) {
- switch (name) {
- case 'onClick':
- case 'onClickCapture':
- case 'onDoubleClick':
- case 'onDoubleClickCapture':
- case 'onMouseDown':
- case 'onMouseDownCapture':
- case 'onMouseMove':
- case 'onMouseMoveCapture':
- case 'onMouseUp':
- case 'onMouseUpCapture':
- case 'onMouseEnter':
- return !!(props.disabled && isInteractive(type));
- default:
- return false;
- }
- }
- /**
- * @param {object} inst The instance, which is the source of events.
- * @param {string} registrationName Name of listener (e.g. `onClick`).
- * @return {?function} The stored callback.
- */
- function getListener(inst, registrationName) {
- var stateNode = inst.stateNode;
- if (stateNode === null) {
- // Work in progress (ex: onload events in incremental mode).
- return null;
- }
- var props = getFiberCurrentPropsFromNode(stateNode);
- if (props === null) {
- // Work in progress.
- return null;
- }
- var listener = props[registrationName];
- if (shouldPreventMouseEvent(registrationName, inst.type, props)) {
- return null;
- }
- if (listener && typeof listener !== 'function') {
- throw new Error("Expected `" + registrationName + "` listener to be a function, instead got a value of `" + typeof listener + "` type.");
- }
- return listener;
- }
- var passiveBrowserEventsSupported = false; // Check if browser support events with passive listeners
- // https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Safely_detecting_option_support
- if (canUseDOM) {
- try {
- var options = {}; // $FlowFixMe: Ignore Flow complaining about needing a value
- Object.defineProperty(options, 'passive', {
- get: function () {
- passiveBrowserEventsSupported = true;
- }
- });
- window.addEventListener('test', options, options);
- window.removeEventListener('test', options, options);
- } catch (e) {
- passiveBrowserEventsSupported = false;
- }
- }
- function invokeGuardedCallbackProd(name, func, context, a, b, c, d, e, f) {
- var funcArgs = Array.prototype.slice.call(arguments, 3);
- try {
- func.apply(context, funcArgs);
- } catch (error) {
- this.onError(error);
- }
- }
- var invokeGuardedCallbackImpl = invokeGuardedCallbackProd;
- {
- // In DEV mode, we swap out invokeGuardedCallback for a special version
- // that plays more nicely with the browser's DevTools. The idea is to preserve
- // "Pause on exceptions" behavior. Because React wraps all user-provided
- // functions in invokeGuardedCallback, and the production version of
- // invokeGuardedCallback uses a try-catch, all user exceptions are treated
- // like caught exceptions, and the DevTools won't pause unless the developer
- // takes the extra step of enabling pause on caught exceptions. This is
- // unintuitive, though, because even though React has caught the error, from
- // the developer's perspective, the error is uncaught.
- //
- // To preserve the expected "Pause on exceptions" behavior, we don't use a
- // try-catch in DEV. Instead, we synchronously dispatch a fake event to a fake
- // DOM node, and call the user-provided callback from inside an event handler
- // for that fake event. If the callback throws, the error is "captured" using
- // a global event handler. But because the error happens in a different
- // event loop context, it does not interrupt the normal program flow.
- // Effectively, this gives us try-catch behavior without actually using
- // try-catch. Neat!
- // Check that the browser supports the APIs we need to implement our special
- // DEV version of invokeGuardedCallback
- if (typeof window !== 'undefined' && typeof window.dispatchEvent === 'function' && typeof document !== 'undefined' && typeof document.createEvent === 'function') {
- var fakeNode = document.createElement('react');
- invokeGuardedCallbackImpl = function invokeGuardedCallbackDev(name, func, context, a, b, c, d, e, f) {
- // If document doesn't exist we know for sure we will crash in this method
- // when we call document.createEvent(). However this can cause confusing
- // errors: https://github.com/facebook/create-react-app/issues/3482
- // So we preemptively throw with a better message instead.
- if (typeof document === 'undefined' || document === null) {
- throw new Error('The `document` global was defined when React was initialized, but is not ' + 'defined anymore. This can happen in a test environment if a component ' + 'schedules an update from an asynchronous callback, but the test has already ' + 'finished running. To solve this, you can either unmount the component at ' + 'the end of your test (and ensure that any asynchronous operations get ' + 'canceled in `componentWillUnmount`), or you can change the test itself ' + 'to be asynchronous.');
- }
- var evt = document.createEvent('Event');
- var didCall = false; // Keeps track of whether the user-provided callback threw an error. We
- // set this to true at the beginning, then set it to false right after
- // calling the function. If the function errors, `didError` will never be
- // set to false. This strategy works even if the browser is flaky and
- // fails to call our global error handler, because it doesn't rely on
- // the error event at all.
- var didError = true; // Keeps track of the value of window.event so that we can reset it
- // during the callback to let user code access window.event in the
- // browsers that support it.
- var windowEvent = window.event; // Keeps track of the descriptor of window.event to restore it after event
- // dispatching: https://github.com/facebook/react/issues/13688
- var windowEventDescriptor = Object.getOwnPropertyDescriptor(window, 'event');
- function restoreAfterDispatch() {
- // We immediately remove the callback from event listeners so that
- // nested `invokeGuardedCallback` calls do not clash. Otherwise, a
- // nested call would trigger the fake event handlers of any call higher
- // in the stack.
- fakeNode.removeEventListener(evtType, callCallback, false); // We check for window.hasOwnProperty('event') to prevent the
- // window.event assignment in both IE <= 10 as they throw an error
- // "Member not found" in strict mode, and in Firefox which does not
- // support window.event.
- if (typeof window.event !== 'undefined' && window.hasOwnProperty('event')) {
- window.event = windowEvent;
- }
- } // Create an event handler for our fake event. We will synchronously
- // dispatch our fake event using `dispatchEvent`. Inside the handler, we
- // call the user-provided callback.
- var funcArgs = Array.prototype.slice.call(arguments, 3);
- function callCallback() {
- didCall = true;
- restoreAfterDispatch();
- func.apply(context, funcArgs);
- didError = false;
- } // Create a global error event handler. We use this to capture the value
- // that was thrown. It's possible that this error handler will fire more
- // than once; for example, if non-React code also calls `dispatchEvent`
- // and a handler for that event throws. We should be resilient to most of
- // those cases. Even if our error event handler fires more than once, the
- // last error event is always used. If the callback actually does error,
- // we know that the last error event is the correct one, because it's not
- // possible for anything else to have happened in between our callback
- // erroring and the code that follows the `dispatchEvent` call below. If
- // the callback doesn't error, but the error event was fired, we know to
- // ignore it because `didError` will be false, as described above.
- var error; // Use this to track whether the error event is ever called.
- var didSetError = false;
- var isCrossOriginError = false;
- function handleWindowError(event) {
- error = event.error;
- didSetError = true;
- if (error === null && event.colno === 0 && event.lineno === 0) {
- isCrossOriginError = true;
- }
- if (event.defaultPrevented) {
- // Some other error handler has prevented default.
- // Browsers silence the error report if this happens.
- // We'll remember this to later decide whether to log it or not.
- if (error != null && typeof error === 'object') {
- try {
- error._suppressLogging = true;
- } catch (inner) {// Ignore.
- }
- }
- }
- } // Create a fake event type.
- var evtType = "react-" + (name ? name : 'invokeguardedcallback'); // Attach our event handlers
- window.addEventListener('error', handleWindowError);
- fakeNode.addEventListener(evtType, callCallback, false); // Synchronously dispatch our fake event. If the user-provided function
- // errors, it will trigger our global error handler.
- evt.initEvent(evtType, false, false);
- fakeNode.dispatchEvent(evt);
- if (windowEventDescriptor) {
- Object.defineProperty(window, 'event', windowEventDescriptor);
- }
- if (didCall && didError) {
- if (!didSetError) {
- // The callback errored, but the error event never fired.
- // eslint-disable-next-line react-internal/prod-error-codes
- error = new Error('An error was thrown inside one of your components, but React ' + "doesn't know what it was. This is likely due to browser " + 'flakiness. React does its best to preserve the "Pause on ' + 'exceptions" behavior of the DevTools, which requires some ' + "DEV-mode only tricks. It's possible that these don't work in " + 'your browser. Try triggering the error in production mode, ' + 'or switching to a modern browser. If you suspect that this is ' + 'actually an issue with React, please file an issue.');
- } else if (isCrossOriginError) {
- // eslint-disable-next-line react-internal/prod-error-codes
- error = new Error("A cross-origin error was thrown. React doesn't have access to " + 'the actual error object in development. ' + 'See https://reactjs.org/link/crossorigin-error for more information.');
- }
- this.onError(error);
- } // Remove our event listeners
- window.removeEventListener('error', handleWindowError);
- if (!didCall) {
- // Something went really wrong, and our event was not dispatched.
- // https://github.com/facebook/react/issues/16734
- // https://github.com/facebook/react/issues/16585
- // Fall back to the production implementation.
- restoreAfterDispatch();
- return invokeGuardedCallbackProd.apply(this, arguments);
- }
- };
- }
- }
- var invokeGuardedCallbackImpl$1 = invokeGuardedCallbackImpl;
- var hasError = false;
- var caughtError = null; // Used by event system to capture/rethrow the first error.
- var hasRethrowError = false;
- var rethrowError = null;
- var reporter = {
- onError: function (error) {
- hasError = true;
- caughtError = error;
- }
- };
- /**
- * Call a function while guarding against errors that happens within it.
- * Returns an error if it throws, otherwise null.
- *
- * In production, this is implemented using a try-catch. The reason we don't
- * use a try-catch directly is so that we can swap out a different
- * implementation in DEV mode.
- *
- * @param {String} name of the guard to use for logging or debugging
- * @param {Function} func The function to invoke
- * @param {*} context The context to use when calling the function
- * @param {...*} args Arguments for function
- */
- function invokeGuardedCallback(name, func, context, a, b, c, d, e, f) {
- hasError = false;
- caughtError = null;
- invokeGuardedCallbackImpl$1.apply(reporter, arguments);
- }
- /**
- * Same as invokeGuardedCallback, but instead of returning an error, it stores
- * it in a global so it can be rethrown by `rethrowCaughtError` later.
- * TODO: See if caughtError and rethrowError can be unified.
- *
- * @param {String} name of the guard to use for logging or debugging
- * @param {Function} func The function to invoke
- * @param {*} context The context to use when calling the function
- * @param {...*} args Arguments for function
- */
- function invokeGuardedCallbackAndCatchFirstError(name, func, context, a, b, c, d, e, f) {
- invokeGuardedCallback.apply(this, arguments);
- if (hasError) {
- var error = clearCaughtError();
- if (!hasRethrowError) {
- hasRethrowError = true;
- rethrowError = error;
- }
- }
- }
- /**
- * During execution of guarded functions we will capture the first error which
- * we will rethrow to be handled by the top level error handler.
- */
- function rethrowCaughtError() {
- if (hasRethrowError) {
- var error = rethrowError;
- hasRethrowError = false;
- rethrowError = null;
- throw error;
- }
- }
- function hasCaughtError() {
- return hasError;
- }
- function clearCaughtError() {
- if (hasError) {
- var error = caughtError;
- hasError = false;
- caughtError = null;
- return error;
- } else {
- throw new Error('clearCaughtError was called but no error was captured. This error ' + 'is likely caused by a bug in React. Please file an issue.');
- }
- }
- var ReactInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
- var _ReactInternals$Sched = ReactInternals.Scheduler,
- unstable_cancelCallback = _ReactInternals$Sched.unstable_cancelCallback,
- unstable_now = _ReactInternals$Sched.unstable_now,
- unstable_scheduleCallback = _ReactInternals$Sched.unstable_scheduleCallback,
- unstable_shouldYield = _ReactInternals$Sched.unstable_shouldYield,
- unstable_requestPaint = _ReactInternals$Sched.unstable_requestPaint,
- unstable_getFirstCallbackNode = _ReactInternals$Sched.unstable_getFirstCallbackNode,
- unstable_runWithPriority = _ReactInternals$Sched.unstable_runWithPriority,
- unstable_next = _ReactInternals$Sched.unstable_next,
- unstable_continueExecution = _ReactInternals$Sched.unstable_continueExecution,
- unstable_pauseExecution = _ReactInternals$Sched.unstable_pauseExecution,
- unstable_getCurrentPriorityLevel = _ReactInternals$Sched.unstable_getCurrentPriorityLevel,
- unstable_ImmediatePriority = _ReactInternals$Sched.unstable_ImmediatePriority,
- unstable_UserBlockingPriority = _ReactInternals$Sched.unstable_UserBlockingPriority,
- unstable_NormalPriority = _ReactInternals$Sched.unstable_NormalPriority,
- unstable_LowPriority = _ReactInternals$Sched.unstable_LowPriority,
- unstable_IdlePriority = _ReactInternals$Sched.unstable_IdlePriority,
- unstable_forceFrameRate = _ReactInternals$Sched.unstable_forceFrameRate,
- unstable_flushAllWithoutAsserting = _ReactInternals$Sched.unstable_flushAllWithoutAsserting,
- unstable_yieldValue = _ReactInternals$Sched.unstable_yieldValue,
- unstable_setDisableYieldValue = _ReactInternals$Sched.unstable_setDisableYieldValue;
- /**
- * `ReactInstanceMap` maintains a mapping from a public facing stateful
- * instance (key) and the internal representation (value). This allows public
- * methods to accept the user facing instance as an argument and map them back
- * to internal methods.
- *
- * Note that this module is currently shared and assumed to be stateless.
- * If this becomes an actual Map, that will break.
- */
- function get(key) {
- return key._reactInternals;
- }
- function has(key) {
- return key._reactInternals !== undefined;
- }
- function set(key, value) {
- key._reactInternals = value;
- }
- // Don't change these two values. They're used by React Dev Tools.
- var NoFlags =
- /* */
- 0;
- var PerformedWork =
- /* */
- 1; // You can change the rest (and add more).
- var Placement =
- /* */
- 2;
- var Update =
- /* */
- 4;
- var ChildDeletion =
- /* */
- 16;
- var ContentReset =
- /* */
- 32;
- var Callback =
- /* */
- 64;
- var DidCapture =
- /* */
- 128;
- var ForceClientRender =
- /* */
- 256;
- var Ref =
- /* */
- 512;
- var Snapshot =
- /* */
- 1024;
- var Passive =
- /* */
- 2048;
- var Hydrating =
- /* */
- 4096;
- var Visibility =
- /* */
- 8192;
- var StoreConsistency =
- /* */
- 16384;
- var LifecycleEffectMask = Passive | Update | Callback | Ref | Snapshot | StoreConsistency; // Union of all commit flags (flags with the lifetime of a particular commit)
- var HostEffectMask =
- /* */
- 32767; // These are not really side effects, but we still reuse this field.
- var Incomplete =
- /* */
- 32768;
- var ShouldCapture =
- /* */
- 65536;
- var ForceUpdateForLegacySuspense =
- /* */
- 131072;
- var Forked =
- /* */
- 1048576; // Static tags describe aspects of a fiber that are not specific to a render,
- // e.g. a fiber uses a passive effect (even if there are no updates on this particular render).
- // This enables us to defer more work in the unmount case,
- // since we can defer traversing the tree during layout to look for Passive effects,
- // and instead rely on the static flag as a signal that there may be cleanup work.
- var RefStatic =
- /* */
- 2097152;
- var LayoutStatic =
- /* */
- 4194304;
- var PassiveStatic =
- /* */
- 8388608; // These flags allow us to traverse to fibers that have effects on mount
- // without traversing the entire tree after every commit for
- // double invoking
- var MountLayoutDev =
- /* */
- 16777216;
- var MountPassiveDev =
- /* */
- 33554432; // Groups of flags that are used in the commit phase to skip over trees that
- // don't contain effects, by checking subtreeFlags.
- var BeforeMutationMask = // TODO: Remove Update flag from before mutation phase by re-landing Visibility
- // flag logic (see #20043)
- Update | Snapshot | (0);
- var MutationMask = Placement | Update | ChildDeletion | ContentReset | Ref | Hydrating | Visibility;
- var LayoutMask = Update | Callback | Ref | Visibility; // TODO: Split into PassiveMountMask and PassiveUnmountMask
- var PassiveMask = Passive | ChildDeletion; // Union of tags that don't get reset on clones.
- // This allows certain concepts to persist without recalculating them,
- // e.g. whether a subtree contains passive effects or portals.
- var StaticMask = LayoutStatic | PassiveStatic | RefStatic;
- var ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;
- function getNearestMountedFiber(fiber) {
- var node = fiber;
- var nearestMounted = fiber;
- if (!fiber.alternate) {
- // If there is no alternate, this might be a new tree that isn't inserted
- // yet. If it is, then it will have a pending insertion effect on it.
- var nextNode = node;
- do {
- node = nextNode;
- if ((node.flags & (Placement | Hydrating)) !== NoFlags) {
- // This is an insertion or in-progress hydration. The nearest possible
- // mounted fiber is the parent but we need to continue to figure out
- // if that one is still mounted.
- nearestMounted = node.return;
- }
- nextNode = node.return;
- } while (nextNode);
- } else {
- while (node.return) {
- node = node.return;
- }
- }
- if (node.tag === HostRoot) {
- // TODO: Check if this was a nested HostRoot when used with
- // renderContainerIntoSubtree.
- return nearestMounted;
- } // If we didn't hit the root, that means that we're in an disconnected tree
- // that has been unmounted.
- return null;
- }
- function getSuspenseInstanceFromFiber(fiber) {
- if (fiber.tag === SuspenseComponent) {
- var suspenseState = fiber.memoizedState;
- if (suspenseState === null) {
- var current = fiber.alternate;
- if (current !== null) {
- suspenseState = current.memoizedState;
- }
- }
- if (suspenseState !== null) {
- return suspenseState.dehydrated;
- }
- }
- return null;
- }
- function getContainerFromFiber(fiber) {
- return fiber.tag === HostRoot ? fiber.stateNode.containerInfo : null;
- }
- function isFiberMounted(fiber) {
- return getNearestMountedFiber(fiber) === fiber;
- }
- function isMounted(component) {
- {
- var owner = ReactCurrentOwner.current;
- if (owner !== null && owner.tag === ClassComponent) {
- var ownerFiber = owner;
- var instance = ownerFiber.stateNode;
- if (!instance._warnedAboutRefsInRender) {
- error('%s is accessing isMounted inside its render() function. ' + 'render() should be a pure function of props and state. It should ' + 'never access something that requires stale data from the previous ' + 'render, such as refs. Move this logic to componentDidMount and ' + 'componentDidUpdate instead.', getComponentNameFromFiber(ownerFiber) || 'A component');
- }
- instance._warnedAboutRefsInRender = true;
- }
- }
- var fiber = get(component);
- if (!fiber) {
- return false;
- }
- return getNearestMountedFiber(fiber) === fiber;
- }
- function assertIsMounted(fiber) {
- if (getNearestMountedFiber(fiber) !== fiber) {
- throw new Error('Unable to find node on an unmounted component.');
- }
- }
- function findCurrentFiberUsingSlowPath(fiber) {
- var alternate = fiber.alternate;
- if (!alternate) {
- // If there is no alternate, then we only need to check if it is mounted.
- var nearestMounted = getNearestMountedFiber(fiber);
- if (nearestMounted === null) {
- throw new Error('Unable to find node on an unmounted component.');
- }
- if (nearestMounted !== fiber) {
- return null;
- }
- return fiber;
- } // If we have two possible branches, we'll walk backwards up to the root
- // to see what path the root points to. On the way we may hit one of the
- // special cases and we'll deal with them.
- var a = fiber;
- var b = alternate;
- while (true) {
- var parentA = a.return;
- if (parentA === null) {
- // We're at the root.
- break;
- }
- var parentB = parentA.alternate;
- if (parentB === null) {
- // There is no alternate. This is an unusual case. Currently, it only
- // happens when a Suspense component is hidden. An extra fragment fiber
- // is inserted in between the Suspense fiber and its children. Skip
- // over this extra fragment fiber and proceed to the next parent.
- var nextParent = parentA.return;
- if (nextParent !== null) {
- a = b = nextParent;
- continue;
- } // If there's no parent, we're at the root.
- break;
- } // If both copies of the parent fiber point to the same child, we can
- // assume that the child is current. This happens when we bailout on low
- // priority: the bailed out fiber's child reuses the current child.
- if (parentA.child === parentB.child) {
- var child = parentA.child;
- while (child) {
- if (child === a) {
- // We've determined that A is the current branch.
- assertIsMounted(parentA);
- return fiber;
- }
- if (child === b) {
- // We've determined that B is the current branch.
- assertIsMounted(parentA);
- return alternate;
- }
- child = child.sibling;
- } // We should never have an alternate for any mounting node. So the only
- // way this could possibly happen is if this was unmounted, if at all.
- throw new Error('Unable to find node on an unmounted component.');
- }
- if (a.return !== b.return) {
- // The return pointer of A and the return pointer of B point to different
- // fibers. We assume that return pointers never criss-cross, so A must
- // belong to the child set of A.return, and B must belong to the child
- // set of B.return.
- a = parentA;
- b = parentB;
- } else {
- // The return pointers point to the same fiber. We'll have to use the
- // default, slow path: scan the child sets of each parent alternate to see
- // which child belongs to which set.
- //
- // Search parent A's child set
- var didFindChild = false;
- var _child = parentA.child;
- while (_child) {
- if (_child === a) {
- didFindChild = true;
- a = parentA;
- b = parentB;
- break;
- }
- if (_child === b) {
- didFindChild = true;
- b = parentA;
- a = parentB;
- break;
- }
- _child = _child.sibling;
- }
- if (!didFindChild) {
- // Search parent B's child set
- _child = parentB.child;
- while (_child) {
- if (_child === a) {
- didFindChild = true;
- a = parentB;
- b = parentA;
- break;
- }
- if (_child === b) {
- didFindChild = true;
- b = parentB;
- a = parentA;
- break;
- }
- _child = _child.sibling;
- }
- if (!didFindChild) {
- throw new Error('Child was not found in either parent set. This indicates a bug ' + 'in React related to the return pointer. Please file an issue.');
- }
- }
- }
- if (a.alternate !== b) {
- throw new Error("Return fibers should always be each others' alternates. " + 'This error is likely caused by a bug in React. Please file an issue.');
- }
- } // If the root is not a host container, we're in a disconnected tree. I.e.
- // unmounted.
- if (a.tag !== HostRoot) {
- throw new Error('Unable to find node on an unmounted component.');
- }
- if (a.stateNode.current === a) {
- // We've determined that A is the current branch.
- return fiber;
- } // Otherwise B has to be current branch.
- return alternate;
- }
- function findCurrentHostFiber(parent) {
- var currentParent = findCurrentFiberUsingSlowPath(parent);
- return currentParent !== null ? findCurrentHostFiberImpl(currentParent) : null;
- }
- function findCurrentHostFiberImpl(node) {
- // Next we'll drill down this component to find the first HostComponent/Text.
- if (node.tag === HostComponent || node.tag === HostText) {
- return node;
- }
- var child = node.child;
- while (child !== null) {
- var match = findCurrentHostFiberImpl(child);
- if (match !== null) {
- return match;
- }
- child = child.sibling;
- }
- return null;
- }
- function findCurrentHostFiberWithNoPortals(parent) {
- var currentParent = findCurrentFiberUsingSlowPath(parent);
- return currentParent !== null ? findCurrentHostFiberWithNoPortalsImpl(currentParent) : null;
- }
- function findCurrentHostFiberWithNoPortalsImpl(node) {
- // Next we'll drill down this component to find the first HostComponent/Text.
- if (node.tag === HostComponent || node.tag === HostText) {
- return node;
- }
- var child = node.child;
- while (child !== null) {
- if (child.tag !== HostPortal) {
- var match = findCurrentHostFiberWithNoPortalsImpl(child);
- if (match !== null) {
- return match;
- }
- }
- child = child.sibling;
- }
- return null;
- }
- // This module only exists as an ESM wrapper around the external CommonJS
- var scheduleCallback = unstable_scheduleCallback;
- var cancelCallback = unstable_cancelCallback;
- var shouldYield = unstable_shouldYield;
- var requestPaint = unstable_requestPaint;
- var now = unstable_now;
- var getCurrentPriorityLevel = unstable_getCurrentPriorityLevel;
- var ImmediatePriority = unstable_ImmediatePriority;
- var UserBlockingPriority = unstable_UserBlockingPriority;
- var NormalPriority = unstable_NormalPriority;
- var LowPriority = unstable_LowPriority;
- var IdlePriority = unstable_IdlePriority;
- // this doesn't actually exist on the scheduler, but it *does*
- // on scheduler/unstable_mock, which we'll need for internal testing
- var unstable_yieldValue$1 = unstable_yieldValue;
- var unstable_setDisableYieldValue$1 = unstable_setDisableYieldValue;
- var rendererID = null;
- var injectedHook = null;
- var injectedProfilingHooks = null;
- var hasLoggedError = false;
- var isDevToolsPresent = typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined';
- function injectInternals(internals) {
- if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') {
- // No DevTools
- return false;
- }
- var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__;
- if (hook.isDisabled) {
- // This isn't a real property on the hook, but it can be set to opt out
- // of DevTools integration and associated warnings and logs.
- // https://github.com/facebook/react/issues/3877
- return true;
- }
- if (!hook.supportsFiber) {
- {
- error('The installed version of React DevTools is too old and will not work ' + 'with the current version of React. Please update React DevTools. ' + 'https://reactjs.org/link/react-devtools');
- } // DevTools exists, even though it doesn't support Fiber.
- return true;
- }
- try {
- if (enableSchedulingProfiler) {
- // Conditionally inject these hooks only if Timeline profiler is supported by this build.
- // This gives DevTools a way to feature detect that isn't tied to version number
- // (since profiling and timeline are controlled by different feature flags).
- internals = assign({}, internals, {
- getLaneLabelMap: getLaneLabelMap,
- injectProfilingHooks: injectProfilingHooks
- });
- }
- rendererID = hook.inject(internals); // We have successfully injected, so now it is safe to set up hooks.
- injectedHook = hook;
- } catch (err) {
- // Catch all errors because it is unsafe to throw during initialization.
- {
- error('React instrumentation encountered an error: %s.', err);
- }
- }
- if (hook.checkDCE) {
- // This is the real DevTools.
- return true;
- } else {
- // This is likely a hook installed by Fast Refresh runtime.
- return false;
- }
- }
- function onScheduleRoot(root, children) {
- {
- if (injectedHook && typeof injectedHook.onScheduleFiberRoot === 'function') {
- try {
- injectedHook.onScheduleFiberRoot(rendererID, root, children);
- } catch (err) {
- if (!hasLoggedError) {
- hasLoggedError = true;
- error('React instrumentation encountered an error: %s', err);
- }
- }
- }
- }
- }
- function onCommitRoot(root, eventPriority) {
- if (injectedHook && typeof injectedHook.onCommitFiberRoot === 'function') {
- try {
- var didError = (root.current.flags & DidCapture) === DidCapture;
- if (enableProfilerTimer) {
- var schedulerPriority;
- switch (eventPriority) {
- case DiscreteEventPriority:
- schedulerPriority = ImmediatePriority;
- break;
- case ContinuousEventPriority:
- schedulerPriority = UserBlockingPriority;
- break;
- case DefaultEventPriority:
- schedulerPriority = NormalPriority;
- break;
- case IdleEventPriority:
- schedulerPriority = IdlePriority;
- break;
- default:
- schedulerPriority = NormalPriority;
- break;
- }
- injectedHook.onCommitFiberRoot(rendererID, root, schedulerPriority, didError);
- } else {
- injectedHook.onCommitFiberRoot(rendererID, root, undefined, didError);
- }
- } catch (err) {
- {
- if (!hasLoggedError) {
- hasLoggedError = true;
- error('React instrumentation encountered an error: %s', err);
- }
- }
- }
- }
- }
- function onPostCommitRoot(root) {
- if (injectedHook && typeof injectedHook.onPostCommitFiberRoot === 'function') {
- try {
- injectedHook.onPostCommitFiberRoot(rendererID, root);
- } catch (err) {
- {
- if (!hasLoggedError) {
- hasLoggedError = true;
- error('React instrumentation encountered an error: %s', err);
- }
- }
- }
- }
- }
- function onCommitUnmount(fiber) {
- if (injectedHook && typeof injectedHook.onCommitFiberUnmount === 'function') {
- try {
- injectedHook.onCommitFiberUnmount(rendererID, fiber);
- } catch (err) {
- {
- if (!hasLoggedError) {
- hasLoggedError = true;
- error('React instrumentation encountered an error: %s', err);
- }
- }
- }
- }
- }
- function setIsStrictModeForDevtools(newIsStrictMode) {
- {
- if (typeof unstable_yieldValue$1 === 'function') {
- // We're in a test because Scheduler.unstable_yieldValue only exists
- // in SchedulerMock. To reduce the noise in strict mode tests,
- // suppress warnings and disable scheduler yielding during the double render
- unstable_setDisableYieldValue$1(newIsStrictMode);
- setSuppressWarning(newIsStrictMode);
- }
- if (injectedHook && typeof injectedHook.setStrictMode === 'function') {
- try {
- injectedHook.setStrictMode(rendererID, newIsStrictMode);
- } catch (err) {
- {
- if (!hasLoggedError) {
- hasLoggedError = true;
- error('React instrumentation encountered an error: %s', err);
- }
- }
- }
- }
- }
- } // Profiler API hooks
- function injectProfilingHooks(profilingHooks) {
- injectedProfilingHooks = profilingHooks;
- }
- function getLaneLabelMap() {
- {
- var map = new Map();
- var lane = 1;
- for (var index = 0; index < TotalLanes; index++) {
- var label = getLabelForLane(lane);
- map.set(lane, label);
- lane *= 2;
- }
- return map;
- }
- }
- function markCommitStarted(lanes) {
- {
- if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markCommitStarted === 'function') {
- injectedProfilingHooks.markCommitStarted(lanes);
- }
- }
- }
- function markCommitStopped() {
- {
- if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markCommitStopped === 'function') {
- injectedProfilingHooks.markCommitStopped();
- }
- }
- }
- function markComponentRenderStarted(fiber) {
- {
- if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentRenderStarted === 'function') {
- injectedProfilingHooks.markComponentRenderStarted(fiber);
- }
- }
- }
- function markComponentRenderStopped() {
- {
- if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentRenderStopped === 'function') {
- injectedProfilingHooks.markComponentRenderStopped();
- }
- }
- }
- function markComponentPassiveEffectMountStarted(fiber) {
- {
- if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentPassiveEffectMountStarted === 'function') {
- injectedProfilingHooks.markComponentPassiveEffectMountStarted(fiber);
- }
- }
- }
- function markComponentPassiveEffectMountStopped() {
- {
- if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentPassiveEffectMountStopped === 'function') {
- injectedProfilingHooks.markComponentPassiveEffectMountStopped();
- }
- }
- }
- function markComponentPassiveEffectUnmountStarted(fiber) {
- {
- if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentPassiveEffectUnmountStarted === 'function') {
- injectedProfilingHooks.markComponentPassiveEffectUnmountStarted(fiber);
- }
- }
- }
- function markComponentPassiveEffectUnmountStopped() {
- {
- if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentPassiveEffectUnmountStopped === 'function') {
- injectedProfilingHooks.markComponentPassiveEffectUnmountStopped();
- }
- }
- }
- function markComponentLayoutEffectMountStarted(fiber) {
- {
- if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentLayoutEffectMountStarted === 'function') {
- injectedProfilingHooks.markComponentLayoutEffectMountStarted(fiber);
- }
- }
- }
- function markComponentLayoutEffectMountStopped() {
- {
- if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentLayoutEffectMountStopped === 'function') {
- injectedProfilingHooks.markComponentLayoutEffectMountStopped();
- }
- }
- }
- function markComponentLayoutEffectUnmountStarted(fiber) {
- {
- if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentLayoutEffectUnmountStarted === 'function') {
- injectedProfilingHooks.markComponentLayoutEffectUnmountStarted(fiber);
- }
- }
- }
- function markComponentLayoutEffectUnmountStopped() {
- {
- if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentLayoutEffectUnmountStopped === 'function') {
- injectedProfilingHooks.markComponentLayoutEffectUnmountStopped();
- }
- }
- }
- function markComponentErrored(fiber, thrownValue, lanes) {
- {
- if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentErrored === 'function') {
- injectedProfilingHooks.markComponentErrored(fiber, thrownValue, lanes);
- }
- }
- }
- function markComponentSuspended(fiber, wakeable, lanes) {
- {
- if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentSuspended === 'function') {
- injectedProfilingHooks.markComponentSuspended(fiber, wakeable, lanes);
- }
- }
- }
- function markLayoutEffectsStarted(lanes) {
- {
- if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markLayoutEffectsStarted === 'function') {
- injectedProfilingHooks.markLayoutEffectsStarted(lanes);
- }
- }
- }
- function markLayoutEffectsStopped() {
- {
- if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markLayoutEffectsStopped === 'function') {
- injectedProfilingHooks.markLayoutEffectsStopped();
- }
- }
- }
- function markPassiveEffectsStarted(lanes) {
- {
- if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markPassiveEffectsStarted === 'function') {
- injectedProfilingHooks.markPassiveEffectsStarted(lanes);
- }
- }
- }
- function markPassiveEffectsStopped() {
- {
- if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markPassiveEffectsStopped === 'function') {
- injectedProfilingHooks.markPassiveEffectsStopped();
- }
- }
- }
- function markRenderStarted(lanes) {
- {
- if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markRenderStarted === 'function') {
- injectedProfilingHooks.markRenderStarted(lanes);
- }
- }
- }
- function markRenderYielded() {
- {
- if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markRenderYielded === 'function') {
- injectedProfilingHooks.markRenderYielded();
- }
- }
- }
- function markRenderStopped() {
- {
- if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markRenderStopped === 'function') {
- injectedProfilingHooks.markRenderStopped();
- }
- }
- }
- function markRenderScheduled(lane) {
- {
- if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markRenderScheduled === 'function') {
- injectedProfilingHooks.markRenderScheduled(lane);
- }
- }
- }
- function markForceUpdateScheduled(fiber, lane) {
- {
- if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markForceUpdateScheduled === 'function') {
- injectedProfilingHooks.markForceUpdateScheduled(fiber, lane);
- }
- }
- }
- function markStateUpdateScheduled(fiber, lane) {
- {
- if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markStateUpdateScheduled === 'function') {
- injectedProfilingHooks.markStateUpdateScheduled(fiber, lane);
- }
- }
- }
- var NoMode =
- /* */
- 0; // TODO: Remove ConcurrentMode by reading from the root tag instead
- var ConcurrentMode =
- /* */
- 1;
- var ProfileMode =
- /* */
- 2;
- var StrictLegacyMode =
- /* */
- 8;
- var StrictEffectsMode =
- /* */
- 16;
- // TODO: This is pretty well supported by browsers. Maybe we can drop it.
- var clz32 = Math.clz32 ? Math.clz32 : clz32Fallback; // Count leading zeros.
- // Based on:
- // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32
- var log = Math.log;
- var LN2 = Math.LN2;
- function clz32Fallback(x) {
- var asUint = x >>> 0;
- if (asUint === 0) {
- return 32;
- }
- return 31 - (log(asUint) / LN2 | 0) | 0;
- }
- // If those values are changed that package should be rebuilt and redeployed.
- var TotalLanes = 31;
- var NoLanes =
- /* */
- 0;
- var NoLane =
- /* */
- 0;
- var SyncLane =
- /* */
- 1;
- var InputContinuousHydrationLane =
- /* */
- 2;
- var InputContinuousLane =
- /* */
- 4;
- var DefaultHydrationLane =
- /* */
- 8;
- var DefaultLane =
- /* */
- 16;
- var TransitionHydrationLane =
- /* */
- 32;
- var TransitionLanes =
- /* */
- 4194240;
- var TransitionLane1 =
- /* */
- 64;
- var TransitionLane2 =
- /* */
- 128;
- var TransitionLane3 =
- /* */
- 256;
- var TransitionLane4 =
- /* */
- 512;
- var TransitionLane5 =
- /* */
- 1024;
- var TransitionLane6 =
- /* */
- 2048;
- var TransitionLane7 =
- /* */
- 4096;
- var TransitionLane8 =
- /* */
- 8192;
- var TransitionLane9 =
- /* */
- 16384;
- var TransitionLane10 =
- /* */
- 32768;
- var TransitionLane11 =
- /* */
- 65536;
- var TransitionLane12 =
- /* */
- 131072;
- var TransitionLane13 =
- /* */
- 262144;
- var TransitionLane14 =
- /* */
- 524288;
- var TransitionLane15 =
- /* */
- 1048576;
- var TransitionLane16 =
- /* */
- 2097152;
- var RetryLanes =
- /* */
- 130023424;
- var RetryLane1 =
- /* */
- 4194304;
- var RetryLane2 =
- /* */
- 8388608;
- var RetryLane3 =
- /* */
- 16777216;
- var RetryLane4 =
- /* */
- 33554432;
- var RetryLane5 =
- /* */
- 67108864;
- var SomeRetryLane = RetryLane1;
- var SelectiveHydrationLane =
- /* */
- 134217728;
- var NonIdleLanes =
- /* */
- 268435455;
- var IdleHydrationLane =
- /* */
- 268435456;
- var IdleLane =
- /* */
- 536870912;
- var OffscreenLane =
- /* */
- 1073741824; // This function is used for the experimental timeline (react-devtools-timeline)
- // It should be kept in sync with the Lanes values above.
- function getLabelForLane(lane) {
- {
- if (lane & SyncLane) {
- return 'Sync';
- }
- if (lane & InputContinuousHydrationLane) {
- return 'InputContinuousHydration';
- }
- if (lane & InputContinuousLane) {
- return 'InputContinuous';
- }
- if (lane & DefaultHydrationLane) {
- return 'DefaultHydration';
- }
- if (lane & DefaultLane) {
- return 'Default';
- }
- if (lane & TransitionHydrationLane) {
- return 'TransitionHydration';
- }
- if (lane & TransitionLanes) {
- return 'Transition';
- }
- if (lane & RetryLanes) {
- return 'Retry';
- }
- if (lane & SelectiveHydrationLane) {
- return 'SelectiveHydration';
- }
- if (lane & IdleHydrationLane) {
- return 'IdleHydration';
- }
- if (lane & IdleLane) {
- return 'Idle';
- }
- if (lane & OffscreenLane) {
- return 'Offscreen';
- }
- }
- }
- var NoTimestamp = -1;
- var nextTransitionLane = TransitionLane1;
- var nextRetryLane = RetryLane1;
- function getHighestPriorityLanes(lanes) {
- switch (getHighestPriorityLane(lanes)) {
- case SyncLane:
- return SyncLane;
- case InputContinuousHydrationLane:
- return InputContinuousHydrationLane;
- case InputContinuousLane:
- return InputContinuousLane;
- case DefaultHydrationLane:
- return DefaultHydrationLane;
- case DefaultLane:
- return DefaultLane;
- case TransitionHydrationLane:
- return TransitionHydrationLane;
- case TransitionLane1:
- case TransitionLane2:
- case TransitionLane3:
- case TransitionLane4:
- case TransitionLane5:
- case TransitionLane6:
- case TransitionLane7:
- case TransitionLane8:
- case TransitionLane9:
- case TransitionLane10:
- case TransitionLane11:
- case TransitionLane12:
- case TransitionLane13:
- case TransitionLane14:
- case TransitionLane15:
- case TransitionLane16:
- return lanes & TransitionLanes;
- case RetryLane1:
- case RetryLane2:
- case RetryLane3:
- case RetryLane4:
- case RetryLane5:
- return lanes & RetryLanes;
- case SelectiveHydrationLane:
- return SelectiveHydrationLane;
- case IdleHydrationLane:
- return IdleHydrationLane;
- case IdleLane:
- return IdleLane;
- case OffscreenLane:
- return OffscreenLane;
- default:
- {
- error('Should have found matching lanes. This is a bug in React.');
- } // This shouldn't be reachable, but as a fallback, return the entire bitmask.
- return lanes;
- }
- }
- function getNextLanes(root, wipLanes) {
- // Early bailout if there's no pending work left.
- var pendingLanes = root.pendingLanes;
- if (pendingLanes === NoLanes) {
- return NoLanes;
- }
- var nextLanes = NoLanes;
- var suspendedLanes = root.suspendedLanes;
- var pingedLanes = root.pingedLanes; // Do not work on any idle work until all the non-idle work has finished,
- // even if the work is suspended.
- var nonIdlePendingLanes = pendingLanes & NonIdleLanes;
- if (nonIdlePendingLanes !== NoLanes) {
- var nonIdleUnblockedLanes = nonIdlePendingLanes & ~suspendedLanes;
- if (nonIdleUnblockedLanes !== NoLanes) {
- nextLanes = getHighestPriorityLanes(nonIdleUnblockedLanes);
- } else {
- var nonIdlePingedLanes = nonIdlePendingLanes & pingedLanes;
- if (nonIdlePingedLanes !== NoLanes) {
- nextLanes = getHighestPriorityLanes(nonIdlePingedLanes);
- }
- }
- } else {
- // The only remaining work is Idle.
- var unblockedLanes = pendingLanes & ~suspendedLanes;
- if (unblockedLanes !== NoLanes) {
- nextLanes = getHighestPriorityLanes(unblockedLanes);
- } else {
- if (pingedLanes !== NoLanes) {
- nextLanes = getHighestPriorityLanes(pingedLanes);
- }
- }
- }
- if (nextLanes === NoLanes) {
- // This should only be reachable if we're suspended
- // TODO: Consider warning in this path if a fallback timer is not scheduled.
- return NoLanes;
- } // If we're already in the middle of a render, switching lanes will interrupt
- // it and we'll lose our progress. We should only do this if the new lanes are
- // higher priority.
- if (wipLanes !== NoLanes && wipLanes !== nextLanes && // If we already suspended with a delay, then interrupting is fine. Don't
- // bother waiting until the root is complete.
- (wipLanes & suspendedLanes) === NoLanes) {
- var nextLane = getHighestPriorityLane(nextLanes);
- var wipLane = getHighestPriorityLane(wipLanes);
- if ( // Tests whether the next lane is equal or lower priority than the wip
- // one. This works because the bits decrease in priority as you go left.
- nextLane >= wipLane || // Default priority updates should not interrupt transition updates. The
- // only difference between default updates and transition updates is that
- // default updates do not support refresh transitions.
- nextLane === DefaultLane && (wipLane & TransitionLanes) !== NoLanes) {
- // Keep working on the existing in-progress tree. Do not interrupt.
- return wipLanes;
- }
- }
- if ((nextLanes & InputContinuousLane) !== NoLanes) {
- // When updates are sync by default, we entangle continuous priority updates
- // and default updates, so they render in the same batch. The only reason
- // they use separate lanes is because continuous updates should interrupt
- // transitions, but default updates should not.
- nextLanes |= pendingLanes & DefaultLane;
- } // Check for entangled lanes and add them to the batch.
- //
- // A lane is said to be entangled with another when it's not allowed to render
- // in a batch that does not also include the other lane. Typically we do this
- // when multiple updates have the same source, and we only want to respond to
- // the most recent event from that source.
- //
- // Note that we apply entanglements *after* checking for partial work above.
- // This means that if a lane is entangled during an interleaved event while
- // it's already rendering, we won't interrupt it. This is intentional, since
- // entanglement is usually "best effort": we'll try our best to render the
- // lanes in the same batch, but it's not worth throwing out partially
- // completed work in order to do it.
- // TODO: Reconsider this. The counter-argument is that the partial work
- // represents an intermediate state, which we don't want to show to the user.
- // And by spending extra time finishing it, we're increasing the amount of
- // time it takes to show the final state, which is what they are actually
- // waiting for.
- //
- // For those exceptions where entanglement is semantically important, like
- // useMutableSource, we should ensure that there is no partial work at the
- // time we apply the entanglement.
- var entangledLanes = root.entangledLanes;
- if (entangledLanes !== NoLanes) {
- var entanglements = root.entanglements;
- var lanes = nextLanes & entangledLanes;
- while (lanes > 0) {
- var index = pickArbitraryLaneIndex(lanes);
- var lane = 1 << index;
- nextLanes |= entanglements[index];
- lanes &= ~lane;
- }
- }
- return nextLanes;
- }
- function getMostRecentEventTime(root, lanes) {
- var eventTimes = root.eventTimes;
- var mostRecentEventTime = NoTimestamp;
- while (lanes > 0) {
- var index = pickArbitraryLaneIndex(lanes);
- var lane = 1 << index;
- var eventTime = eventTimes[index];
- if (eventTime > mostRecentEventTime) {
- mostRecentEventTime = eventTime;
- }
- lanes &= ~lane;
- }
- return mostRecentEventTime;
- }
- function computeExpirationTime(lane, currentTime) {
- switch (lane) {
- case SyncLane:
- case InputContinuousHydrationLane:
- case InputContinuousLane:
- // User interactions should expire slightly more quickly.
- //
- // NOTE: This is set to the corresponding constant as in Scheduler.js.
- // When we made it larger, a product metric in www regressed, suggesting
- // there's a user interaction that's being starved by a series of
- // synchronous updates. If that theory is correct, the proper solution is
- // to fix the starvation. However, this scenario supports the idea that
- // expiration times are an important safeguard when starvation
- // does happen.
- return currentTime + 250;
- case DefaultHydrationLane:
- case DefaultLane:
- case TransitionHydrationLane:
- case TransitionLane1:
- case TransitionLane2:
- case TransitionLane3:
- case TransitionLane4:
- case TransitionLane5:
- case TransitionLane6:
- case TransitionLane7:
- case TransitionLane8:
- case TransitionLane9:
- case TransitionLane10:
- case TransitionLane11:
- case TransitionLane12:
- case TransitionLane13:
- case TransitionLane14:
- case TransitionLane15:
- case TransitionLane16:
- return currentTime + 5000;
- case RetryLane1:
- case RetryLane2:
- case RetryLane3:
- case RetryLane4:
- case RetryLane5:
- // TODO: Retries should be allowed to expire if they are CPU bound for
- // too long, but when I made this change it caused a spike in browser
- // crashes. There must be some other underlying bug; not super urgent but
- // ideally should figure out why and fix it. Unfortunately we don't have
- // a repro for the crashes, only detected via production metrics.
- return NoTimestamp;
- case SelectiveHydrationLane:
- case IdleHydrationLane:
- case IdleLane:
- case OffscreenLane:
- // Anything idle priority or lower should never expire.
- return NoTimestamp;
- default:
- {
- error('Should have found matching lanes. This is a bug in React.');
- }
- return NoTimestamp;
- }
- }
- function markStarvedLanesAsExpired(root, currentTime) {
- // TODO: This gets called every time we yield. We can optimize by storing
- // the earliest expiration time on the root. Then use that to quickly bail out
- // of this function.
- var pendingLanes = root.pendingLanes;
- var suspendedLanes = root.suspendedLanes;
- var pingedLanes = root.pingedLanes;
- var expirationTimes = root.expirationTimes; // Iterate through the pending lanes and check if we've reached their
- // expiration time. If so, we'll assume the update is being starved and mark
- // it as expired to force it to finish.
- var lanes = pendingLanes;
- while (lanes > 0) {
- var index = pickArbitraryLaneIndex(lanes);
- var lane = 1 << index;
- var expirationTime = expirationTimes[index];
- if (expirationTime === NoTimestamp) {
- // Found a pending lane with no expiration time. If it's not suspended, or
- // if it's pinged, assume it's CPU-bound. Compute a new expiration time
- // using the current time.
- if ((lane & suspendedLanes) === NoLanes || (lane & pingedLanes) !== NoLanes) {
- // Assumes timestamps are monotonically increasing.
- expirationTimes[index] = computeExpirationTime(lane, currentTime);
- }
- } else if (expirationTime <= currentTime) {
- // This lane expired
- root.expiredLanes |= lane;
- }
- lanes &= ~lane;
- }
- } // This returns the highest priority pending lanes regardless of whether they
- // are suspended.
- function getHighestPriorityPendingLanes(root) {
- return getHighestPriorityLanes(root.pendingLanes);
- }
- function getLanesToRetrySynchronouslyOnError(root) {
- var everythingButOffscreen = root.pendingLanes & ~OffscreenLane;
- if (everythingButOffscreen !== NoLanes) {
- return everythingButOffscreen;
- }
- if (everythingButOffscreen & OffscreenLane) {
- return OffscreenLane;
- }
- return NoLanes;
- }
- function includesSyncLane(lanes) {
- return (lanes & SyncLane) !== NoLanes;
- }
- function includesNonIdleWork(lanes) {
- return (lanes & NonIdleLanes) !== NoLanes;
- }
- function includesOnlyRetries(lanes) {
- return (lanes & RetryLanes) === lanes;
- }
- function includesOnlyNonUrgentLanes(lanes) {
- var UrgentLanes = SyncLane | InputContinuousLane | DefaultLane;
- return (lanes & UrgentLanes) === NoLanes;
- }
- function includesOnlyTransitions(lanes) {
- return (lanes & TransitionLanes) === lanes;
- }
- function includesBlockingLane(root, lanes) {
- var SyncDefaultLanes = InputContinuousHydrationLane | InputContinuousLane | DefaultHydrationLane | DefaultLane;
- return (lanes & SyncDefaultLanes) !== NoLanes;
- }
- function includesExpiredLane(root, lanes) {
- // This is a separate check from includesBlockingLane because a lane can
- // expire after a render has already started.
- return (lanes & root.expiredLanes) !== NoLanes;
- }
- function isTransitionLane(lane) {
- return (lane & TransitionLanes) !== NoLanes;
- }
- function claimNextTransitionLane() {
- // Cycle through the lanes, assigning each new transition to the next lane.
- // In most cases, this means every transition gets its own lane, until we
- // run out of lanes and cycle back to the beginning.
- var lane = nextTransitionLane;
- nextTransitionLane <<= 1;
- if ((nextTransitionLane & TransitionLanes) === NoLanes) {
- nextTransitionLane = TransitionLane1;
- }
- return lane;
- }
- function claimNextRetryLane() {
- var lane = nextRetryLane;
- nextRetryLane <<= 1;
- if ((nextRetryLane & RetryLanes) === NoLanes) {
- nextRetryLane = RetryLane1;
- }
- return lane;
- }
- function getHighestPriorityLane(lanes) {
- return lanes & -lanes;
- }
- function pickArbitraryLane(lanes) {
- // This wrapper function gets inlined. Only exists so to communicate that it
- // doesn't matter which bit is selected; you can pick any bit without
- // affecting the algorithms where its used. Here I'm using
- // getHighestPriorityLane because it requires the fewest operations.
- return getHighestPriorityLane(lanes);
- }
- function pickArbitraryLaneIndex(lanes) {
- return 31 - clz32(lanes);
- }
- function laneToIndex(lane) {
- return pickArbitraryLaneIndex(lane);
- }
- function includesSomeLane(a, b) {
- return (a & b) !== NoLanes;
- }
- function isSubsetOfLanes(set, subset) {
- return (set & subset) === subset;
- }
- function mergeLanes(a, b) {
- return a | b;
- }
- function removeLanes(set, subset) {
- return set & ~subset;
- }
- function intersectLanes(a, b) {
- return a & b;
- } // Seems redundant, but it changes the type from a single lane (used for
- // updates) to a group of lanes (used for flushing work).
- function laneToLanes(lane) {
- return lane;
- }
- function higherPriorityLane(a, b) {
- // This works because the bit ranges decrease in priority as you go left.
- return a !== NoLane && a < b ? a : b;
- }
- function createLaneMap(initial) {
- // Intentionally pushing one by one.
- // https://v8.dev/blog/elements-kinds#avoid-creating-holes
- var laneMap = [];
- for (var i = 0; i < TotalLanes; i++) {
- laneMap.push(initial);
- }
- return laneMap;
- }
- function markRootUpdated(root, updateLane, eventTime) {
- root.pendingLanes |= updateLane; // If there are any suspended transitions, it's possible this new update
- // could unblock them. Clear the suspended lanes so that we can try rendering
- // them again.
- //
- // TODO: We really only need to unsuspend only lanes that are in the
- // `subtreeLanes` of the updated fiber, or the update lanes of the return
- // path. This would exclude suspended updates in an unrelated sibling tree,
- // since there's no way for this update to unblock it.
- //
- // We don't do this if the incoming update is idle, because we never process
- // idle updates until after all the regular updates have finished; there's no
- // way it could unblock a transition.
- if (updateLane !== IdleLane) {
- root.suspendedLanes = NoLanes;
- root.pingedLanes = NoLanes;
- }
- var eventTimes = root.eventTimes;
- var index = laneToIndex(updateLane); // We can always overwrite an existing timestamp because we prefer the most
- // recent event, and we assume time is monotonically increasing.
- eventTimes[index] = eventTime;
- }
- function markRootSuspended(root, suspendedLanes) {
- root.suspendedLanes |= suspendedLanes;
- root.pingedLanes &= ~suspendedLanes; // The suspended lanes are no longer CPU-bound. Clear their expiration times.
- var expirationTimes = root.expirationTimes;
- var lanes = suspendedLanes;
- while (lanes > 0) {
- var index = pickArbitraryLaneIndex(lanes);
- var lane = 1 << index;
- expirationTimes[index] = NoTimestamp;
- lanes &= ~lane;
- }
- }
- function markRootPinged(root, pingedLanes, eventTime) {
- root.pingedLanes |= root.suspendedLanes & pingedLanes;
- }
- function markRootFinished(root, remainingLanes) {
- var noLongerPendingLanes = root.pendingLanes & ~remainingLanes;
- root.pendingLanes = remainingLanes; // Let's try everything again
- root.suspendedLanes = NoLanes;
- root.pingedLanes = NoLanes;
- root.expiredLanes &= remainingLanes;
- root.mutableReadLanes &= remainingLanes;
- root.entangledLanes &= remainingLanes;
- var entanglements = root.entanglements;
- var eventTimes = root.eventTimes;
- var expirationTimes = root.expirationTimes; // Clear the lanes that no longer have pending work
- var lanes = noLongerPendingLanes;
- while (lanes > 0) {
- var index = pickArbitraryLaneIndex(lanes);
- var lane = 1 << index;
- entanglements[index] = NoLanes;
- eventTimes[index] = NoTimestamp;
- expirationTimes[index] = NoTimestamp;
- lanes &= ~lane;
- }
- }
- function markRootEntangled(root, entangledLanes) {
- // In addition to entangling each of the given lanes with each other, we also
- // have to consider _transitive_ entanglements. For each lane that is already
- // entangled with *any* of the given lanes, that lane is now transitively
- // entangled with *all* the given lanes.
- //
- // Translated: If C is entangled with A, then entangling A with B also
- // entangles C with B.
- //
- // If this is hard to grasp, it might help to intentionally break this
- // function and look at the tests that fail in ReactTransition-test.js. Try
- // commenting out one of the conditions below.
- var rootEntangledLanes = root.entangledLanes |= entangledLanes;
- var entanglements = root.entanglements;
- var lanes = rootEntangledLanes;
- while (lanes) {
- var index = pickArbitraryLaneIndex(lanes);
- var lane = 1 << index;
- if ( // Is this one of the newly entangled lanes?
- lane & entangledLanes | // Is this lane transitively entangled with the newly entangled lanes?
- entanglements[index] & entangledLanes) {
- entanglements[index] |= entangledLanes;
- }
- lanes &= ~lane;
- }
- }
- function getBumpedLaneForHydration(root, renderLanes) {
- var renderLane = getHighestPriorityLane(renderLanes);
- var lane;
- switch (renderLane) {
- case InputContinuousLane:
- lane = InputContinuousHydrationLane;
- break;
- case DefaultLane:
- lane = DefaultHydrationLane;
- break;
- case TransitionLane1:
- case TransitionLane2:
- case TransitionLane3:
- case TransitionLane4:
- case TransitionLane5:
- case TransitionLane6:
- case TransitionLane7:
- case TransitionLane8:
- case TransitionLane9:
- case TransitionLane10:
- case TransitionLane11:
- case TransitionLane12:
- case TransitionLane13:
- case TransitionLane14:
- case TransitionLane15:
- case TransitionLane16:
- case RetryLane1:
- case RetryLane2:
- case RetryLane3:
- case RetryLane4:
- case RetryLane5:
- lane = TransitionHydrationLane;
- break;
- case IdleLane:
- lane = IdleHydrationLane;
- break;
- default:
- // Everything else is already either a hydration lane, or shouldn't
- // be retried at a hydration lane.
- lane = NoLane;
- break;
- } // Check if the lane we chose is suspended. If so, that indicates that we
- // already attempted and failed to hydrate at that level. Also check if we're
- // already rendering that lane, which is rare but could happen.
- if ((lane & (root.suspendedLanes | renderLanes)) !== NoLane) {
- // Give up trying to hydrate and fall back to client render.
- return NoLane;
- }
- return lane;
- }
- function addFiberToLanesMap(root, fiber, lanes) {
- if (!isDevToolsPresent) {
- return;
- }
- var pendingUpdatersLaneMap = root.pendingUpdatersLaneMap;
- while (lanes > 0) {
- var index = laneToIndex(lanes);
- var lane = 1 << index;
- var updaters = pendingUpdatersLaneMap[index];
- updaters.add(fiber);
- lanes &= ~lane;
- }
- }
- function movePendingFibersToMemoized(root, lanes) {
- if (!isDevToolsPresent) {
- return;
- }
- var pendingUpdatersLaneMap = root.pendingUpdatersLaneMap;
- var memoizedUpdaters = root.memoizedUpdaters;
- while (lanes > 0) {
- var index = laneToIndex(lanes);
- var lane = 1 << index;
- var updaters = pendingUpdatersLaneMap[index];
- if (updaters.size > 0) {
- updaters.forEach(function (fiber) {
- var alternate = fiber.alternate;
- if (alternate === null || !memoizedUpdaters.has(alternate)) {
- memoizedUpdaters.add(fiber);
- }
- });
- updaters.clear();
- }
- lanes &= ~lane;
- }
- }
- function getTransitionsForLanes(root, lanes) {
- {
- return null;
- }
- }
- var DiscreteEventPriority = SyncLane;
- var ContinuousEventPriority = InputContinuousLane;
- var DefaultEventPriority = DefaultLane;
- var IdleEventPriority = IdleLane;
- var currentUpdatePriority = NoLane;
- function getCurrentUpdatePriority() {
- return currentUpdatePriority;
- }
- function setCurrentUpdatePriority(newPriority) {
- currentUpdatePriority = newPriority;
- }
- function runWithPriority(priority, fn) {
- var previousPriority = currentUpdatePriority;
- try {
- currentUpdatePriority = priority;
- return fn();
- } finally {
- currentUpdatePriority = previousPriority;
- }
- }
- function higherEventPriority(a, b) {
- return a !== 0 && a < b ? a : b;
- }
- function lowerEventPriority(a, b) {
- return a === 0 || a > b ? a : b;
- }
- function isHigherEventPriority(a, b) {
- return a !== 0 && a < b;
- }
- function lanesToEventPriority(lanes) {
- var lane = getHighestPriorityLane(lanes);
- if (!isHigherEventPriority(DiscreteEventPriority, lane)) {
- return DiscreteEventPriority;
- }
- if (!isHigherEventPriority(ContinuousEventPriority, lane)) {
- return ContinuousEventPriority;
- }
- if (includesNonIdleWork(lane)) {
- return DefaultEventPriority;
- }
- return IdleEventPriority;
- }
- // This is imported by the event replaying implementation in React DOM. It's
- // in a separate file to break a circular dependency between the renderer and
- // the reconciler.
- function isRootDehydrated(root) {
- var currentState = root.current.memoizedState;
- return currentState.isDehydrated;
- }
- var _attemptSynchronousHydration;
- function setAttemptSynchronousHydration(fn) {
- _attemptSynchronousHydration = fn;
- }
- function attemptSynchronousHydration(fiber) {
- _attemptSynchronousHydration(fiber);
- }
- var attemptContinuousHydration;
- function setAttemptContinuousHydration(fn) {
- attemptContinuousHydration = fn;
- }
- var attemptHydrationAtCurrentPriority;
- function setAttemptHydrationAtCurrentPriority(fn) {
- attemptHydrationAtCurrentPriority = fn;
- }
- var getCurrentUpdatePriority$1;
- function setGetCurrentUpdatePriority(fn) {
- getCurrentUpdatePriority$1 = fn;
- }
- var attemptHydrationAtPriority;
- function setAttemptHydrationAtPriority(fn) {
- attemptHydrationAtPriority = fn;
- } // TODO: Upgrade this definition once we're on a newer version of Flow that
- // has this definition built-in.
- var hasScheduledReplayAttempt = false; // The queue of discrete events to be replayed.
- var queuedDiscreteEvents = []; // Indicates if any continuous event targets are non-null for early bailout.
- // if the last target was dehydrated.
- var queuedFocus = null;
- var queuedDrag = null;
- var queuedMouse = null; // For pointer events there can be one latest event per pointerId.
- var queuedPointers = new Map();
- var queuedPointerCaptures = new Map(); // We could consider replaying selectionchange and touchmoves too.
- var queuedExplicitHydrationTargets = [];
- var discreteReplayableEvents = ['mousedown', 'mouseup', 'touchcancel', 'touchend', 'touchstart', 'auxclick', 'dblclick', 'pointercancel', 'pointerdown', 'pointerup', 'dragend', 'dragstart', 'drop', 'compositionend', 'compositionstart', 'keydown', 'keypress', 'keyup', 'input', 'textInput', // Intentionally camelCase
- 'copy', 'cut', 'paste', 'click', 'change', 'contextmenu', 'reset', 'submit'];
- function isDiscreteEventThatRequiresHydration(eventType) {
- return discreteReplayableEvents.indexOf(eventType) > -1;
- }
- function createQueuedReplayableEvent(blockedOn, domEventName, eventSystemFlags, targetContainer, nativeEvent) {
- return {
- blockedOn: blockedOn,
- domEventName: domEventName,
- eventSystemFlags: eventSystemFlags,
- nativeEvent: nativeEvent,
- targetContainers: [targetContainer]
- };
- }
- function clearIfContinuousEvent(domEventName, nativeEvent) {
- switch (domEventName) {
- case 'focusin':
- case 'focusout':
- queuedFocus = null;
- break;
- case 'dragenter':
- case 'dragleave':
- queuedDrag = null;
- break;
- case 'mouseover':
- case 'mouseout':
- queuedMouse = null;
- break;
- case 'pointerover':
- case 'pointerout':
- {
- var pointerId = nativeEvent.pointerId;
- queuedPointers.delete(pointerId);
- break;
- }
- case 'gotpointercapture':
- case 'lostpointercapture':
- {
- var _pointerId = nativeEvent.pointerId;
- queuedPointerCaptures.delete(_pointerId);
- break;
- }
- }
- }
- function accumulateOrCreateContinuousQueuedReplayableEvent(existingQueuedEvent, blockedOn, domEventName, eventSystemFlags, targetContainer, nativeEvent) {
- if (existingQueuedEvent === null || existingQueuedEvent.nativeEvent !== nativeEvent) {
- var queuedEvent = createQueuedReplayableEvent(blockedOn, domEventName, eventSystemFlags, targetContainer, nativeEvent);
- if (blockedOn !== null) {
- var _fiber2 = getInstanceFromNode(blockedOn);
- if (_fiber2 !== null) {
- // Attempt to increase the priority of this target.
- attemptContinuousHydration(_fiber2);
- }
- }
- return queuedEvent;
- } // If we have already queued this exact event, then it's because
- // the different event systems have different DOM event listeners.
- // We can accumulate the flags, and the targetContainers, and
- // store a single event to be replayed.
- existingQueuedEvent.eventSystemFlags |= eventSystemFlags;
- var targetContainers = existingQueuedEvent.targetContainers;
- if (targetContainer !== null && targetContainers.indexOf(targetContainer) === -1) {
- targetContainers.push(targetContainer);
- }
- return existingQueuedEvent;
- }
- function queueIfContinuousEvent(blockedOn, domEventName, eventSystemFlags, targetContainer, nativeEvent) {
- // These set relatedTarget to null because the replayed event will be treated as if we
- // moved from outside the window (no target) onto the target once it hydrates.
- // Instead of mutating we could clone the event.
- switch (domEventName) {
- case 'focusin':
- {
- var focusEvent = nativeEvent;
- queuedFocus = accumulateOrCreateContinuousQueuedReplayableEvent(queuedFocus, blockedOn, domEventName, eventSystemFlags, targetContainer, focusEvent);
- return true;
- }
- case 'dragenter':
- {
- var dragEvent = nativeEvent;
- queuedDrag = accumulateOrCreateContinuousQueuedReplayableEvent(queuedDrag, blockedOn, domEventName, eventSystemFlags, targetContainer, dragEvent);
- return true;
- }
- case 'mouseover':
- {
- var mouseEvent = nativeEvent;
- queuedMouse = accumulateOrCreateContinuousQueuedReplayableEvent(queuedMouse, blockedOn, domEventName, eventSystemFlags, targetContainer, mouseEvent);
- return true;
- }
- case 'pointerover':
- {
- var pointerEvent = nativeEvent;
- var pointerId = pointerEvent.pointerId;
- queuedPointers.set(pointerId, accumulateOrCreateContinuousQueuedReplayableEvent(queuedPointers.get(pointerId) || null, blockedOn, domEventName, eventSystemFlags, targetContainer, pointerEvent));
- return true;
- }
- case 'gotpointercapture':
- {
- var _pointerEvent = nativeEvent;
- var _pointerId2 = _pointerEvent.pointerId;
- queuedPointerCaptures.set(_pointerId2, accumulateOrCreateContinuousQueuedReplayableEvent(queuedPointerCaptures.get(_pointerId2) || null, blockedOn, domEventName, eventSystemFlags, targetContainer, _pointerEvent));
- return true;
- }
- }
- return false;
- } // Check if this target is unblocked. Returns true if it's unblocked.
- function attemptExplicitHydrationTarget(queuedTarget) {
- // TODO: This function shares a lot of logic with findInstanceBlockingEvent.
- // Try to unify them. It's a bit tricky since it would require two return
- // values.
- var targetInst = getClosestInstanceFromNode(queuedTarget.target);
- if (targetInst !== null) {
- var nearestMounted = getNearestMountedFiber(targetInst);
- if (nearestMounted !== null) {
- var tag = nearestMounted.tag;
- if (tag === SuspenseComponent) {
- var instance = getSuspenseInstanceFromFiber(nearestMounted);
- if (instance !== null) {
- // We're blocked on hydrating this boundary.
- // Increase its priority.
- queuedTarget.blockedOn = instance;
- attemptHydrationAtPriority(queuedTarget.priority, function () {
- attemptHydrationAtCurrentPriority(nearestMounted);
- });
- return;
- }
- } else if (tag === HostRoot) {
- var root = nearestMounted.stateNode;
- if (isRootDehydrated(root)) {
- queuedTarget.blockedOn = getContainerFromFiber(nearestMounted); // We don't currently have a way to increase the priority of
- // a root other than sync.
- return;
- }
- }
- }
- }
- queuedTarget.blockedOn = null;
- }
- function queueExplicitHydrationTarget(target) {
- // TODO: This will read the priority if it's dispatched by the React
- // event system but not native events. Should read window.event.type, like
- // we do for updates (getCurrentEventPriority).
- var updatePriority = getCurrentUpdatePriority$1();
- var queuedTarget = {
- blockedOn: null,
- target: target,
- priority: updatePriority
- };
- var i = 0;
- for (; i < queuedExplicitHydrationTargets.length; i++) {
- // Stop once we hit the first target with lower priority than
- if (!isHigherEventPriority(updatePriority, queuedExplicitHydrationTargets[i].priority)) {
- break;
- }
- }
- queuedExplicitHydrationTargets.splice(i, 0, queuedTarget);
- if (i === 0) {
- attemptExplicitHydrationTarget(queuedTarget);
- }
- }
- function attemptReplayContinuousQueuedEvent(queuedEvent) {
- if (queuedEvent.blockedOn !== null) {
- return false;
- }
- var targetContainers = queuedEvent.targetContainers;
- while (targetContainers.length > 0) {
- var targetContainer = targetContainers[0];
- var nextBlockedOn = findInstanceBlockingEvent(queuedEvent.domEventName, queuedEvent.eventSystemFlags, targetContainer, queuedEvent.nativeEvent);
- if (nextBlockedOn === null) {
- {
- var nativeEvent = queuedEvent.nativeEvent;
- var nativeEventClone = new nativeEvent.constructor(nativeEvent.type, nativeEvent);
- setReplayingEvent(nativeEventClone);
- nativeEvent.target.dispatchEvent(nativeEventClone);
- resetReplayingEvent();
- }
- } else {
- // We're still blocked. Try again later.
- var _fiber3 = getInstanceFromNode(nextBlockedOn);
- if (_fiber3 !== null) {
- attemptContinuousHydration(_fiber3);
- }
- queuedEvent.blockedOn = nextBlockedOn;
- return false;
- } // This target container was successfully dispatched. Try the next.
- targetContainers.shift();
- }
- return true;
- }
- function attemptReplayContinuousQueuedEventInMap(queuedEvent, key, map) {
- if (attemptReplayContinuousQueuedEvent(queuedEvent)) {
- map.delete(key);
- }
- }
- function replayUnblockedEvents() {
- hasScheduledReplayAttempt = false;
- if (queuedFocus !== null && attemptReplayContinuousQueuedEvent(queuedFocus)) {
- queuedFocus = null;
- }
- if (queuedDrag !== null && attemptReplayContinuousQueuedEvent(queuedDrag)) {
- queuedDrag = null;
- }
- if (queuedMouse !== null && attemptReplayContinuousQueuedEvent(queuedMouse)) {
- queuedMouse = null;
- }
- queuedPointers.forEach(attemptReplayContinuousQueuedEventInMap);
- queuedPointerCaptures.forEach(attemptReplayContinuousQueuedEventInMap);
- }
- function scheduleCallbackIfUnblocked(queuedEvent, unblocked) {
- if (queuedEvent.blockedOn === unblocked) {
- queuedEvent.blockedOn = null;
- if (!hasScheduledReplayAttempt) {
- hasScheduledReplayAttempt = true; // Schedule a callback to attempt replaying as many events as are
- // now unblocked. This first might not actually be unblocked yet.
- // We could check it early to avoid scheduling an unnecessary callback.
- unstable_scheduleCallback(unstable_NormalPriority, replayUnblockedEvents);
- }
- }
- }
- function retryIfBlockedOn(unblocked) {
- // Mark anything that was blocked on this as no longer blocked
- // and eligible for a replay.
- if (queuedDiscreteEvents.length > 0) {
- scheduleCallbackIfUnblocked(queuedDiscreteEvents[0], unblocked); // This is a exponential search for each boundary that commits. I think it's
- // worth it because we expect very few discrete events to queue up and once
- // we are actually fully unblocked it will be fast to replay them.
- for (var i = 1; i < queuedDiscreteEvents.length; i++) {
- var queuedEvent = queuedDiscreteEvents[i];
- if (queuedEvent.blockedOn === unblocked) {
- queuedEvent.blockedOn = null;
- }
- }
- }
- if (queuedFocus !== null) {
- scheduleCallbackIfUnblocked(queuedFocus, unblocked);
- }
- if (queuedDrag !== null) {
- scheduleCallbackIfUnblocked(queuedDrag, unblocked);
- }
- if (queuedMouse !== null) {
- scheduleCallbackIfUnblocked(queuedMouse, unblocked);
- }
- var unblock = function (queuedEvent) {
- return scheduleCallbackIfUnblocked(queuedEvent, unblocked);
- };
- queuedPointers.forEach(unblock);
- queuedPointerCaptures.forEach(unblock);
- for (var _i = 0; _i < queuedExplicitHydrationTargets.length; _i++) {
- var queuedTarget = queuedExplicitHydrationTargets[_i];
- if (queuedTarget.blockedOn === unblocked) {
- queuedTarget.blockedOn = null;
- }
- }
- while (queuedExplicitHydrationTargets.length > 0) {
- var nextExplicitTarget = queuedExplicitHydrationTargets[0];
- if (nextExplicitTarget.blockedOn !== null) {
- // We're still blocked.
- break;
- } else {
- attemptExplicitHydrationTarget(nextExplicitTarget);
- if (nextExplicitTarget.blockedOn === null) {
- // We're unblocked.
- queuedExplicitHydrationTargets.shift();
- }
- }
- }
- }
- var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; // TODO: can we stop exporting these?
- var _enabled = true; // This is exported in FB builds for use by legacy FB layer infra.
- // We'd like to remove this but it's not clear if this is safe.
- function setEnabled(enabled) {
- _enabled = !!enabled;
- }
- function isEnabled() {
- return _enabled;
- }
- function createEventListenerWrapperWithPriority(targetContainer, domEventName, eventSystemFlags) {
- var eventPriority = getEventPriority(domEventName);
- var listenerWrapper;
- switch (eventPriority) {
- case DiscreteEventPriority:
- listenerWrapper = dispatchDiscreteEvent;
- break;
- case ContinuousEventPriority:
- listenerWrapper = dispatchContinuousEvent;
- break;
- case DefaultEventPriority:
- default:
- listenerWrapper = dispatchEvent;
- break;
- }
- return listenerWrapper.bind(null, domEventName, eventSystemFlags, targetContainer);
- }
- function dispatchDiscreteEvent(domEventName, eventSystemFlags, container, nativeEvent) {
- var previousPriority = getCurrentUpdatePriority();
- var prevTransition = ReactCurrentBatchConfig.transition;
- ReactCurrentBatchConfig.transition = null;
- try {
- setCurrentUpdatePriority(DiscreteEventPriority);
- dispatchEvent(domEventName, eventSystemFlags, container, nativeEvent);
- } finally {
- setCurrentUpdatePriority(previousPriority);
- ReactCurrentBatchConfig.transition = prevTransition;
- }
- }
- function dispatchContinuousEvent(domEventName, eventSystemFlags, container, nativeEvent) {
- var previousPriority = getCurrentUpdatePriority();
- var prevTransition = ReactCurrentBatchConfig.transition;
- ReactCurrentBatchConfig.transition = null;
- try {
- setCurrentUpdatePriority(ContinuousEventPriority);
- dispatchEvent(domEventName, eventSystemFlags, container, nativeEvent);
- } finally {
- setCurrentUpdatePriority(previousPriority);
- ReactCurrentBatchConfig.transition = prevTransition;
- }
- }
- function dispatchEvent(domEventName, eventSystemFlags, targetContainer, nativeEvent) {
- if (!_enabled) {
- return;
- }
- {
- dispatchEventWithEnableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay(domEventName, eventSystemFlags, targetContainer, nativeEvent);
- }
- }
- function dispatchEventWithEnableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay(domEventName, eventSystemFlags, targetContainer, nativeEvent) {
- var blockedOn = findInstanceBlockingEvent(domEventName, eventSystemFlags, targetContainer, nativeEvent);
- if (blockedOn === null) {
- dispatchEventForPluginEventSystem(domEventName, eventSystemFlags, nativeEvent, return_targetInst, targetContainer);
- clearIfContinuousEvent(domEventName, nativeEvent);
- return;
- }
- if (queueIfContinuousEvent(blockedOn, domEventName, eventSystemFlags, targetContainer, nativeEvent)) {
- nativeEvent.stopPropagation();
- return;
- } // We need to clear only if we didn't queue because
- // queueing is accumulative.
- clearIfContinuousEvent(domEventName, nativeEvent);
- if (eventSystemFlags & IS_CAPTURE_PHASE && isDiscreteEventThatRequiresHydration(domEventName)) {
- while (blockedOn !== null) {
- var fiber = getInstanceFromNode(blockedOn);
- if (fiber !== null) {
- attemptSynchronousHydration(fiber);
- }
- var nextBlockedOn = findInstanceBlockingEvent(domEventName, eventSystemFlags, targetContainer, nativeEvent);
- if (nextBlockedOn === null) {
- dispatchEventForPluginEventSystem(domEventName, eventSystemFlags, nativeEvent, return_targetInst, targetContainer);
- }
- if (nextBlockedOn === blockedOn) {
- break;
- }
- blockedOn = nextBlockedOn;
- }
- if (blockedOn !== null) {
- nativeEvent.stopPropagation();
- }
- return;
- } // This is not replayable so we'll invoke it but without a target,
- // in case the event system needs to trace it.
- dispatchEventForPluginEventSystem(domEventName, eventSystemFlags, nativeEvent, null, targetContainer);
- }
- var return_targetInst = null; // Returns a SuspenseInstance or Container if it's blocked.
- // The return_targetInst field above is conceptually part of the return value.
- function findInstanceBlockingEvent(domEventName, eventSystemFlags, targetContainer, nativeEvent) {
- // TODO: Warn if _enabled is false.
- return_targetInst = null;
- var nativeEventTarget = getEventTarget(nativeEvent);
- var targetInst = getClosestInstanceFromNode(nativeEventTarget);
- if (targetInst !== null) {
- var nearestMounted = getNearestMountedFiber(targetInst);
- if (nearestMounted === null) {
- // This tree has been unmounted already. Dispatch without a target.
- targetInst = null;
- } else {
- var tag = nearestMounted.tag;
- if (tag === SuspenseComponent) {
- var instance = getSuspenseInstanceFromFiber(nearestMounted);
- if (instance !== null) {
- // Queue the event to be replayed later. Abort dispatching since we
- // don't want this event dispatched twice through the event system.
- // TODO: If this is the first discrete event in the queue. Schedule an increased
- // priority for this boundary.
- return instance;
- } // This shouldn't happen, something went wrong but to avoid blocking
- // the whole system, dispatch the event without a target.
- // TODO: Warn.
- targetInst = null;
- } else if (tag === HostRoot) {
- var root = nearestMounted.stateNode;
- if (isRootDehydrated(root)) {
- // If this happens during a replay something went wrong and it might block
- // the whole system.
- return getContainerFromFiber(nearestMounted);
- }
- targetInst = null;
- } else if (nearestMounted !== targetInst) {
- // If we get an event (ex: img onload) before committing that
- // component's mount, ignore it for now (that is, treat it as if it was an
- // event on a non-React tree). We might also consider queueing events and
- // dispatching them after the mount.
- targetInst = null;
- }
- }
- }
- return_targetInst = targetInst; // We're not blocked on anything.
- return null;
- }
- function getEventPriority(domEventName) {
- switch (domEventName) {
- // Used by SimpleEventPlugin:
- case 'cancel':
- case 'click':
- case 'close':
- case 'contextmenu':
- case 'copy':
- case 'cut':
- case 'auxclick':
- case 'dblclick':
- case 'dragend':
- case 'dragstart':
- case 'drop':
- case 'focusin':
- case 'focusout':
- case 'input':
- case 'invalid':
- case 'keydown':
- case 'keypress':
- case 'keyup':
- case 'mousedown':
- case 'mouseup':
- case 'paste':
- case 'pause':
- case 'play':
- case 'pointercancel':
- case 'pointerdown':
- case 'pointerup':
- case 'ratechange':
- case 'reset':
- case 'resize':
- case 'seeked':
- case 'submit':
- case 'touchcancel':
- case 'touchend':
- case 'touchstart':
- case 'volumechange': // Used by polyfills:
- // eslint-disable-next-line no-fallthrough
- case 'change':
- case 'selectionchange':
- case 'textInput':
- case 'compositionstart':
- case 'compositionend':
- case 'compositionupdate': // Only enableCreateEventHandleAPI:
- // eslint-disable-next-line no-fallthrough
- case 'beforeblur':
- case 'afterblur': // Not used by React but could be by user code:
- // eslint-disable-next-line no-fallthrough
- case 'beforeinput':
- case 'blur':
- case 'fullscreenchange':
- case 'focus':
- case 'hashchange':
- case 'popstate':
- case 'select':
- case 'selectstart':
- return DiscreteEventPriority;
- case 'drag':
- case 'dragenter':
- case 'dragexit':
- case 'dragleave':
- case 'dragover':
- case 'mousemove':
- case 'mouseout':
- case 'mouseover':
- case 'pointermove':
- case 'pointerout':
- case 'pointerover':
- case 'scroll':
- case 'toggle':
- case 'touchmove':
- case 'wheel': // Not used by React but could be by user code:
- // eslint-disable-next-line no-fallthrough
- case 'mouseenter':
- case 'mouseleave':
- case 'pointerenter':
- case 'pointerleave':
- return ContinuousEventPriority;
- case 'message':
- {
- // We might be in the Scheduler callback.
- // Eventually this mechanism will be replaced by a check
- // of the current priority on the native scheduler.
- var schedulerPriority = getCurrentPriorityLevel();
- switch (schedulerPriority) {
- case ImmediatePriority:
- return DiscreteEventPriority;
- case UserBlockingPriority:
- return ContinuousEventPriority;
- case NormalPriority:
- case LowPriority:
- // TODO: Handle LowSchedulerPriority, somehow. Maybe the same lane as hydration.
- return DefaultEventPriority;
- case IdlePriority:
- return IdleEventPriority;
- default:
- return DefaultEventPriority;
- }
- }
- default:
- return DefaultEventPriority;
- }
- }
- function addEventBubbleListener(target, eventType, listener) {
- target.addEventListener(eventType, listener, false);
- return listener;
- }
- function addEventCaptureListener(target, eventType, listener) {
- target.addEventListener(eventType, listener, true);
- return listener;
- }
- function addEventCaptureListenerWithPassiveFlag(target, eventType, listener, passive) {
- target.addEventListener(eventType, listener, {
- capture: true,
- passive: passive
- });
- return listener;
- }
- function addEventBubbleListenerWithPassiveFlag(target, eventType, listener, passive) {
- target.addEventListener(eventType, listener, {
- passive: passive
- });
- return listener;
- }
- /**
- * These variables store information about text content of a target node,
- * allowing comparison of content before and after a given event.
- *
- * Identify the node where selection currently begins, then observe
- * both its text content and its current position in the DOM. Since the
- * browser may natively replace the target node during composition, we can
- * use its position to find its replacement.
- *
- *
- */
- var root = null;
- var startText = null;
- var fallbackText = null;
- function initialize(nativeEventTarget) {
- root = nativeEventTarget;
- startText = getText();
- return true;
- }
- function reset() {
- root = null;
- startText = null;
- fallbackText = null;
- }
- function getData() {
- if (fallbackText) {
- return fallbackText;
- }
- var start;
- var startValue = startText;
- var startLength = startValue.length;
- var end;
- var endValue = getText();
- var endLength = endValue.length;
- for (start = 0; start < startLength; start++) {
- if (startValue[start] !== endValue[start]) {
- break;
- }
- }
- var minEnd = startLength - start;
- for (end = 1; end <= minEnd; end++) {
- if (startValue[startLength - end] !== endValue[endLength - end]) {
- break;
- }
- }
- var sliceTail = end > 1 ? 1 - end : undefined;
- fallbackText = endValue.slice(start, sliceTail);
- return fallbackText;
- }
- function getText() {
- if ('value' in root) {
- return root.value;
- }
- return root.textContent;
- }
- /**
- * `charCode` represents the actual "character code" and is safe to use with
- * `String.fromCharCode`. As such, only keys that correspond to printable
- * characters produce a valid `charCode`, the only exception to this is Enter.
- * The Tab-key is considered non-printable and does not have a `charCode`,
- * presumably because it does not produce a tab-character in browsers.
- *
- * @param {object} nativeEvent Native browser event.
- * @return {number} Normalized `charCode` property.
- */
- function getEventCharCode(nativeEvent) {
- var charCode;
- var keyCode = nativeEvent.keyCode;
- if ('charCode' in nativeEvent) {
- charCode = nativeEvent.charCode; // FF does not set `charCode` for the Enter-key, check against `keyCode`.
- if (charCode === 0 && keyCode === 13) {
- charCode = 13;
- }
- } else {
- // IE8 does not implement `charCode`, but `keyCode` has the correct value.
- charCode = keyCode;
- } // IE and Edge (on Windows) and Chrome / Safari (on Windows and Linux)
- // report Enter as charCode 10 when ctrl is pressed.
- if (charCode === 10) {
- charCode = 13;
- } // Some non-printable keys are reported in `charCode`/`keyCode`, discard them.
- // Must not discard the (non-)printable Enter-key.
- if (charCode >= 32 || charCode === 13) {
- return charCode;
- }
- return 0;
- }
- function functionThatReturnsTrue() {
- return true;
- }
- function functionThatReturnsFalse() {
- return false;
- } // This is intentionally a factory so that we have different returned constructors.
- // If we had a single constructor, it would be megamorphic and engines would deopt.
- function createSyntheticEvent(Interface) {
- /**
- * Synthetic events are dispatched by event plugins, typically in response to a
- * top-level event delegation handler.
- *
- * These systems should generally use pooling to reduce the frequency of garbage
- * collection. The system should check `isPersistent` to determine whether the
- * event should be released into the pool after being dispatched. Users that
- * need a persisted event should invoke `persist`.
- *
- * Synthetic events (and subclasses) implement the DOM Level 3 Events API by
- * normalizing browser quirks. Subclasses do not necessarily have to implement a
- * DOM interface; custom application-specific events can also subclass this.
- */
- function SyntheticBaseEvent(reactName, reactEventType, targetInst, nativeEvent, nativeEventTarget) {
- this._reactName = reactName;
- this._targetInst = targetInst;
- this.type = reactEventType;
- this.nativeEvent = nativeEvent;
- this.target = nativeEventTarget;
- this.currentTarget = null;
- for (var _propName in Interface) {
- if (!Interface.hasOwnProperty(_propName)) {
- continue;
- }
- var normalize = Interface[_propName];
- if (normalize) {
- this[_propName] = normalize(nativeEvent);
- } else {
- this[_propName] = nativeEvent[_propName];
- }
- }
- var defaultPrevented = nativeEvent.defaultPrevented != null ? nativeEvent.defaultPrevented : nativeEvent.returnValue === false;
- if (defaultPrevented) {
- this.isDefaultPrevented = functionThatReturnsTrue;
- } else {
- this.isDefaultPrevented = functionThatReturnsFalse;
- }
- this.isPropagationStopped = functionThatReturnsFalse;
- return this;
- }
- assign(SyntheticBaseEvent.prototype, {
- preventDefault: function () {
- this.defaultPrevented = true;
- var event = this.nativeEvent;
- if (!event) {
- return;
- }
- if (event.preventDefault) {
- event.preventDefault(); // $FlowFixMe - flow is not aware of `unknown` in IE
- } else if (typeof event.returnValue !== 'unknown') {
- event.returnValue = false;
- }
- this.isDefaultPrevented = functionThatReturnsTrue;
- },
- stopPropagation: function () {
- var event = this.nativeEvent;
- if (!event) {
- return;
- }
- if (event.stopPropagation) {
- event.stopPropagation(); // $FlowFixMe - flow is not aware of `unknown` in IE
- } else if (typeof event.cancelBubble !== 'unknown') {
- // The ChangeEventPlugin registers a "propertychange" event for
- // IE. This event does not support bubbling or cancelling, and
- // any references to cancelBubble throw "Member not found". A
- // typeof check of "unknown" circumvents this issue (and is also
- // IE specific).
- event.cancelBubble = true;
- }
- this.isPropagationStopped = functionThatReturnsTrue;
- },
- /**
- * We release all dispatched `SyntheticEvent`s after each event loop, adding
- * them back into the pool. This allows a way to hold onto a reference that
- * won't be added back into the pool.
- */
- persist: function () {// Modern event system doesn't use pooling.
- },
- /**
- * Checks if this event should be released back into the pool.
- *
- * @return {boolean} True if this should not be released, false otherwise.
- */
- isPersistent: functionThatReturnsTrue
- });
- return SyntheticBaseEvent;
- }
- /**
- * @interface Event
- * @see http://www.w3.org/TR/DOM-Level-3-Events/
- */
- var EventInterface = {
- eventPhase: 0,
- bubbles: 0,
- cancelable: 0,
- timeStamp: function (event) {
- return event.timeStamp || Date.now();
- },
- defaultPrevented: 0,
- isTrusted: 0
- };
- var SyntheticEvent = createSyntheticEvent(EventInterface);
- var UIEventInterface = assign({}, EventInterface, {
- view: 0,
- detail: 0
- });
- var SyntheticUIEvent = createSyntheticEvent(UIEventInterface);
- var lastMovementX;
- var lastMovementY;
- var lastMouseEvent;
- function updateMouseMovementPolyfillState(event) {
- if (event !== lastMouseEvent) {
- if (lastMouseEvent && event.type === 'mousemove') {
- lastMovementX = event.screenX - lastMouseEvent.screenX;
- lastMovementY = event.screenY - lastMouseEvent.screenY;
- } else {
- lastMovementX = 0;
- lastMovementY = 0;
- }
- lastMouseEvent = event;
- }
- }
- /**
- * @interface MouseEvent
- * @see http://www.w3.org/TR/DOM-Level-3-Events/
- */
- var MouseEventInterface = assign({}, UIEventInterface, {
- screenX: 0,
- screenY: 0,
- clientX: 0,
- clientY: 0,
- pageX: 0,
- pageY: 0,
- ctrlKey: 0,
- shiftKey: 0,
- altKey: 0,
- metaKey: 0,
- getModifierState: getEventModifierState,
- button: 0,
- buttons: 0,
- relatedTarget: function (event) {
- if (event.relatedTarget === undefined) return event.fromElement === event.srcElement ? event.toElement : event.fromElement;
- return event.relatedTarget;
- },
- movementX: function (event) {
- if ('movementX' in event) {
- return event.movementX;
- }
- updateMouseMovementPolyfillState(event);
- return lastMovementX;
- },
- movementY: function (event) {
- if ('movementY' in event) {
- return event.movementY;
- } // Don't need to call updateMouseMovementPolyfillState() here
- // because it's guaranteed to have already run when movementX
- // was copied.
- return lastMovementY;
- }
- });
- var SyntheticMouseEvent = createSyntheticEvent(MouseEventInterface);
- /**
- * @interface DragEvent
- * @see http://www.w3.org/TR/DOM-Level-3-Events/
- */
- var DragEventInterface = assign({}, MouseEventInterface, {
- dataTransfer: 0
- });
- var SyntheticDragEvent = createSyntheticEvent(DragEventInterface);
- /**
- * @interface FocusEvent
- * @see http://www.w3.org/TR/DOM-Level-3-Events/
- */
- var FocusEventInterface = assign({}, UIEventInterface, {
- relatedTarget: 0
- });
- var SyntheticFocusEvent = createSyntheticEvent(FocusEventInterface);
- /**
- * @interface Event
- * @see http://www.w3.org/TR/css3-animations/#AnimationEvent-interface
- * @see https://developer.mozilla.org/en-US/docs/Web/API/AnimationEvent
- */
- var AnimationEventInterface = assign({}, EventInterface, {
- animationName: 0,
- elapsedTime: 0,
- pseudoElement: 0
- });
- var SyntheticAnimationEvent = createSyntheticEvent(AnimationEventInterface);
- /**
- * @interface Event
- * @see http://www.w3.org/TR/clipboard-apis/
- */
- var ClipboardEventInterface = assign({}, EventInterface, {
- clipboardData: function (event) {
- return 'clipboardData' in event ? event.clipboardData : window.clipboardData;
- }
- });
- var SyntheticClipboardEvent = createSyntheticEvent(ClipboardEventInterface);
- /**
- * @interface Event
- * @see http://www.w3.org/TR/DOM-Level-3-Events/#events-compositionevents
- */
- var CompositionEventInterface = assign({}, EventInterface, {
- data: 0
- });
- var SyntheticCompositionEvent = createSyntheticEvent(CompositionEventInterface);
- /**
- * @interface Event
- * @see http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105
- * /#events-inputevents
- */
- // Happens to share the same list for now.
- var SyntheticInputEvent = SyntheticCompositionEvent;
- /**
- * Normalization of deprecated HTML5 `key` values
- * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names
- */
- var normalizeKey = {
- Esc: 'Escape',
- Spacebar: ' ',
- Left: 'ArrowLeft',
- Up: 'ArrowUp',
- Right: 'ArrowRight',
- Down: 'ArrowDown',
- Del: 'Delete',
- Win: 'OS',
- Menu: 'ContextMenu',
- Apps: 'ContextMenu',
- Scroll: 'ScrollLock',
- MozPrintableKey: 'Unidentified'
- };
- /**
- * Translation from legacy `keyCode` to HTML5 `key`
- * Only special keys supported, all others depend on keyboard layout or browser
- * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names
- */
- var translateToKey = {
- '8': 'Backspace',
- '9': 'Tab',
- '12': 'Clear',
- '13': 'Enter',
- '16': 'Shift',
- '17': 'Control',
- '18': 'Alt',
- '19': 'Pause',
- '20': 'CapsLock',
- '27': 'Escape',
- '32': ' ',
- '33': 'PageUp',
- '34': 'PageDown',
- '35': 'End',
- '36': 'Home',
- '37': 'ArrowLeft',
- '38': 'ArrowUp',
- '39': 'ArrowRight',
- '40': 'ArrowDown',
- '45': 'Insert',
- '46': 'Delete',
- '112': 'F1',
- '113': 'F2',
- '114': 'F3',
- '115': 'F4',
- '116': 'F5',
- '117': 'F6',
- '118': 'F7',
- '119': 'F8',
- '120': 'F9',
- '121': 'F10',
- '122': 'F11',
- '123': 'F12',
- '144': 'NumLock',
- '145': 'ScrollLock',
- '224': 'Meta'
- };
- /**
- * @param {object} nativeEvent Native browser event.
- * @return {string} Normalized `key` property.
- */
- function getEventKey(nativeEvent) {
- if (nativeEvent.key) {
- // Normalize inconsistent values reported by browsers due to
- // implementations of a working draft specification.
- // FireFox implements `key` but returns `MozPrintableKey` for all
- // printable characters (normalized to `Unidentified`), ignore it.
- var key = normalizeKey[nativeEvent.key] || nativeEvent.key;
- if (key !== 'Unidentified') {
- return key;
- }
- } // Browser does not implement `key`, polyfill as much of it as we can.
- if (nativeEvent.type === 'keypress') {
- var charCode = getEventCharCode(nativeEvent); // The enter-key is technically both printable and non-printable and can
- // thus be captured by `keypress`, no other non-printable key should.
- return charCode === 13 ? 'Enter' : String.fromCharCode(charCode);
- }
- if (nativeEvent.type === 'keydown' || nativeEvent.type === 'keyup') {
- // While user keyboard layout determines the actual meaning of each
- // `keyCode` value, almost all function keys have a universal value.
- return translateToKey[nativeEvent.keyCode] || 'Unidentified';
- }
- return '';
- }
- /**
- * Translation from modifier key to the associated property in the event.
- * @see http://www.w3.org/TR/DOM-Level-3-Events/#keys-Modifiers
- */
- var modifierKeyToProp = {
- Alt: 'altKey',
- Control: 'ctrlKey',
- Meta: 'metaKey',
- Shift: 'shiftKey'
- }; // Older browsers (Safari <= 10, iOS Safari <= 10.2) do not support
- // getModifierState. If getModifierState is not supported, we map it to a set of
- // modifier keys exposed by the event. In this case, Lock-keys are not supported.
- function modifierStateGetter(keyArg) {
- var syntheticEvent = this;
- var nativeEvent = syntheticEvent.nativeEvent;
- if (nativeEvent.getModifierState) {
- return nativeEvent.getModifierState(keyArg);
- }
- var keyProp = modifierKeyToProp[keyArg];
- return keyProp ? !!nativeEvent[keyProp] : false;
- }
- function getEventModifierState(nativeEvent) {
- return modifierStateGetter;
- }
- /**
- * @interface KeyboardEvent
- * @see http://www.w3.org/TR/DOM-Level-3-Events/
- */
- var KeyboardEventInterface = assign({}, UIEventInterface, {
- key: getEventKey,
- code: 0,
- location: 0,
- ctrlKey: 0,
- shiftKey: 0,
- altKey: 0,
- metaKey: 0,
- repeat: 0,
- locale: 0,
- getModifierState: getEventModifierState,
- // Legacy Interface
- charCode: function (event) {
- // `charCode` is the result of a KeyPress event and represents the value of
- // the actual printable character.
- // KeyPress is deprecated, but its replacement is not yet final and not
- // implemented in any major browser. Only KeyPress has charCode.
- if (event.type === 'keypress') {
- return getEventCharCode(event);
- }
- return 0;
- },
- keyCode: function (event) {
- // `keyCode` is the result of a KeyDown/Up event and represents the value of
- // physical keyboard key.
- // The actual meaning of the value depends on the users' keyboard layout
- // which cannot be detected. Assuming that it is a US keyboard layout
- // provides a surprisingly accurate mapping for US and European users.
- // Due to this, it is left to the user to implement at this time.
- if (event.type === 'keydown' || event.type === 'keyup') {
- return event.keyCode;
- }
- return 0;
- },
- which: function (event) {
- // `which` is an alias for either `keyCode` or `charCode` depending on the
- // type of the event.
- if (event.type === 'keypress') {
- return getEventCharCode(event);
- }
- if (event.type === 'keydown' || event.type === 'keyup') {
- return event.keyCode;
- }
- return 0;
- }
- });
- var SyntheticKeyboardEvent = createSyntheticEvent(KeyboardEventInterface);
- /**
- * @interface PointerEvent
- * @see http://www.w3.org/TR/pointerevents/
- */
- var PointerEventInterface = assign({}, MouseEventInterface, {
- pointerId: 0,
- width: 0,
- height: 0,
- pressure: 0,
- tangentialPressure: 0,
- tiltX: 0,
- tiltY: 0,
- twist: 0,
- pointerType: 0,
- isPrimary: 0
- });
- var SyntheticPointerEvent = createSyntheticEvent(PointerEventInterface);
- /**
- * @interface TouchEvent
- * @see http://www.w3.org/TR/touch-events/
- */
- var TouchEventInterface = assign({}, UIEventInterface, {
- touches: 0,
- targetTouches: 0,
- changedTouches: 0,
- altKey: 0,
- metaKey: 0,
- ctrlKey: 0,
- shiftKey: 0,
- getModifierState: getEventModifierState
- });
- var SyntheticTouchEvent = createSyntheticEvent(TouchEventInterface);
- /**
- * @interface Event
- * @see http://www.w3.org/TR/2009/WD-css3-transitions-20090320/#transition-events-
- * @see https://developer.mozilla.org/en-US/docs/Web/API/TransitionEvent
- */
- var TransitionEventInterface = assign({}, EventInterface, {
- propertyName: 0,
- elapsedTime: 0,
- pseudoElement: 0
- });
- var SyntheticTransitionEvent = createSyntheticEvent(TransitionEventInterface);
- /**
- * @interface WheelEvent
- * @see http://www.w3.org/TR/DOM-Level-3-Events/
- */
- var WheelEventInterface = assign({}, MouseEventInterface, {
- deltaX: function (event) {
- return 'deltaX' in event ? event.deltaX : // Fallback to `wheelDeltaX` for Webkit and normalize (right is positive).
- 'wheelDeltaX' in event ? -event.wheelDeltaX : 0;
- },
- deltaY: function (event) {
- return 'deltaY' in event ? event.deltaY : // Fallback to `wheelDeltaY` for Webkit and normalize (down is positive).
- 'wheelDeltaY' in event ? -event.wheelDeltaY : // Fallback to `wheelDelta` for IE<9 and normalize (down is positive).
- 'wheelDelta' in event ? -event.wheelDelta : 0;
- },
- deltaZ: 0,
- // Browsers without "deltaMode" is reporting in raw wheel delta where one
- // notch on the scroll is always +/- 120, roughly equivalent to pixels.
- // A good approximation of DOM_DELTA_LINE (1) is 5% of viewport size or
- // ~40 pixels, for DOM_DELTA_SCREEN (2) it is 87.5% of viewport size.
- deltaMode: 0
- });
- var SyntheticWheelEvent = createSyntheticEvent(WheelEventInterface);
- var END_KEYCODES = [9, 13, 27, 32]; // Tab, Return, Esc, Space
- var START_KEYCODE = 229;
- var canUseCompositionEvent = canUseDOM && 'CompositionEvent' in window;
- var documentMode = null;
- if (canUseDOM && 'documentMode' in document) {
- documentMode = document.documentMode;
- } // Webkit offers a very useful `textInput` event that can be used to
- // directly represent `beforeInput`. The IE `textinput` event is not as
- // useful, so we don't use it.
- var canUseTextInputEvent = canUseDOM && 'TextEvent' in window && !documentMode; // In IE9+, we have access to composition events, but the data supplied
- // by the native compositionend event may be incorrect. Japanese ideographic
- // spaces, for instance (\u3000) are not recorded correctly.
- var useFallbackCompositionData = canUseDOM && (!canUseCompositionEvent || documentMode && documentMode > 8 && documentMode <= 11);
- var SPACEBAR_CODE = 32;
- var SPACEBAR_CHAR = String.fromCharCode(SPACEBAR_CODE);
- function registerEvents() {
- registerTwoPhaseEvent('onBeforeInput', ['compositionend', 'keypress', 'textInput', 'paste']);
- registerTwoPhaseEvent('onCompositionEnd', ['compositionend', 'focusout', 'keydown', 'keypress', 'keyup', 'mousedown']);
- registerTwoPhaseEvent('onCompositionStart', ['compositionstart', 'focusout', 'keydown', 'keypress', 'keyup', 'mousedown']);
- registerTwoPhaseEvent('onCompositionUpdate', ['compositionupdate', 'focusout', 'keydown', 'keypress', 'keyup', 'mousedown']);
- } // Track whether we've ever handled a keypress on the space key.
- var hasSpaceKeypress = false;
- /**
- * Return whether a native keypress event is assumed to be a command.
- * This is required because Firefox fires `keypress` events for key commands
- * (cut, copy, select-all, etc.) even though no character is inserted.
- */
- function isKeypressCommand(nativeEvent) {
- return (nativeEvent.ctrlKey || nativeEvent.altKey || nativeEvent.metaKey) && // ctrlKey && altKey is equivalent to AltGr, and is not a command.
- !(nativeEvent.ctrlKey && nativeEvent.altKey);
- }
- /**
- * Translate native top level events into event types.
- */
- function getCompositionEventType(domEventName) {
- switch (domEventName) {
- case 'compositionstart':
- return 'onCompositionStart';
- case 'compositionend':
- return 'onCompositionEnd';
- case 'compositionupdate':
- return 'onCompositionUpdate';
- }
- }
- /**
- * Does our fallback best-guess model think this event signifies that
- * composition has begun?
- */
- function isFallbackCompositionStart(domEventName, nativeEvent) {
- return domEventName === 'keydown' && nativeEvent.keyCode === START_KEYCODE;
- }
- /**
- * Does our fallback mode think that this event is the end of composition?
- */
- function isFallbackCompositionEnd(domEventName, nativeEvent) {
- switch (domEventName) {
- case 'keyup':
- // Command keys insert or clear IME input.
- return END_KEYCODES.indexOf(nativeEvent.keyCode) !== -1;
- case 'keydown':
- // Expect IME keyCode on each keydown. If we get any other
- // code we must have exited earlier.
- return nativeEvent.keyCode !== START_KEYCODE;
- case 'keypress':
- case 'mousedown':
- case 'focusout':
- // Events are not possible without cancelling IME.
- return true;
- default:
- return false;
- }
- }
- /**
- * Google Input Tools provides composition data via a CustomEvent,
- * with the `data` property populated in the `detail` object. If this
- * is available on the event object, use it. If not, this is a plain
- * composition event and we have nothing special to extract.
- *
- * @param {object} nativeEvent
- * @return {?string}
- */
- function getDataFromCustomEvent(nativeEvent) {
- var detail = nativeEvent.detail;
- if (typeof detail === 'object' && 'data' in detail) {
- return detail.data;
- }
- return null;
- }
- /**
- * Check if a composition event was triggered by Korean IME.
- * Our fallback mode does not work well with IE's Korean IME,
- * so just use native composition events when Korean IME is used.
- * Although CompositionEvent.locale property is deprecated,
- * it is available in IE, where our fallback mode is enabled.
- *
- * @param {object} nativeEvent
- * @return {boolean}
- */
- function isUsingKoreanIME(nativeEvent) {
- return nativeEvent.locale === 'ko';
- } // Track the current IME composition status, if any.
- var isComposing = false;
- /**
- * @return {?object} A SyntheticCompositionEvent.
- */
- function extractCompositionEvent(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget) {
- var eventType;
- var fallbackData;
- if (canUseCompositionEvent) {
- eventType = getCompositionEventType(domEventName);
- } else if (!isComposing) {
- if (isFallbackCompositionStart(domEventName, nativeEvent)) {
- eventType = 'onCompositionStart';
- }
- } else if (isFallbackCompositionEnd(domEventName, nativeEvent)) {
- eventType = 'onCompositionEnd';
- }
- if (!eventType) {
- return null;
- }
- if (useFallbackCompositionData && !isUsingKoreanIME(nativeEvent)) {
- // The current composition is stored statically and must not be
- // overwritten while composition continues.
- if (!isComposing && eventType === 'onCompositionStart') {
- isComposing = initialize(nativeEventTarget);
- } else if (eventType === 'onCompositionEnd') {
- if (isComposing) {
- fallbackData = getData();
- }
- }
- }
- var listeners = accumulateTwoPhaseListeners(targetInst, eventType);
- if (listeners.length > 0) {
- var event = new SyntheticCompositionEvent(eventType, domEventName, null, nativeEvent, nativeEventTarget);
- dispatchQueue.push({
- event: event,
- listeners: listeners
- });
- if (fallbackData) {
- // Inject data generated from fallback path into the synthetic event.
- // This matches the property of native CompositionEventInterface.
- event.data = fallbackData;
- } else {
- var customData = getDataFromCustomEvent(nativeEvent);
- if (customData !== null) {
- event.data = customData;
- }
- }
- }
- }
- function getNativeBeforeInputChars(domEventName, nativeEvent) {
- switch (domEventName) {
- case 'compositionend':
- return getDataFromCustomEvent(nativeEvent);
- case 'keypress':
- /**
- * If native `textInput` events are available, our goal is to make
- * use of them. However, there is a special case: the spacebar key.
- * In Webkit, preventing default on a spacebar `textInput` event
- * cancels character insertion, but it *also* causes the browser
- * to fall back to its default spacebar behavior of scrolling the
- * page.
- *
- * Tracking at:
- * https://code.google.com/p/chromium/issues/detail?id=355103
- *
- * To avoid this issue, use the keypress event as if no `textInput`
- * event is available.
- */
- var which = nativeEvent.which;
- if (which !== SPACEBAR_CODE) {
- return null;
- }
- hasSpaceKeypress = true;
- return SPACEBAR_CHAR;
- case 'textInput':
- // Record the characters to be added to the DOM.
- var chars = nativeEvent.data; // If it's a spacebar character, assume that we have already handled
- // it at the keypress level and bail immediately. Android Chrome
- // doesn't give us keycodes, so we need to ignore it.
- if (chars === SPACEBAR_CHAR && hasSpaceKeypress) {
- return null;
- }
- return chars;
- default:
- // For other native event types, do nothing.
- return null;
- }
- }
- /**
- * For browsers that do not provide the `textInput` event, extract the
- * appropriate string to use for SyntheticInputEvent.
- */
- function getFallbackBeforeInputChars(domEventName, nativeEvent) {
- // If we are currently composing (IME) and using a fallback to do so,
- // try to extract the composed characters from the fallback object.
- // If composition event is available, we extract a string only at
- // compositionevent, otherwise extract it at fallback events.
- if (isComposing) {
- if (domEventName === 'compositionend' || !canUseCompositionEvent && isFallbackCompositionEnd(domEventName, nativeEvent)) {
- var chars = getData();
- reset();
- isComposing = false;
- return chars;
- }
- return null;
- }
- switch (domEventName) {
- case 'paste':
- // If a paste event occurs after a keypress, throw out the input
- // chars. Paste events should not lead to BeforeInput events.
- return null;
- case 'keypress':
- /**
- * As of v27, Firefox may fire keypress events even when no character
- * will be inserted. A few possibilities:
- *
- * - `which` is `0`. Arrow keys, Esc key, etc.
- *
- * - `which` is the pressed key code, but no char is available.
- * Ex: 'AltGr + d` in Polish. There is no modified character for
- * this key combination and no character is inserted into the
- * document, but FF fires the keypress for char code `100` anyway.
- * No `input` event will occur.
- *
- * - `which` is the pressed key code, but a command combination is
- * being used. Ex: `Cmd+C`. No character is inserted, and no
- * `input` event will occur.
- */
- if (!isKeypressCommand(nativeEvent)) {
- // IE fires the `keypress` event when a user types an emoji via
- // Touch keyboard of Windows. In such a case, the `char` property
- // holds an emoji character like `\uD83D\uDE0A`. Because its length
- // is 2, the property `which` does not represent an emoji correctly.
- // In such a case, we directly return the `char` property instead of
- // using `which`.
- if (nativeEvent.char && nativeEvent.char.length > 1) {
- return nativeEvent.char;
- } else if (nativeEvent.which) {
- return String.fromCharCode(nativeEvent.which);
- }
- }
- return null;
- case 'compositionend':
- return useFallbackCompositionData && !isUsingKoreanIME(nativeEvent) ? null : nativeEvent.data;
- default:
- return null;
- }
- }
- /**
- * Extract a SyntheticInputEvent for `beforeInput`, based on either native
- * `textInput` or fallback behavior.
- *
- * @return {?object} A SyntheticInputEvent.
- */
- function extractBeforeInputEvent(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget) {
- var chars;
- if (canUseTextInputEvent) {
- chars = getNativeBeforeInputChars(domEventName, nativeEvent);
- } else {
- chars = getFallbackBeforeInputChars(domEventName, nativeEvent);
- } // If no characters are being inserted, no BeforeInput event should
- // be fired.
- if (!chars) {
- return null;
- }
- var listeners = accumulateTwoPhaseListeners(targetInst, 'onBeforeInput');
- if (listeners.length > 0) {
- var event = new SyntheticInputEvent('onBeforeInput', 'beforeinput', null, nativeEvent, nativeEventTarget);
- dispatchQueue.push({
- event: event,
- listeners: listeners
- });
- event.data = chars;
- }
- }
- /**
- * Create an `onBeforeInput` event to match
- * http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105/#events-inputevents.
- *
- * This event plugin is based on the native `textInput` event
- * available in Chrome, Safari, Opera, and IE. This event fires after
- * `onKeyPress` and `onCompositionEnd`, but before `onInput`.
- *
- * `beforeInput` is spec'd but not implemented in any browsers, and
- * the `input` event does not provide any useful information about what has
- * actually been added, contrary to the spec. Thus, `textInput` is the best
- * available event to identify the characters that have actually been inserted
- * into the target node.
- *
- * This plugin is also responsible for emitting `composition` events, thus
- * allowing us to share composition fallback code for both `beforeInput` and
- * `composition` event types.
- */
- function extractEvents(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget, eventSystemFlags, targetContainer) {
- extractCompositionEvent(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget);
- extractBeforeInputEvent(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget);
- }
- /**
- * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary
- */
- var supportedInputTypes = {
- color: true,
- date: true,
- datetime: true,
- 'datetime-local': true,
- email: true,
- month: true,
- number: true,
- password: true,
- range: true,
- search: true,
- tel: true,
- text: true,
- time: true,
- url: true,
- week: true
- };
- function isTextInputElement(elem) {
- var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase();
- if (nodeName === 'input') {
- return !!supportedInputTypes[elem.type];
- }
- if (nodeName === 'textarea') {
- return true;
- }
- return false;
- }
- /**
- * Checks if an event is supported in the current execution environment.
- *
- * NOTE: This will not work correctly for non-generic events such as `change`,
- * `reset`, `load`, `error`, and `select`.
- *
- * Borrows from Modernizr.
- *
- * @param {string} eventNameSuffix Event name, e.g. "click".
- * @return {boolean} True if the event is supported.
- * @internal
- * @license Modernizr 3.0.0pre (Custom Build) | MIT
- */
- function isEventSupported(eventNameSuffix) {
- if (!canUseDOM) {
- return false;
- }
- var eventName = 'on' + eventNameSuffix;
- var isSupported = (eventName in document);
- if (!isSupported) {
- var element = document.createElement('div');
- element.setAttribute(eventName, 'return;');
- isSupported = typeof element[eventName] === 'function';
- }
- return isSupported;
- }
- function registerEvents$1() {
- registerTwoPhaseEvent('onChange', ['change', 'click', 'focusin', 'focusout', 'input', 'keydown', 'keyup', 'selectionchange']);
- }
- function createAndAccumulateChangeEvent(dispatchQueue, inst, nativeEvent, target) {
- // Flag this event loop as needing state restore.
- enqueueStateRestore(target);
- var listeners = accumulateTwoPhaseListeners(inst, 'onChange');
- if (listeners.length > 0) {
- var event = new SyntheticEvent('onChange', 'change', null, nativeEvent, target);
- dispatchQueue.push({
- event: event,
- listeners: listeners
- });
- }
- }
- /**
- * For IE shims
- */
- var activeElement = null;
- var activeElementInst = null;
- /**
- * SECTION: handle `change` event
- */
- function shouldUseChangeEvent(elem) {
- var nodeName = elem.nodeName && elem.nodeName.toLowerCase();
- return nodeName === 'select' || nodeName === 'input' && elem.type === 'file';
- }
- function manualDispatchChangeEvent(nativeEvent) {
- var dispatchQueue = [];
- createAndAccumulateChangeEvent(dispatchQueue, activeElementInst, nativeEvent, getEventTarget(nativeEvent)); // If change and propertychange bubbled, we'd just bind to it like all the
- // other events and have it go through ReactBrowserEventEmitter. Since it
- // doesn't, we manually listen for the events and so we have to enqueue and
- // process the abstract event manually.
- //
- // Batching is necessary here in order to ensure that all event handlers run
- // before the next rerender (including event handlers attached to ancestor
- // elements instead of directly on the input). Without this, controlled
- // components don't work properly in conjunction with event bubbling because
- // the component is rerendered and the value reverted before all the event
- // handlers can run. See https://github.com/facebook/react/issues/708.
- batchedUpdates(runEventInBatch, dispatchQueue);
- }
- function runEventInBatch(dispatchQueue) {
- processDispatchQueue(dispatchQueue, 0);
- }
- function getInstIfValueChanged(targetInst) {
- var targetNode = getNodeFromInstance(targetInst);
- if (updateValueIfChanged(targetNode)) {
- return targetInst;
- }
- }
- function getTargetInstForChangeEvent(domEventName, targetInst) {
- if (domEventName === 'change') {
- return targetInst;
- }
- }
- /**
- * SECTION: handle `input` event
- */
- var isInputEventSupported = false;
- if (canUseDOM) {
- // IE9 claims to support the input event but fails to trigger it when
- // deleting text, so we ignore its input events.
- isInputEventSupported = isEventSupported('input') && (!document.documentMode || document.documentMode > 9);
- }
- /**
- * (For IE <=9) Starts tracking propertychange events on the passed-in element
- * and override the value property so that we can distinguish user events from
- * value changes in JS.
- */
- function startWatchingForValueChange(target, targetInst) {
- activeElement = target;
- activeElementInst = targetInst;
- activeElement.attachEvent('onpropertychange', handlePropertyChange);
- }
- /**
- * (For IE <=9) Removes the event listeners from the currently-tracked element,
- * if any exists.
- */
- function stopWatchingForValueChange() {
- if (!activeElement) {
- return;
- }
- activeElement.detachEvent('onpropertychange', handlePropertyChange);
- activeElement = null;
- activeElementInst = null;
- }
- /**
- * (For IE <=9) Handles a propertychange event, sending a `change` event if
- * the value of the active element has changed.
- */
- function handlePropertyChange(nativeEvent) {
- if (nativeEvent.propertyName !== 'value') {
- return;
- }
- if (getInstIfValueChanged(activeElementInst)) {
- manualDispatchChangeEvent(nativeEvent);
- }
- }
- function handleEventsForInputEventPolyfill(domEventName, target, targetInst) {
- if (domEventName === 'focusin') {
- // In IE9, propertychange fires for most input events but is buggy and
- // doesn't fire when text is deleted, but conveniently, selectionchange
- // appears to fire in all of the remaining cases so we catch those and
- // forward the event if the value has changed
- // In either case, we don't want to call the event handler if the value
- // is changed from JS so we redefine a setter for `.value` that updates
- // our activeElementValue variable, allowing us to ignore those changes
- //
- // stopWatching() should be a noop here but we call it just in case we
- // missed a blur event somehow.
- stopWatchingForValueChange();
- startWatchingForValueChange(target, targetInst);
- } else if (domEventName === 'focusout') {
- stopWatchingForValueChange();
- }
- } // For IE8 and IE9.
- function getTargetInstForInputEventPolyfill(domEventName, targetInst) {
- if (domEventName === 'selectionchange' || domEventName === 'keyup' || domEventName === 'keydown') {
- // On the selectionchange event, the target is just document which isn't
- // helpful for us so just check activeElement instead.
- //
- // 99% of the time, keydown and keyup aren't necessary. IE8 fails to fire
- // propertychange on the first input event after setting `value` from a
- // script and fires only keydown, keypress, keyup. Catching keyup usually
- // gets it and catching keydown lets us fire an event for the first
- // keystroke if user does a key repeat (it'll be a little delayed: right
- // before the second keystroke). Other input methods (e.g., paste) seem to
- // fire selectionchange normally.
- return getInstIfValueChanged(activeElementInst);
- }
- }
- /**
- * SECTION: handle `click` event
- */
- function shouldUseClickEvent(elem) {
- // Use the `click` event to detect changes to checkbox and radio inputs.
- // This approach works across all browsers, whereas `change` does not fire
- // until `blur` in IE8.
- var nodeName = elem.nodeName;
- return nodeName && nodeName.toLowerCase() === 'input' && (elem.type === 'checkbox' || elem.type === 'radio');
- }
- function getTargetInstForClickEvent(domEventName, targetInst) {
- if (domEventName === 'click') {
- return getInstIfValueChanged(targetInst);
- }
- }
- function getTargetInstForInputOrChangeEvent(domEventName, targetInst) {
- if (domEventName === 'input' || domEventName === 'change') {
- return getInstIfValueChanged(targetInst);
- }
- }
- function handleControlledInputBlur(node) {
- var state = node._wrapperState;
- if (!state || !state.controlled || node.type !== 'number') {
- return;
- }
- {
- // If controlled, assign the value attribute to the current value on blur
- setDefaultValue(node, 'number', node.value);
- }
- }
- /**
- * This plugin creates an `onChange` event that normalizes change events
- * across form elements. This event fires at a time when it's possible to
- * change the element's value without seeing a flicker.
- *
- * Supported elements are:
- * - input (see `isTextInputElement`)
- * - textarea
- * - select
- */
- function extractEvents$1(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget, eventSystemFlags, targetContainer) {
- var targetNode = targetInst ? getNodeFromInstance(targetInst) : window;
- var getTargetInstFunc, handleEventFunc;
- if (shouldUseChangeEvent(targetNode)) {
- getTargetInstFunc = getTargetInstForChangeEvent;
- } else if (isTextInputElement(targetNode)) {
- if (isInputEventSupported) {
- getTargetInstFunc = getTargetInstForInputOrChangeEvent;
- } else {
- getTargetInstFunc = getTargetInstForInputEventPolyfill;
- handleEventFunc = handleEventsForInputEventPolyfill;
- }
- } else if (shouldUseClickEvent(targetNode)) {
- getTargetInstFunc = getTargetInstForClickEvent;
- }
- if (getTargetInstFunc) {
- var inst = getTargetInstFunc(domEventName, targetInst);
- if (inst) {
- createAndAccumulateChangeEvent(dispatchQueue, inst, nativeEvent, nativeEventTarget);
- return;
- }
- }
- if (handleEventFunc) {
- handleEventFunc(domEventName, targetNode, targetInst);
- } // When blurring, set the value attribute for number inputs
- if (domEventName === 'focusout') {
- handleControlledInputBlur(targetNode);
- }
- }
- function registerEvents$2() {
- registerDirectEvent('onMouseEnter', ['mouseout', 'mouseover']);
- registerDirectEvent('onMouseLeave', ['mouseout', 'mouseover']);
- registerDirectEvent('onPointerEnter', ['pointerout', 'pointerover']);
- registerDirectEvent('onPointerLeave', ['pointerout', 'pointerover']);
- }
- /**
- * For almost every interaction we care about, there will be both a top-level
- * `mouseover` and `mouseout` event that occurs. Only use `mouseout` so that
- * we do not extract duplicate events. However, moving the mouse into the
- * browser from outside will not fire a `mouseout` event. In this case, we use
- * the `mouseover` top-level event.
- */
- function extractEvents$2(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget, eventSystemFlags, targetContainer) {
- var isOverEvent = domEventName === 'mouseover' || domEventName === 'pointerover';
- var isOutEvent = domEventName === 'mouseout' || domEventName === 'pointerout';
- if (isOverEvent && !isReplayingEvent(nativeEvent)) {
- // If this is an over event with a target, we might have already dispatched
- // the event in the out event of the other target. If this is replayed,
- // then it's because we couldn't dispatch against this target previously
- // so we have to do it now instead.
- var related = nativeEvent.relatedTarget || nativeEvent.fromElement;
- if (related) {
- // If the related node is managed by React, we can assume that we have
- // already dispatched the corresponding events during its mouseout.
- if (getClosestInstanceFromNode(related) || isContainerMarkedAsRoot(related)) {
- return;
- }
- }
- }
- if (!isOutEvent && !isOverEvent) {
- // Must not be a mouse or pointer in or out - ignoring.
- return;
- }
- var win; // TODO: why is this nullable in the types but we read from it?
- if (nativeEventTarget.window === nativeEventTarget) {
- // `nativeEventTarget` is probably a window object.
- win = nativeEventTarget;
- } else {
- // TODO: Figure out why `ownerDocument` is sometimes undefined in IE8.
- var doc = nativeEventTarget.ownerDocument;
- if (doc) {
- win = doc.defaultView || doc.parentWindow;
- } else {
- win = window;
- }
- }
- var from;
- var to;
- if (isOutEvent) {
- var _related = nativeEvent.relatedTarget || nativeEvent.toElement;
- from = targetInst;
- to = _related ? getClosestInstanceFromNode(_related) : null;
- if (to !== null) {
- var nearestMounted = getNearestMountedFiber(to);
- if (to !== nearestMounted || to.tag !== HostComponent && to.tag !== HostText) {
- to = null;
- }
- }
- } else {
- // Moving to a node from outside the window.
- from = null;
- to = targetInst;
- }
- if (from === to) {
- // Nothing pertains to our managed components.
- return;
- }
- var SyntheticEventCtor = SyntheticMouseEvent;
- var leaveEventType = 'onMouseLeave';
- var enterEventType = 'onMouseEnter';
- var eventTypePrefix = 'mouse';
- if (domEventName === 'pointerout' || domEventName === 'pointerover') {
- SyntheticEventCtor = SyntheticPointerEvent;
- leaveEventType = 'onPointerLeave';
- enterEventType = 'onPointerEnter';
- eventTypePrefix = 'pointer';
- }
- var fromNode = from == null ? win : getNodeFromInstance(from);
- var toNode = to == null ? win : getNodeFromInstance(to);
- var leave = new SyntheticEventCtor(leaveEventType, eventTypePrefix + 'leave', from, nativeEvent, nativeEventTarget);
- leave.target = fromNode;
- leave.relatedTarget = toNode;
- var enter = null; // We should only process this nativeEvent if we are processing
- // the first ancestor. Next time, we will ignore the event.
- var nativeTargetInst = getClosestInstanceFromNode(nativeEventTarget);
- if (nativeTargetInst === targetInst) {
- var enterEvent = new SyntheticEventCtor(enterEventType, eventTypePrefix + 'enter', to, nativeEvent, nativeEventTarget);
- enterEvent.target = toNode;
- enterEvent.relatedTarget = fromNode;
- enter = enterEvent;
- }
- accumulateEnterLeaveTwoPhaseListeners(dispatchQueue, leave, enter, from, to);
- }
- /**
- * inlined Object.is polyfill to avoid requiring consumers ship their own
- * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
- */
- function is(x, y) {
- return x === y && (x !== 0 || 1 / x === 1 / y) || x !== x && y !== y // eslint-disable-line no-self-compare
- ;
- }
- var objectIs = typeof Object.is === 'function' ? Object.is : is;
- /**
- * Performs equality by iterating through keys on an object and returning false
- * when any key has values which are not strictly equal between the arguments.
- * Returns true when the values of all keys are strictly equal.
- */
- function shallowEqual(objA, objB) {
- if (objectIs(objA, objB)) {
- return true;
- }
- if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {
- return false;
- }
- var keysA = Object.keys(objA);
- var keysB = Object.keys(objB);
- if (keysA.length !== keysB.length) {
- return false;
- } // Test for A's keys different from B.
- for (var i = 0; i < keysA.length; i++) {
- var currentKey = keysA[i];
- if (!hasOwnProperty.call(objB, currentKey) || !objectIs(objA[currentKey], objB[currentKey])) {
- return false;
- }
- }
- return true;
- }
- /**
- * Given any node return the first leaf node without children.
- *
- * @param {DOMElement|DOMTextNode} node
- * @return {DOMElement|DOMTextNode}
- */
- function getLeafNode(node) {
- while (node && node.firstChild) {
- node = node.firstChild;
- }
- return node;
- }
- /**
- * Get the next sibling within a container. This will walk up the
- * DOM if a node's siblings have been exhausted.
- *
- * @param {DOMElement|DOMTextNode} node
- * @return {?DOMElement|DOMTextNode}
- */
- function getSiblingNode(node) {
- while (node) {
- if (node.nextSibling) {
- return node.nextSibling;
- }
- node = node.parentNode;
- }
- }
- /**
- * Get object describing the nodes which contain characters at offset.
- *
- * @param {DOMElement|DOMTextNode} root
- * @param {number} offset
- * @return {?object}
- */
- function getNodeForCharacterOffset(root, offset) {
- var node = getLeafNode(root);
- var nodeStart = 0;
- var nodeEnd = 0;
- while (node) {
- if (node.nodeType === TEXT_NODE) {
- nodeEnd = nodeStart + node.textContent.length;
- if (nodeStart <= offset && nodeEnd >= offset) {
- return {
- node: node,
- offset: offset - nodeStart
- };
- }
- nodeStart = nodeEnd;
- }
- node = getLeafNode(getSiblingNode(node));
- }
- }
- /**
- * @param {DOMElement} outerNode
- * @return {?object}
- */
- function getOffsets(outerNode) {
- var ownerDocument = outerNode.ownerDocument;
- var win = ownerDocument && ownerDocument.defaultView || window;
- var selection = win.getSelection && win.getSelection();
- if (!selection || selection.rangeCount === 0) {
- return null;
- }
- var anchorNode = selection.anchorNode,
- anchorOffset = selection.anchorOffset,
- focusNode = selection.focusNode,
- focusOffset = selection.focusOffset; // In Firefox, anchorNode and focusNode can be "anonymous divs", e.g. the
- // up/down buttons on an <input type="number">. Anonymous divs do not seem to
- // expose properties, triggering a "Permission denied error" if any of its
- // properties are accessed. The only seemingly possible way to avoid erroring
- // is to access a property that typically works for non-anonymous divs and
- // catch any error that may otherwise arise. See
- // https://bugzilla.mozilla.org/show_bug.cgi?id=208427
- try {
- /* eslint-disable no-unused-expressions */
- anchorNode.nodeType;
- focusNode.nodeType;
- /* eslint-enable no-unused-expressions */
- } catch (e) {
- return null;
- }
- return getModernOffsetsFromPoints(outerNode, anchorNode, anchorOffset, focusNode, focusOffset);
- }
- /**
- * Returns {start, end} where `start` is the character/codepoint index of
- * (anchorNode, anchorOffset) within the textContent of `outerNode`, and
- * `end` is the index of (focusNode, focusOffset).
- *
- * Returns null if you pass in garbage input but we should probably just crash.
- *
- * Exported only for testing.
- */
- function getModernOffsetsFromPoints(outerNode, anchorNode, anchorOffset, focusNode, focusOffset) {
- var length = 0;
- var start = -1;
- var end = -1;
- var indexWithinAnchor = 0;
- var indexWithinFocus = 0;
- var node = outerNode;
- var parentNode = null;
- outer: while (true) {
- var next = null;
- while (true) {
- if (node === anchorNode && (anchorOffset === 0 || node.nodeType === TEXT_NODE)) {
- start = length + anchorOffset;
- }
- if (node === focusNode && (focusOffset === 0 || node.nodeType === TEXT_NODE)) {
- end = length + focusOffset;
- }
- if (node.nodeType === TEXT_NODE) {
- length += node.nodeValue.length;
- }
- if ((next = node.firstChild) === null) {
- break;
- } // Moving from `node` to its first child `next`.
- parentNode = node;
- node = next;
- }
- while (true) {
- if (node === outerNode) {
- // If `outerNode` has children, this is always the second time visiting
- // it. If it has no children, this is still the first loop, and the only
- // valid selection is anchorNode and focusNode both equal to this node
- // and both offsets 0, in which case we will have handled above.
- break outer;
- }
- if (parentNode === anchorNode && ++indexWithinAnchor === anchorOffset) {
- start = length;
- }
- if (parentNode === focusNode && ++indexWithinFocus === focusOffset) {
- end = length;
- }
- if ((next = node.nextSibling) !== null) {
- break;
- }
- node = parentNode;
- parentNode = node.parentNode;
- } // Moving from `node` to its next sibling `next`.
- node = next;
- }
- if (start === -1 || end === -1) {
- // This should never happen. (Would happen if the anchor/focus nodes aren't
- // actually inside the passed-in node.)
- return null;
- }
- return {
- start: start,
- end: end
- };
- }
- /**
- * In modern non-IE browsers, we can support both forward and backward
- * selections.
- *
- * Note: IE10+ supports the Selection object, but it does not support
- * the `extend` method, which means that even in modern IE, it's not possible
- * to programmatically create a backward selection. Thus, for all IE
- * versions, we use the old IE API to create our selections.
- *
- * @param {DOMElement|DOMTextNode} node
- * @param {object} offsets
- */
- function setOffsets(node, offsets) {
- var doc = node.ownerDocument || document;
- var win = doc && doc.defaultView || window; // Edge fails with "Object expected" in some scenarios.
- // (For instance: TinyMCE editor used in a list component that supports pasting to add more,
- // fails when pasting 100+ items)
- if (!win.getSelection) {
- return;
- }
- var selection = win.getSelection();
- var length = node.textContent.length;
- var start = Math.min(offsets.start, length);
- var end = offsets.end === undefined ? start : Math.min(offsets.end, length); // IE 11 uses modern selection, but doesn't support the extend method.
- // Flip backward selections, so we can set with a single range.
- if (!selection.extend && start > end) {
- var temp = end;
- end = start;
- start = temp;
- }
- var startMarker = getNodeForCharacterOffset(node, start);
- var endMarker = getNodeForCharacterOffset(node, end);
- if (startMarker && endMarker) {
- if (selection.rangeCount === 1 && selection.anchorNode === startMarker.node && selection.anchorOffset === startMarker.offset && selection.focusNode === endMarker.node && selection.focusOffset === endMarker.offset) {
- return;
- }
- var range = doc.createRange();
- range.setStart(startMarker.node, startMarker.offset);
- selection.removeAllRanges();
- if (start > end) {
- selection.addRange(range);
- selection.extend(endMarker.node, endMarker.offset);
- } else {
- range.setEnd(endMarker.node, endMarker.offset);
- selection.addRange(range);
- }
- }
- }
- function isTextNode(node) {
- return node && node.nodeType === TEXT_NODE;
- }
- function containsNode(outerNode, innerNode) {
- if (!outerNode || !innerNode) {
- return false;
- } else if (outerNode === innerNode) {
- return true;
- } else if (isTextNode(outerNode)) {
- return false;
- } else if (isTextNode(innerNode)) {
- return containsNode(outerNode, innerNode.parentNode);
- } else if ('contains' in outerNode) {
- return outerNode.contains(innerNode);
- } else if (outerNode.compareDocumentPosition) {
- return !!(outerNode.compareDocumentPosition(innerNode) & 16);
- } else {
- return false;
- }
- }
- function isInDocument(node) {
- return node && node.ownerDocument && containsNode(node.ownerDocument.documentElement, node);
- }
- function isSameOriginFrame(iframe) {
- try {
- // Accessing the contentDocument of a HTMLIframeElement can cause the browser
- // to throw, e.g. if it has a cross-origin src attribute.
- // Safari will show an error in the console when the access results in "Blocked a frame with origin". e.g:
- // iframe.contentDocument.defaultView;
- // A safety way is to access one of the cross origin properties: Window or Location
- // Which might result in "SecurityError" DOM Exception and it is compatible to Safari.
- // https://html.spec.whatwg.org/multipage/browsers.html#integration-with-idl
- return typeof iframe.contentWindow.location.href === 'string';
- } catch (err) {
- return false;
- }
- }
- function getActiveElementDeep() {
- var win = window;
- var element = getActiveElement();
- while (element instanceof win.HTMLIFrameElement) {
- if (isSameOriginFrame(element)) {
- win = element.contentWindow;
- } else {
- return element;
- }
- element = getActiveElement(win.document);
- }
- return element;
- }
- /**
- * @ReactInputSelection: React input selection module. Based on Selection.js,
- * but modified to be suitable for react and has a couple of bug fixes (doesn't
- * assume buttons have range selections allowed).
- * Input selection module for React.
- */
- /**
- * @hasSelectionCapabilities: we get the element types that support selection
- * from https://html.spec.whatwg.org/#do-not-apply, looking at `selectionStart`
- * and `selectionEnd` rows.
- */
- function hasSelectionCapabilities(elem) {
- var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase();
- return nodeName && (nodeName === 'input' && (elem.type === 'text' || elem.type === 'search' || elem.type === 'tel' || elem.type === 'url' || elem.type === 'password') || nodeName === 'textarea' || elem.contentEditable === 'true');
- }
- function getSelectionInformation() {
- var focusedElem = getActiveElementDeep();
- return {
- focusedElem: focusedElem,
- selectionRange: hasSelectionCapabilities(focusedElem) ? getSelection(focusedElem) : null
- };
- }
- /**
- * @restoreSelection: If any selection information was potentially lost,
- * restore it. This is useful when performing operations that could remove dom
- * nodes and place them back in, resulting in focus being lost.
- */
- function restoreSelection(priorSelectionInformation) {
- var curFocusedElem = getActiveElementDeep();
- var priorFocusedElem = priorSelectionInformation.focusedElem;
- var priorSelectionRange = priorSelectionInformation.selectionRange;
- if (curFocusedElem !== priorFocusedElem && isInDocument(priorFocusedElem)) {
- if (priorSelectionRange !== null && hasSelectionCapabilities(priorFocusedElem)) {
- setSelection(priorFocusedElem, priorSelectionRange);
- } // Focusing a node can change the scroll position, which is undesirable
- var ancestors = [];
- var ancestor = priorFocusedElem;
- while (ancestor = ancestor.parentNode) {
- if (ancestor.nodeType === ELEMENT_NODE) {
- ancestors.push({
- element: ancestor,
- left: ancestor.scrollLeft,
- top: ancestor.scrollTop
- });
- }
- }
- if (typeof priorFocusedElem.focus === 'function') {
- priorFocusedElem.focus();
- }
- for (var i = 0; i < ancestors.length; i++) {
- var info = ancestors[i];
- info.element.scrollLeft = info.left;
- info.element.scrollTop = info.top;
- }
- }
- }
- /**
- * @getSelection: Gets the selection bounds of a focused textarea, input or
- * contentEditable node.
- * -@input: Look up selection bounds of this input
- * -@return {start: selectionStart, end: selectionEnd}
- */
- function getSelection(input) {
- var selection;
- if ('selectionStart' in input) {
- // Modern browser with input or textarea.
- selection = {
- start: input.selectionStart,
- end: input.selectionEnd
- };
- } else {
- // Content editable or old IE textarea.
- selection = getOffsets(input);
- }
- return selection || {
- start: 0,
- end: 0
- };
- }
- /**
- * @setSelection: Sets the selection bounds of a textarea or input and focuses
- * the input.
- * -@input Set selection bounds of this input or textarea
- * -@offsets Object of same form that is returned from get*
- */
- function setSelection(input, offsets) {
- var start = offsets.start;
- var end = offsets.end;
- if (end === undefined) {
- end = start;
- }
- if ('selectionStart' in input) {
- input.selectionStart = start;
- input.selectionEnd = Math.min(end, input.value.length);
- } else {
- setOffsets(input, offsets);
- }
- }
- var skipSelectionChangeEvent = canUseDOM && 'documentMode' in document && document.documentMode <= 11;
- function registerEvents$3() {
- registerTwoPhaseEvent('onSelect', ['focusout', 'contextmenu', 'dragend', 'focusin', 'keydown', 'keyup', 'mousedown', 'mouseup', 'selectionchange']);
- }
- var activeElement$1 = null;
- var activeElementInst$1 = null;
- var lastSelection = null;
- var mouseDown = false;
- /**
- * Get an object which is a unique representation of the current selection.
- *
- * The return value will not be consistent across nodes or browsers, but
- * two identical selections on the same node will return identical objects.
- */
- function getSelection$1(node) {
- if ('selectionStart' in node && hasSelectionCapabilities(node)) {
- return {
- start: node.selectionStart,
- end: node.selectionEnd
- };
- } else {
- var win = node.ownerDocument && node.ownerDocument.defaultView || window;
- var selection = win.getSelection();
- return {
- anchorNode: selection.anchorNode,
- anchorOffset: selection.anchorOffset,
- focusNode: selection.focusNode,
- focusOffset: selection.focusOffset
- };
- }
- }
- /**
- * Get document associated with the event target.
- */
- function getEventTargetDocument(eventTarget) {
- return eventTarget.window === eventTarget ? eventTarget.document : eventTarget.nodeType === DOCUMENT_NODE ? eventTarget : eventTarget.ownerDocument;
- }
- /**
- * Poll selection to see whether it's changed.
- *
- * @param {object} nativeEvent
- * @param {object} nativeEventTarget
- * @return {?SyntheticEvent}
- */
- function constructSelectEvent(dispatchQueue, nativeEvent, nativeEventTarget) {
- // Ensure we have the right element, and that the user is not dragging a
- // selection (this matches native `select` event behavior). In HTML5, select
- // fires only on input and textarea thus if there's no focused element we
- // won't dispatch.
- var doc = getEventTargetDocument(nativeEventTarget);
- if (mouseDown || activeElement$1 == null || activeElement$1 !== getActiveElement(doc)) {
- return;
- } // Only fire when selection has actually changed.
- var currentSelection = getSelection$1(activeElement$1);
- if (!lastSelection || !shallowEqual(lastSelection, currentSelection)) {
- lastSelection = currentSelection;
- var listeners = accumulateTwoPhaseListeners(activeElementInst$1, 'onSelect');
- if (listeners.length > 0) {
- var event = new SyntheticEvent('onSelect', 'select', null, nativeEvent, nativeEventTarget);
- dispatchQueue.push({
- event: event,
- listeners: listeners
- });
- event.target = activeElement$1;
- }
- }
- }
- /**
- * This plugin creates an `onSelect` event that normalizes select events
- * across form elements.
- *
- * Supported elements are:
- * - input (see `isTextInputElement`)
- * - textarea
- * - contentEditable
- *
- * This differs from native browser implementations in the following ways:
- * - Fires on contentEditable fields as well as inputs.
- * - Fires for collapsed selection.
- * - Fires after user input.
- */
- function extractEvents$3(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget, eventSystemFlags, targetContainer) {
- var targetNode = targetInst ? getNodeFromInstance(targetInst) : window;
- switch (domEventName) {
- // Track the input node that has focus.
- case 'focusin':
- if (isTextInputElement(targetNode) || targetNode.contentEditable === 'true') {
- activeElement$1 = targetNode;
- activeElementInst$1 = targetInst;
- lastSelection = null;
- }
- break;
- case 'focusout':
- activeElement$1 = null;
- activeElementInst$1 = null;
- lastSelection = null;
- break;
- // Don't fire the event while the user is dragging. This matches the
- // semantics of the native select event.
- case 'mousedown':
- mouseDown = true;
- break;
- case 'contextmenu':
- case 'mouseup':
- case 'dragend':
- mouseDown = false;
- constructSelectEvent(dispatchQueue, nativeEvent, nativeEventTarget);
- break;
- // Chrome and IE fire non-standard event when selection is changed (and
- // sometimes when it hasn't). IE's event fires out of order with respect
- // to key and input events on deletion, so we discard it.
- //
- // Firefox doesn't support selectionchange, so check selection status
- // after each key entry. The selection changes after keydown and before
- // keyup, but we check on keydown as well in the case of holding down a
- // key, when multiple keydown events are fired but only one keyup is.
- // This is also our approach for IE handling, for the reason above.
- case 'selectionchange':
- if (skipSelectionChangeEvent) {
- break;
- }
- // falls through
- case 'keydown':
- case 'keyup':
- constructSelectEvent(dispatchQueue, nativeEvent, nativeEventTarget);
- }
- }
- /**
- * Generate a mapping of standard vendor prefixes using the defined style property and event name.
- *
- * @param {string} styleProp
- * @param {string} eventName
- * @returns {object}
- */
- function makePrefixMap(styleProp, eventName) {
- var prefixes = {};
- prefixes[styleProp.toLowerCase()] = eventName.toLowerCase();
- prefixes['Webkit' + styleProp] = 'webkit' + eventName;
- prefixes['Moz' + styleProp] = 'moz' + eventName;
- return prefixes;
- }
- /**
- * A list of event names to a configurable list of vendor prefixes.
- */
- var vendorPrefixes = {
- animationend: makePrefixMap('Animation', 'AnimationEnd'),
- animationiteration: makePrefixMap('Animation', 'AnimationIteration'),
- animationstart: makePrefixMap('Animation', 'AnimationStart'),
- transitionend: makePrefixMap('Transition', 'TransitionEnd')
- };
- /**
- * Event names that have already been detected and prefixed (if applicable).
- */
- var prefixedEventNames = {};
- /**
- * Element to check for prefixes on.
- */
- var style = {};
- /**
- * Bootstrap if a DOM exists.
- */
- if (canUseDOM) {
- style = document.createElement('div').style; // On some platforms, in particular some releases of Android 4.x,
- // the un-prefixed "animation" and "transition" properties are defined on the
- // style object but the events that fire will still be prefixed, so we need
- // to check if the un-prefixed events are usable, and if not remove them from the map.
- if (!('AnimationEvent' in window)) {
- delete vendorPrefixes.animationend.animation;
- delete vendorPrefixes.animationiteration.animation;
- delete vendorPrefixes.animationstart.animation;
- } // Same as above
- if (!('TransitionEvent' in window)) {
- delete vendorPrefixes.transitionend.transition;
- }
- }
- /**
- * Attempts to determine the correct vendor prefixed event name.
- *
- * @param {string} eventName
- * @returns {string}
- */
- function getVendorPrefixedEventName(eventName) {
- if (prefixedEventNames[eventName]) {
- return prefixedEventNames[eventName];
- } else if (!vendorPrefixes[eventName]) {
- return eventName;
- }
- var prefixMap = vendorPrefixes[eventName];
- for (var styleProp in prefixMap) {
- if (prefixMap.hasOwnProperty(styleProp) && styleProp in style) {
- return prefixedEventNames[eventName] = prefixMap[styleProp];
- }
- }
- return eventName;
- }
- var ANIMATION_END = getVendorPrefixedEventName('animationend');
- var ANIMATION_ITERATION = getVendorPrefixedEventName('animationiteration');
- var ANIMATION_START = getVendorPrefixedEventName('animationstart');
- var TRANSITION_END = getVendorPrefixedEventName('transitionend');
- var topLevelEventsToReactNames = new Map(); // NOTE: Capitalization is important in this list!
- //
- // E.g. it needs "pointerDown", not "pointerdown".
- // This is because we derive both React name ("onPointerDown")
- // and DOM name ("pointerdown") from the same list.
- //
- // Exceptions that don't match this convention are listed separately.
- //
- // prettier-ignore
- var simpleEventPluginEvents = ['abort', 'auxClick', 'cancel', 'canPlay', 'canPlayThrough', 'click', 'close', 'contextMenu', 'copy', 'cut', 'drag', 'dragEnd', 'dragEnter', 'dragExit', 'dragLeave', 'dragOver', 'dragStart', 'drop', 'durationChange', 'emptied', 'encrypted', 'ended', 'error', 'gotPointerCapture', 'input', 'invalid', 'keyDown', 'keyPress', 'keyUp', 'load', 'loadedData', 'loadedMetadata', 'loadStart', 'lostPointerCapture', 'mouseDown', 'mouseMove', 'mouseOut', 'mouseOver', 'mouseUp', 'paste', 'pause', 'play', 'playing', 'pointerCancel', 'pointerDown', 'pointerMove', 'pointerOut', 'pointerOver', 'pointerUp', 'progress', 'rateChange', 'reset', 'resize', 'seeked', 'seeking', 'stalled', 'submit', 'suspend', 'timeUpdate', 'touchCancel', 'touchEnd', 'touchStart', 'volumeChange', 'scroll', 'toggle', 'touchMove', 'waiting', 'wheel'];
- function registerSimpleEvent(domEventName, reactName) {
- topLevelEventsToReactNames.set(domEventName, reactName);
- registerTwoPhaseEvent(reactName, [domEventName]);
- }
- function registerSimpleEvents() {
- for (var i = 0; i < simpleEventPluginEvents.length; i++) {
- var eventName = simpleEventPluginEvents[i];
- var domEventName = eventName.toLowerCase();
- var capitalizedEvent = eventName[0].toUpperCase() + eventName.slice(1);
- registerSimpleEvent(domEventName, 'on' + capitalizedEvent);
- } // Special cases where event names don't match.
- registerSimpleEvent(ANIMATION_END, 'onAnimationEnd');
- registerSimpleEvent(ANIMATION_ITERATION, 'onAnimationIteration');
- registerSimpleEvent(ANIMATION_START, 'onAnimationStart');
- registerSimpleEvent('dblclick', 'onDoubleClick');
- registerSimpleEvent('focusin', 'onFocus');
- registerSimpleEvent('focusout', 'onBlur');
- registerSimpleEvent(TRANSITION_END, 'onTransitionEnd');
- }
- function extractEvents$4(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget, eventSystemFlags, targetContainer) {
- var reactName = topLevelEventsToReactNames.get(domEventName);
- if (reactName === undefined) {
- return;
- }
- var SyntheticEventCtor = SyntheticEvent;
- var reactEventType = domEventName;
- switch (domEventName) {
- case 'keypress':
- // Firefox creates a keypress event for function keys too. This removes
- // the unwanted keypress events. Enter is however both printable and
- // non-printable. One would expect Tab to be as well (but it isn't).
- if (getEventCharCode(nativeEvent) === 0) {
- return;
- }
- /* falls through */
- case 'keydown':
- case 'keyup':
- SyntheticEventCtor = SyntheticKeyboardEvent;
- break;
- case 'focusin':
- reactEventType = 'focus';
- SyntheticEventCtor = SyntheticFocusEvent;
- break;
- case 'focusout':
- reactEventType = 'blur';
- SyntheticEventCtor = SyntheticFocusEvent;
- break;
- case 'beforeblur':
- case 'afterblur':
- SyntheticEventCtor = SyntheticFocusEvent;
- break;
- case 'click':
- // Firefox creates a click event on right mouse clicks. This removes the
- // unwanted click events.
- if (nativeEvent.button === 2) {
- return;
- }
- /* falls through */
- case 'auxclick':
- case 'dblclick':
- case 'mousedown':
- case 'mousemove':
- case 'mouseup': // TODO: Disabled elements should not respond to mouse events
- /* falls through */
- case 'mouseout':
- case 'mouseover':
- case 'contextmenu':
- SyntheticEventCtor = SyntheticMouseEvent;
- break;
- case 'drag':
- case 'dragend':
- case 'dragenter':
- case 'dragexit':
- case 'dragleave':
- case 'dragover':
- case 'dragstart':
- case 'drop':
- SyntheticEventCtor = SyntheticDragEvent;
- break;
- case 'touchcancel':
- case 'touchend':
- case 'touchmove':
- case 'touchstart':
- SyntheticEventCtor = SyntheticTouchEvent;
- break;
- case ANIMATION_END:
- case ANIMATION_ITERATION:
- case ANIMATION_START:
- SyntheticEventCtor = SyntheticAnimationEvent;
- break;
- case TRANSITION_END:
- SyntheticEventCtor = SyntheticTransitionEvent;
- break;
- case 'scroll':
- SyntheticEventCtor = SyntheticUIEvent;
- break;
- case 'wheel':
- SyntheticEventCtor = SyntheticWheelEvent;
- break;
- case 'copy':
- case 'cut':
- case 'paste':
- SyntheticEventCtor = SyntheticClipboardEvent;
- break;
- case 'gotpointercapture':
- case 'lostpointercapture':
- case 'pointercancel':
- case 'pointerdown':
- case 'pointermove':
- case 'pointerout':
- case 'pointerover':
- case 'pointerup':
- SyntheticEventCtor = SyntheticPointerEvent;
- break;
- }
- var inCapturePhase = (eventSystemFlags & IS_CAPTURE_PHASE) !== 0;
- {
- // Some events don't bubble in the browser.
- // In the past, React has always bubbled them, but this can be surprising.
- // We're going to try aligning closer to the browser behavior by not bubbling
- // them in React either. We'll start by not bubbling onScroll, and then expand.
- var accumulateTargetOnly = !inCapturePhase && // TODO: ideally, we'd eventually add all events from
- // nonDelegatedEvents list in DOMPluginEventSystem.
- // Then we can remove this special list.
- // This is a breaking change that can wait until React 18.
- domEventName === 'scroll';
- var _listeners = accumulateSinglePhaseListeners(targetInst, reactName, nativeEvent.type, inCapturePhase, accumulateTargetOnly);
- if (_listeners.length > 0) {
- // Intentionally create event lazily.
- var _event = new SyntheticEventCtor(reactName, reactEventType, null, nativeEvent, nativeEventTarget);
- dispatchQueue.push({
- event: _event,
- listeners: _listeners
- });
- }
- }
- }
- // TODO: remove top-level side effect.
- registerSimpleEvents();
- registerEvents$2();
- registerEvents$1();
- registerEvents$3();
- registerEvents();
- function extractEvents$5(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget, eventSystemFlags, targetContainer) {
- // TODO: we should remove the concept of a "SimpleEventPlugin".
- // This is the basic functionality of the event system. All
- // the other plugins are essentially polyfills. So the plugin
- // should probably be inlined somewhere and have its logic
- // be core the to event system. This would potentially allow
- // us to ship builds of React without the polyfilled plugins below.
- extractEvents$4(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget, eventSystemFlags);
- var shouldProcessPolyfillPlugins = (eventSystemFlags & SHOULD_NOT_PROCESS_POLYFILL_EVENT_PLUGINS) === 0; // We don't process these events unless we are in the
- // event's native "bubble" phase, which means that we're
- // not in the capture phase. That's because we emulate
- // the capture phase here still. This is a trade-off,
- // because in an ideal world we would not emulate and use
- // the phases properly, like we do with the SimpleEvent
- // plugin. However, the plugins below either expect
- // emulation (EnterLeave) or use state localized to that
- // plugin (BeforeInput, Change, Select). The state in
- // these modules complicates things, as you'll essentially
- // get the case where the capture phase event might change
- // state, only for the following bubble event to come in
- // later and not trigger anything as the state now
- // invalidates the heuristics of the event plugin. We
- // could alter all these plugins to work in such ways, but
- // that might cause other unknown side-effects that we
- // can't foresee right now.
- if (shouldProcessPolyfillPlugins) {
- extractEvents$2(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget);
- extractEvents$1(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget);
- extractEvents$3(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget);
- extractEvents(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget);
- }
- } // List of events that need to be individually attached to media elements.
- var mediaEventTypes = ['abort', 'canplay', 'canplaythrough', 'durationchange', 'emptied', 'encrypted', 'ended', 'error', 'loadeddata', 'loadedmetadata', 'loadstart', 'pause', 'play', 'playing', 'progress', 'ratechange', 'resize', 'seeked', 'seeking', 'stalled', 'suspend', 'timeupdate', 'volumechange', 'waiting']; // We should not delegate these events to the container, but rather
- // set them on the actual target element itself. This is primarily
- // because these events do not consistently bubble in the DOM.
- var nonDelegatedEvents = new Set(['cancel', 'close', 'invalid', 'load', 'scroll', 'toggle'].concat(mediaEventTypes));
- function executeDispatch(event, listener, currentTarget) {
- var type = event.type || 'unknown-event';
- event.currentTarget = currentTarget;
- invokeGuardedCallbackAndCatchFirstError(type, listener, undefined, event);
- event.currentTarget = null;
- }
- function processDispatchQueueItemsInOrder(event, dispatchListeners, inCapturePhase) {
- var previousInstance;
- if (inCapturePhase) {
- for (var i = dispatchListeners.length - 1; i >= 0; i--) {
- var _dispatchListeners$i = dispatchListeners[i],
- instance = _dispatchListeners$i.instance,
- currentTarget = _dispatchListeners$i.currentTarget,
- listener = _dispatchListeners$i.listener;
- if (instance !== previousInstance && event.isPropagationStopped()) {
- return;
- }
- executeDispatch(event, listener, currentTarget);
- previousInstance = instance;
- }
- } else {
- for (var _i = 0; _i < dispatchListeners.length; _i++) {
- var _dispatchListeners$_i = dispatchListeners[_i],
- _instance = _dispatchListeners$_i.instance,
- _currentTarget = _dispatchListeners$_i.currentTarget,
- _listener = _dispatchListeners$_i.listener;
- if (_instance !== previousInstance && event.isPropagationStopped()) {
- return;
- }
- executeDispatch(event, _listener, _currentTarget);
- previousInstance = _instance;
- }
- }
- }
- function processDispatchQueue(dispatchQueue, eventSystemFlags) {
- var inCapturePhase = (eventSystemFlags & IS_CAPTURE_PHASE) !== 0;
- for (var i = 0; i < dispatchQueue.length; i++) {
- var _dispatchQueue$i = dispatchQueue[i],
- event = _dispatchQueue$i.event,
- listeners = _dispatchQueue$i.listeners;
- processDispatchQueueItemsInOrder(event, listeners, inCapturePhase); // event system doesn't use pooling.
- } // This would be a good time to rethrow if any of the event handlers threw.
- rethrowCaughtError();
- }
- function dispatchEventsForPlugins(domEventName, eventSystemFlags, nativeEvent, targetInst, targetContainer) {
- var nativeEventTarget = getEventTarget(nativeEvent);
- var dispatchQueue = [];
- extractEvents$5(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget, eventSystemFlags);
- processDispatchQueue(dispatchQueue, eventSystemFlags);
- }
- function listenToNonDelegatedEvent(domEventName, targetElement) {
- {
- if (!nonDelegatedEvents.has(domEventName)) {
- error('Did not expect a listenToNonDelegatedEvent() call for "%s". ' + 'This is a bug in React. Please file an issue.', domEventName);
- }
- }
- var isCapturePhaseListener = false;
- var listenerSet = getEventListenerSet(targetElement);
- var listenerSetKey = getListenerSetKey(domEventName, isCapturePhaseListener);
- if (!listenerSet.has(listenerSetKey)) {
- addTrappedEventListener(targetElement, domEventName, IS_NON_DELEGATED, isCapturePhaseListener);
- listenerSet.add(listenerSetKey);
- }
- }
- function listenToNativeEvent(domEventName, isCapturePhaseListener, target) {
- {
- if (nonDelegatedEvents.has(domEventName) && !isCapturePhaseListener) {
- error('Did not expect a listenToNativeEvent() call for "%s" in the bubble phase. ' + 'This is a bug in React. Please file an issue.', domEventName);
- }
- }
- var eventSystemFlags = 0;
- if (isCapturePhaseListener) {
- eventSystemFlags |= IS_CAPTURE_PHASE;
- }
- addTrappedEventListener(target, domEventName, eventSystemFlags, isCapturePhaseListener);
- } // This is only used by createEventHandle when the
- var listeningMarker = '_reactListening' + Math.random().toString(36).slice(2);
- function listenToAllSupportedEvents(rootContainerElement) {
- if (!rootContainerElement[listeningMarker]) {
- rootContainerElement[listeningMarker] = true;
- allNativeEvents.forEach(function (domEventName) {
- // We handle selectionchange separately because it
- // doesn't bubble and needs to be on the document.
- if (domEventName !== 'selectionchange') {
- if (!nonDelegatedEvents.has(domEventName)) {
- listenToNativeEvent(domEventName, false, rootContainerElement);
- }
- listenToNativeEvent(domEventName, true, rootContainerElement);
- }
- });
- var ownerDocument = rootContainerElement.nodeType === DOCUMENT_NODE ? rootContainerElement : rootContainerElement.ownerDocument;
- if (ownerDocument !== null) {
- // The selectionchange event also needs deduplication
- // but it is attached to the document.
- if (!ownerDocument[listeningMarker]) {
- ownerDocument[listeningMarker] = true;
- listenToNativeEvent('selectionchange', false, ownerDocument);
- }
- }
- }
- }
- function addTrappedEventListener(targetContainer, domEventName, eventSystemFlags, isCapturePhaseListener, isDeferredListenerForLegacyFBSupport) {
- var listener = createEventListenerWrapperWithPriority(targetContainer, domEventName, eventSystemFlags); // If passive option is not supported, then the event will be
- // active and not passive.
- var isPassiveListener = undefined;
- if (passiveBrowserEventsSupported) {
- // Browsers introduced an intervention, making these events
- // passive by default on document. React doesn't bind them
- // to document anymore, but changing this now would undo
- // the performance wins from the change. So we emulate
- // the existing behavior manually on the roots now.
- // https://github.com/facebook/react/issues/19651
- if (domEventName === 'touchstart' || domEventName === 'touchmove' || domEventName === 'wheel') {
- isPassiveListener = true;
- }
- }
- targetContainer = targetContainer;
- var unsubscribeListener; // When legacyFBSupport is enabled, it's for when we
- if (isCapturePhaseListener) {
- if (isPassiveListener !== undefined) {
- unsubscribeListener = addEventCaptureListenerWithPassiveFlag(targetContainer, domEventName, listener, isPassiveListener);
- } else {
- unsubscribeListener = addEventCaptureListener(targetContainer, domEventName, listener);
- }
- } else {
- if (isPassiveListener !== undefined) {
- unsubscribeListener = addEventBubbleListenerWithPassiveFlag(targetContainer, domEventName, listener, isPassiveListener);
- } else {
- unsubscribeListener = addEventBubbleListener(targetContainer, domEventName, listener);
- }
- }
- }
- function isMatchingRootContainer(grandContainer, targetContainer) {
- return grandContainer === targetContainer || grandContainer.nodeType === COMMENT_NODE && grandContainer.parentNode === targetContainer;
- }
- function dispatchEventForPluginEventSystem(domEventName, eventSystemFlags, nativeEvent, targetInst, targetContainer) {
- var ancestorInst = targetInst;
- if ((eventSystemFlags & IS_EVENT_HANDLE_NON_MANAGED_NODE) === 0 && (eventSystemFlags & IS_NON_DELEGATED) === 0) {
- var targetContainerNode = targetContainer; // If we are using the legacy FB support flag, we
- if (targetInst !== null) {
- // The below logic attempts to work out if we need to change
- // the target fiber to a different ancestor. We had similar logic
- // in the legacy event system, except the big difference between
- // systems is that the modern event system now has an event listener
- // attached to each React Root and React Portal Root. Together,
- // the DOM nodes representing these roots are the "rootContainer".
- // To figure out which ancestor instance we should use, we traverse
- // up the fiber tree from the target instance and attempt to find
- // root boundaries that match that of our current "rootContainer".
- // If we find that "rootContainer", we find the parent fiber
- // sub-tree for that root and make that our ancestor instance.
- var node = targetInst;
- mainLoop: while (true) {
- if (node === null) {
- return;
- }
- var nodeTag = node.tag;
- if (nodeTag === HostRoot || nodeTag === HostPortal) {
- var container = node.stateNode.containerInfo;
- if (isMatchingRootContainer(container, targetContainerNode)) {
- break;
- }
- if (nodeTag === HostPortal) {
- // The target is a portal, but it's not the rootContainer we're looking for.
- // Normally portals handle their own events all the way down to the root.
- // So we should be able to stop now. However, we don't know if this portal
- // was part of *our* root.
- var grandNode = node.return;
- while (grandNode !== null) {
- var grandTag = grandNode.tag;
- if (grandTag === HostRoot || grandTag === HostPortal) {
- var grandContainer = grandNode.stateNode.containerInfo;
- if (isMatchingRootContainer(grandContainer, targetContainerNode)) {
- // This is the rootContainer we're looking for and we found it as
- // a parent of the Portal. That means we can ignore it because the
- // Portal will bubble through to us.
- return;
- }
- }
- grandNode = grandNode.return;
- }
- } // Now we need to find it's corresponding host fiber in the other
- // tree. To do this we can use getClosestInstanceFromNode, but we
- // need to validate that the fiber is a host instance, otherwise
- // we need to traverse up through the DOM till we find the correct
- // node that is from the other tree.
- while (container !== null) {
- var parentNode = getClosestInstanceFromNode(container);
- if (parentNode === null) {
- return;
- }
- var parentTag = parentNode.tag;
- if (parentTag === HostComponent || parentTag === HostText) {
- node = ancestorInst = parentNode;
- continue mainLoop;
- }
- container = container.parentNode;
- }
- }
- node = node.return;
- }
- }
- }
- batchedUpdates(function () {
- return dispatchEventsForPlugins(domEventName, eventSystemFlags, nativeEvent, ancestorInst);
- });
- }
- function createDispatchListener(instance, listener, currentTarget) {
- return {
- instance: instance,
- listener: listener,
- currentTarget: currentTarget
- };
- }
- function accumulateSinglePhaseListeners(targetFiber, reactName, nativeEventType, inCapturePhase, accumulateTargetOnly, nativeEvent) {
- var captureName = reactName !== null ? reactName + 'Capture' : null;
- var reactEventName = inCapturePhase ? captureName : reactName;
- var listeners = [];
- var instance = targetFiber;
- var lastHostComponent = null; // Accumulate all instances and listeners via the target -> root path.
- while (instance !== null) {
- var _instance2 = instance,
- stateNode = _instance2.stateNode,
- tag = _instance2.tag; // Handle listeners that are on HostComponents (i.e. <div>)
- if (tag === HostComponent && stateNode !== null) {
- lastHostComponent = stateNode; // createEventHandle listeners
- if (reactEventName !== null) {
- var listener = getListener(instance, reactEventName);
- if (listener != null) {
- listeners.push(createDispatchListener(instance, listener, lastHostComponent));
- }
- }
- } // If we are only accumulating events for the target, then we don't
- // continue to propagate through the React fiber tree to find other
- // listeners.
- if (accumulateTargetOnly) {
- break;
- } // If we are processing the onBeforeBlur event, then we need to take
- instance = instance.return;
- }
- return listeners;
- } // We should only use this function for:
- // - BeforeInputEventPlugin
- // - ChangeEventPlugin
- // - SelectEventPlugin
- // This is because we only process these plugins
- // in the bubble phase, so we need to accumulate two
- // phase event listeners (via emulation).
- function accumulateTwoPhaseListeners(targetFiber, reactName) {
- var captureName = reactName + 'Capture';
- var listeners = [];
- var instance = targetFiber; // Accumulate all instances and listeners via the target -> root path.
- while (instance !== null) {
- var _instance3 = instance,
- stateNode = _instance3.stateNode,
- tag = _instance3.tag; // Handle listeners that are on HostComponents (i.e. <div>)
- if (tag === HostComponent && stateNode !== null) {
- var currentTarget = stateNode;
- var captureListener = getListener(instance, captureName);
- if (captureListener != null) {
- listeners.unshift(createDispatchListener(instance, captureListener, currentTarget));
- }
- var bubbleListener = getListener(instance, reactName);
- if (bubbleListener != null) {
- listeners.push(createDispatchListener(instance, bubbleListener, currentTarget));
- }
- }
- instance = instance.return;
- }
- return listeners;
- }
- function getParent(inst) {
- if (inst === null) {
- return null;
- }
- do {
- inst = inst.return; // TODO: If this is a HostRoot we might want to bail out.
- // That is depending on if we want nested subtrees (layers) to bubble
- // events to their parent. We could also go through parentNode on the
- // host node but that wouldn't work for React Native and doesn't let us
- // do the portal feature.
- } while (inst && inst.tag !== HostComponent);
- if (inst) {
- return inst;
- }
- return null;
- }
- /**
- * Return the lowest common ancestor of A and B, or null if they are in
- * different trees.
- */
- function getLowestCommonAncestor(instA, instB) {
- var nodeA = instA;
- var nodeB = instB;
- var depthA = 0;
- for (var tempA = nodeA; tempA; tempA = getParent(tempA)) {
- depthA++;
- }
- var depthB = 0;
- for (var tempB = nodeB; tempB; tempB = getParent(tempB)) {
- depthB++;
- } // If A is deeper, crawl up.
- while (depthA - depthB > 0) {
- nodeA = getParent(nodeA);
- depthA--;
- } // If B is deeper, crawl up.
- while (depthB - depthA > 0) {
- nodeB = getParent(nodeB);
- depthB--;
- } // Walk in lockstep until we find a match.
- var depth = depthA;
- while (depth--) {
- if (nodeA === nodeB || nodeB !== null && nodeA === nodeB.alternate) {
- return nodeA;
- }
- nodeA = getParent(nodeA);
- nodeB = getParent(nodeB);
- }
- return null;
- }
- function accumulateEnterLeaveListenersForEvent(dispatchQueue, event, target, common, inCapturePhase) {
- var registrationName = event._reactName;
- var listeners = [];
- var instance = target;
- while (instance !== null) {
- if (instance === common) {
- break;
- }
- var _instance4 = instance,
- alternate = _instance4.alternate,
- stateNode = _instance4.stateNode,
- tag = _instance4.tag;
- if (alternate !== null && alternate === common) {
- break;
- }
- if (tag === HostComponent && stateNode !== null) {
- var currentTarget = stateNode;
- if (inCapturePhase) {
- var captureListener = getListener(instance, registrationName);
- if (captureListener != null) {
- listeners.unshift(createDispatchListener(instance, captureListener, currentTarget));
- }
- } else if (!inCapturePhase) {
- var bubbleListener = getListener(instance, registrationName);
- if (bubbleListener != null) {
- listeners.push(createDispatchListener(instance, bubbleListener, currentTarget));
- }
- }
- }
- instance = instance.return;
- }
- if (listeners.length !== 0) {
- dispatchQueue.push({
- event: event,
- listeners: listeners
- });
- }
- } // We should only use this function for:
- // - EnterLeaveEventPlugin
- // This is because we only process this plugin
- // in the bubble phase, so we need to accumulate two
- // phase event listeners.
- function accumulateEnterLeaveTwoPhaseListeners(dispatchQueue, leaveEvent, enterEvent, from, to) {
- var common = from && to ? getLowestCommonAncestor(from, to) : null;
- if (from !== null) {
- accumulateEnterLeaveListenersForEvent(dispatchQueue, leaveEvent, from, common, false);
- }
- if (to !== null && enterEvent !== null) {
- accumulateEnterLeaveListenersForEvent(dispatchQueue, enterEvent, to, common, true);
- }
- }
- function getListenerSetKey(domEventName, capture) {
- return domEventName + "__" + (capture ? 'capture' : 'bubble');
- }
- var didWarnInvalidHydration = false;
- var DANGEROUSLY_SET_INNER_HTML = 'dangerouslySetInnerHTML';
- var SUPPRESS_CONTENT_EDITABLE_WARNING = 'suppressContentEditableWarning';
- var SUPPRESS_HYDRATION_WARNING = 'suppressHydrationWarning';
- var AUTOFOCUS = 'autoFocus';
- var CHILDREN = 'children';
- var STYLE = 'style';
- var HTML$1 = '__html';
- var warnedUnknownTags;
- var validatePropertiesInDevelopment;
- var warnForPropDifference;
- var warnForExtraAttributes;
- var warnForInvalidEventListener;
- var canDiffStyleForHydrationWarning;
- var normalizeHTML;
- {
- warnedUnknownTags = {
- // There are working polyfills for <dialog>. Let people use it.
- dialog: true,
- // Electron ships a custom <webview> tag to display external web content in
- // an isolated frame and process.
- // This tag is not present in non Electron environments such as JSDom which
- // is often used for testing purposes.
- // @see https://electronjs.org/docs/api/webview-tag
- webview: true
- };
- validatePropertiesInDevelopment = function (type, props) {
- validateProperties(type, props);
- validateProperties$1(type, props);
- validateProperties$2(type, props, {
- registrationNameDependencies: registrationNameDependencies,
- possibleRegistrationNames: possibleRegistrationNames
- });
- }; // IE 11 parses & normalizes the style attribute as opposed to other
- // browsers. It adds spaces and sorts the properties in some
- // non-alphabetical order. Handling that would require sorting CSS
- // properties in the client & server versions or applying
- // `expectedStyle` to a temporary DOM node to read its `style` attribute
- // normalized. Since it only affects IE, we're skipping style warnings
- // in that browser completely in favor of doing all that work.
- // See https://github.com/facebook/react/issues/11807
- canDiffStyleForHydrationWarning = canUseDOM && !document.documentMode;
- warnForPropDifference = function (propName, serverValue, clientValue) {
- if (didWarnInvalidHydration) {
- return;
- }
- var normalizedClientValue = normalizeMarkupForTextOrAttribute(clientValue);
- var normalizedServerValue = normalizeMarkupForTextOrAttribute(serverValue);
- if (normalizedServerValue === normalizedClientValue) {
- return;
- }
- didWarnInvalidHydration = true;
- error('Prop `%s` did not match. Server: %s Client: %s', propName, JSON.stringify(normalizedServerValue), JSON.stringify(normalizedClientValue));
- };
- warnForExtraAttributes = function (attributeNames) {
- if (didWarnInvalidHydration) {
- return;
- }
- didWarnInvalidHydration = true;
- var names = [];
- attributeNames.forEach(function (name) {
- names.push(name);
- });
- error('Extra attributes from the server: %s', names);
- };
- warnForInvalidEventListener = function (registrationName, listener) {
- if (listener === false) {
- error('Expected `%s` listener to be a function, instead got `false`.\n\n' + 'If you used to conditionally omit it with %s={condition && value}, ' + 'pass %s={condition ? value : undefined} instead.', registrationName, registrationName, registrationName);
- } else {
- error('Expected `%s` listener to be a function, instead got a value of `%s` type.', registrationName, typeof listener);
- }
- }; // Parse the HTML and read it back to normalize the HTML string so that it
- // can be used for comparison.
- normalizeHTML = function (parent, html) {
- // We could have created a separate document here to avoid
- // re-initializing custom elements if they exist. But this breaks
- // how <noscript> is being handled. So we use the same document.
- // See the discussion in https://github.com/facebook/react/pull/11157.
- var testElement = parent.namespaceURI === HTML_NAMESPACE ? parent.ownerDocument.createElement(parent.tagName) : parent.ownerDocument.createElementNS(parent.namespaceURI, parent.tagName);
- testElement.innerHTML = html;
- return testElement.innerHTML;
- };
- } // HTML parsing normalizes CR and CRLF to LF.
- // It also can turn \u0000 into \uFFFD inside attributes.
- // https://www.w3.org/TR/html5/single-page.html#preprocessing-the-input-stream
- // If we have a mismatch, it might be caused by that.
- // We will still patch up in this case but not fire the warning.
- var NORMALIZE_NEWLINES_REGEX = /\r\n?/g;
- var NORMALIZE_NULL_AND_REPLACEMENT_REGEX = /\u0000|\uFFFD/g;
- function normalizeMarkupForTextOrAttribute(markup) {
- {
- checkHtmlStringCoercion(markup);
- }
- var markupString = typeof markup === 'string' ? markup : '' + markup;
- return markupString.replace(NORMALIZE_NEWLINES_REGEX, '\n').replace(NORMALIZE_NULL_AND_REPLACEMENT_REGEX, '');
- }
- function checkForUnmatchedText(serverText, clientText, isConcurrentMode, shouldWarnDev) {
- var normalizedClientText = normalizeMarkupForTextOrAttribute(clientText);
- var normalizedServerText = normalizeMarkupForTextOrAttribute(serverText);
- if (normalizedServerText === normalizedClientText) {
- return;
- }
- if (shouldWarnDev) {
- {
- if (!didWarnInvalidHydration) {
- didWarnInvalidHydration = true;
- error('Text content did not match. Server: "%s" Client: "%s"', normalizedServerText, normalizedClientText);
- }
- }
- }
- if (isConcurrentMode && enableClientRenderFallbackOnTextMismatch) {
- // In concurrent roots, we throw when there's a text mismatch and revert to
- // client rendering, up to the nearest Suspense boundary.
- throw new Error('Text content does not match server-rendered HTML.');
- }
- }
- function getOwnerDocumentFromRootContainer(rootContainerElement) {
- return rootContainerElement.nodeType === DOCUMENT_NODE ? rootContainerElement : rootContainerElement.ownerDocument;
- }
- function noop() { }
- function trapClickOnNonInteractiveElement(node) {
- // Mobile Safari does not fire properly bubble click events on
- // non-interactive elements, which means delegated click listeners do not
- // fire. The workaround for this bug involves attaching an empty click
- // listener on the target node.
- // https://www.quirksmode.org/blog/archives/2010/09/click_event_del.html
- // Just set it using the onclick property so that we don't have to manage any
- // bookkeeping for it. Not sure if we need to clear it when the listener is
- // removed.
- // TODO: Only do this for the relevant Safaris maybe?
- node.onclick = noop;
- }
- function setInitialDOMProperties(tag, domElement, rootContainerElement, nextProps, isCustomComponentTag) {
- for (var propKey in nextProps) {
- if (!nextProps.hasOwnProperty(propKey)) {
- continue;
- }
- var nextProp = nextProps[propKey];
- if (propKey === STYLE) {
- {
- if (nextProp) {
- // Freeze the next style object so that we can assume it won't be
- // mutated. We have already warned for this in the past.
- Object.freeze(nextProp);
- }
- } // Relies on `updateStylesByID` not mutating `styleUpdates`.
- setValueForStyles(domElement, nextProp);
- } else if (propKey === DANGEROUSLY_SET_INNER_HTML) {
- var nextHtml = nextProp ? nextProp[HTML$1] : undefined;
- if (nextHtml != null) {
- setInnerHTML(domElement, nextHtml);
- }
- } else if (propKey === CHILDREN) {
- if (typeof nextProp === 'string') {
- // Avoid setting initial textContent when the text is empty. In IE11 setting
- // textContent on a <textarea> will cause the placeholder to not
- // show within the <textarea> until it has been focused and blurred again.
- // https://github.com/facebook/react/issues/6731#issuecomment-254874553
- var canSetTextContent = tag !== 'textarea' || nextProp !== '';
- if (canSetTextContent) {
- setTextContent(domElement, nextProp);
- }
- } else if (typeof nextProp === 'number') {
- setTextContent(domElement, '' + nextProp);
- }
- } else if (propKey === SUPPRESS_CONTENT_EDITABLE_WARNING || propKey === SUPPRESS_HYDRATION_WARNING); else if (propKey === AUTOFOCUS); else if (registrationNameDependencies.hasOwnProperty(propKey)) {
- if (nextProp != null) {
- if (typeof nextProp !== 'function') {
- warnForInvalidEventListener(propKey, nextProp);
- }
- if (propKey === 'onScroll') {
- listenToNonDelegatedEvent('scroll', domElement);
- }
- }
- } else if (nextProp != null) {
- setValueForProperty(domElement, propKey, nextProp, isCustomComponentTag);
- }
- }
- }
- function updateDOMProperties(domElement, updatePayload, wasCustomComponentTag, isCustomComponentTag) {
- // TODO: Handle wasCustomComponentTag
- for (var i = 0; i < updatePayload.length; i += 2) {
- var propKey = updatePayload[i];
- var propValue = updatePayload[i + 1];
- if (propKey === STYLE) {
- setValueForStyles(domElement, propValue);
- } else if (propKey === DANGEROUSLY_SET_INNER_HTML) {
- setInnerHTML(domElement, propValue);
- } else if (propKey === CHILDREN) {
- setTextContent(domElement, propValue);
- } else {
- setValueForProperty(domElement, propKey, propValue, isCustomComponentTag);
- }
- }
- }
- function createElement(type, props, rootContainerElement, parentNamespace) {
- var isCustomComponentTag; // We create tags in the namespace of their parent container, except HTML
- // tags get no namespace.
- var ownerDocument = getOwnerDocumentFromRootContainer(rootContainerElement);
- var domElement;
- var namespaceURI = parentNamespace;
- if (namespaceURI === HTML_NAMESPACE) {
- namespaceURI = getIntrinsicNamespace(type);
- }
- if (namespaceURI === HTML_NAMESPACE) {
- {
- isCustomComponentTag = isCustomComponent(type, props); // Should this check be gated by parent namespace? Not sure we want to
- // allow <SVG> or <mATH>.
- if (!isCustomComponentTag && type !== type.toLowerCase()) {
- error('<%s /> is using incorrect casing. ' + 'Use PascalCase for React components, ' + 'or lowercase for HTML elements.', type);
- }
- }
- if (type === 'script') {
- // Create the script via .innerHTML so its "parser-inserted" flag is
- // set to true and it does not execute
- var div = ownerDocument.createElement('div');
- div.innerHTML = '<script><' + '/script>'; // eslint-disable-line
- // This is guaranteed to yield a script element.
- var firstChild = div.firstChild;
- domElement = div.removeChild(firstChild);
- } else if (typeof props.is === 'string') {
- // $FlowIssue `createElement` should be updated for Web Components
- domElement = ownerDocument.createElement(type, {
- is: props.is
- });
- } else {
- // Separate else branch instead of using `props.is || undefined` above because of a Firefox bug.
- // See discussion in https://github.com/facebook/react/pull/6896
- // and discussion in https://bugzilla.mozilla.org/show_bug.cgi?id=1276240
- domElement = ownerDocument.createElement(type); // Normally attributes are assigned in `setInitialDOMProperties`, however the `multiple` and `size`
- // attributes on `select`s needs to be added before `option`s are inserted.
- // This prevents:
- // - a bug where the `select` does not scroll to the correct option because singular
- // `select` elements automatically pick the first item #13222
- // - a bug where the `select` set the first item as selected despite the `size` attribute #14239
- // See https://github.com/facebook/react/issues/13222
- // and https://github.com/facebook/react/issues/14239
- if (type === 'select') {
- var node = domElement;
- if (props.multiple) {
- node.multiple = true;
- } else if (props.size) {
- // Setting a size greater than 1 causes a select to behave like `multiple=true`, where
- // it is possible that no option is selected.
- //
- // This is only necessary when a select in "single selection mode".
- node.size = props.size;
- }
- }
- }
- } else {
- domElement = ownerDocument.createElementNS(namespaceURI, type);
- }
- {
- if (namespaceURI === HTML_NAMESPACE) {
- if (!isCustomComponentTag && Object.prototype.toString.call(domElement) === '[object HTMLUnknownElement]' && !hasOwnProperty.call(warnedUnknownTags, type)) {
- warnedUnknownTags[type] = true;
- error('The tag <%s> is unrecognized in this browser. ' + 'If you meant to render a React component, start its name with ' + 'an uppercase letter.', type);
- }
- }
- }
- return domElement;
- }
- function createTextNode(text, rootContainerElement) {
- return getOwnerDocumentFromRootContainer(rootContainerElement).createTextNode(text);
- }
- function setInitialProperties(domElement, tag, rawProps, rootContainerElement) {
- var isCustomComponentTag = isCustomComponent(tag, rawProps);
- {
- validatePropertiesInDevelopment(tag, rawProps);
- } // TODO: Make sure that we check isMounted before firing any of these events.
- var props;
- switch (tag) {
- case 'dialog':
- listenToNonDelegatedEvent('cancel', domElement);
- listenToNonDelegatedEvent('close', domElement);
- props = rawProps;
- break;
- case 'iframe':
- case 'object':
- case 'embed':
- // We listen to this event in case to ensure emulated bubble
- // listeners still fire for the load event.
- listenToNonDelegatedEvent('load', domElement);
- props = rawProps;
- break;
- case 'video':
- case 'audio':
- // We listen to these events in case to ensure emulated bubble
- // listeners still fire for all the media events.
- for (var i = 0; i < mediaEventTypes.length; i++) {
- listenToNonDelegatedEvent(mediaEventTypes[i], domElement);
- }
- props = rawProps;
- break;
- case 'source':
- // We listen to this event in case to ensure emulated bubble
- // listeners still fire for the error event.
- listenToNonDelegatedEvent('error', domElement);
- props = rawProps;
- break;
- case 'img':
- case 'image':
- case 'link':
- // We listen to these events in case to ensure emulated bubble
- // listeners still fire for error and load events.
- listenToNonDelegatedEvent('error', domElement);
- listenToNonDelegatedEvent('load', domElement);
- props = rawProps;
- break;
- case 'details':
- // We listen to this event in case to ensure emulated bubble
- // listeners still fire for the toggle event.
- listenToNonDelegatedEvent('toggle', domElement);
- props = rawProps;
- break;
- case 'input':
- initWrapperState(domElement, rawProps);
- props = getHostProps(domElement, rawProps); // We listen to this event in case to ensure emulated bubble
- // listeners still fire for the invalid event.
- listenToNonDelegatedEvent('invalid', domElement);
- break;
- case 'option':
- validateProps(domElement, rawProps);
- props = rawProps;
- break;
- case 'select':
- initWrapperState$1(domElement, rawProps);
- props = getHostProps$1(domElement, rawProps); // We listen to this event in case to ensure emulated bubble
- // listeners still fire for the invalid event.
- listenToNonDelegatedEvent('invalid', domElement);
- break;
- case 'textarea':
- initWrapperState$2(domElement, rawProps);
- props = getHostProps$2(domElement, rawProps); // We listen to this event in case to ensure emulated bubble
- // listeners still fire for the invalid event.
- listenToNonDelegatedEvent('invalid', domElement);
- break;
- default:
- props = rawProps;
- }
- assertValidProps(tag, props);
- setInitialDOMProperties(tag, domElement, rootContainerElement, props, isCustomComponentTag);
- switch (tag) {
- case 'input':
- // TODO: Make sure we check if this is still unmounted or do any clean
- // up necessary since we never stop tracking anymore.
- track(domElement);
- postMountWrapper(domElement, rawProps, false);
- break;
- case 'textarea':
- // TODO: Make sure we check if this is still unmounted or do any clean
- // up necessary since we never stop tracking anymore.
- track(domElement);
- postMountWrapper$3(domElement);
- break;
- case 'option':
- postMountWrapper$1(domElement, rawProps);
- break;
- case 'select':
- postMountWrapper$2(domElement, rawProps);
- break;
- default:
- if (typeof props.onClick === 'function') {
- // TODO: This cast may not be sound for SVG, MathML or custom elements.
- trapClickOnNonInteractiveElement(domElement);
- }
- break;
- }
- } // Calculate the diff between the two objects.
- function diffProperties(domElement, tag, lastRawProps, nextRawProps, rootContainerElement) {
- {
- validatePropertiesInDevelopment(tag, nextRawProps);
- }
- var updatePayload = null;
- var lastProps;
- var nextProps;
- switch (tag) {
- case 'input':
- lastProps = getHostProps(domElement, lastRawProps);
- nextProps = getHostProps(domElement, nextRawProps);
- updatePayload = [];
- break;
- case 'select':
- lastProps = getHostProps$1(domElement, lastRawProps);
- nextProps = getHostProps$1(domElement, nextRawProps);
- updatePayload = [];
- break;
- case 'textarea':
- lastProps = getHostProps$2(domElement, lastRawProps);
- nextProps = getHostProps$2(domElement, nextRawProps);
- updatePayload = [];
- break;
- default:
- lastProps = lastRawProps;
- nextProps = nextRawProps;
- if (typeof lastProps.onClick !== 'function' && typeof nextProps.onClick === 'function') {
- // TODO: This cast may not be sound for SVG, MathML or custom elements.
- trapClickOnNonInteractiveElement(domElement);
- }
- break;
- }
- assertValidProps(tag, nextProps);
- var propKey;
- var styleName;
- var styleUpdates = null;
- for (propKey in lastProps) {
- if (nextProps.hasOwnProperty(propKey) || !lastProps.hasOwnProperty(propKey) || lastProps[propKey] == null) {
- continue;
- }
- if (propKey === STYLE) {
- var lastStyle = lastProps[propKey];
- for (styleName in lastStyle) {
- if (lastStyle.hasOwnProperty(styleName)) {
- if (!styleUpdates) {
- styleUpdates = {};
- }
- styleUpdates[styleName] = '';
- }
- }
- } else if (propKey === DANGEROUSLY_SET_INNER_HTML || propKey === CHILDREN); else if (propKey === SUPPRESS_CONTENT_EDITABLE_WARNING || propKey === SUPPRESS_HYDRATION_WARNING); else if (propKey === AUTOFOCUS); else if (registrationNameDependencies.hasOwnProperty(propKey)) {
- // This is a special case. If any listener updates we need to ensure
- // that the "current" fiber pointer gets updated so we need a commit
- // to update this element.
- if (!updatePayload) {
- updatePayload = [];
- }
- } else {
- // For all other deleted properties we add it to the queue. We use
- // the allowed property list in the commit phase instead.
- (updatePayload = updatePayload || []).push(propKey, null);
- }
- }
- for (propKey in nextProps) {
- var nextProp = nextProps[propKey];
- var lastProp = lastProps != null ? lastProps[propKey] : undefined;
- if (!nextProps.hasOwnProperty(propKey) || nextProp === lastProp || nextProp == null && lastProp == null) {
- continue;
- }
- if (propKey === STYLE) {
- {
- if (nextProp) {
- // Freeze the next style object so that we can assume it won't be
- // mutated. We have already warned for this in the past.
- Object.freeze(nextProp);
- }
- }
- if (lastProp) {
- // Unset styles on `lastProp` but not on `nextProp`.
- for (styleName in lastProp) {
- if (lastProp.hasOwnProperty(styleName) && (!nextProp || !nextProp.hasOwnProperty(styleName))) {
- if (!styleUpdates) {
- styleUpdates = {};
- }
- styleUpdates[styleName] = '';
- }
- } // Update styles that changed since `lastProp`.
- for (styleName in nextProp) {
- if (nextProp.hasOwnProperty(styleName) && lastProp[styleName] !== nextProp[styleName]) {
- if (!styleUpdates) {
- styleUpdates = {};
- }
- styleUpdates[styleName] = nextProp[styleName];
- }
- }
- } else {
- // Relies on `updateStylesByID` not mutating `styleUpdates`.
- if (!styleUpdates) {
- if (!updatePayload) {
- updatePayload = [];
- }
- updatePayload.push(propKey, styleUpdates);
- }
- styleUpdates = nextProp;
- }
- } else if (propKey === DANGEROUSLY_SET_INNER_HTML) {
- var nextHtml = nextProp ? nextProp[HTML$1] : undefined;
- var lastHtml = lastProp ? lastProp[HTML$1] : undefined;
- if (nextHtml != null) {
- if (lastHtml !== nextHtml) {
- (updatePayload = updatePayload || []).push(propKey, nextHtml);
- }
- }
- } else if (propKey === CHILDREN) {
- if (typeof nextProp === 'string' || typeof nextProp === 'number') {
- (updatePayload = updatePayload || []).push(propKey, '' + nextProp);
- }
- } else if (propKey === SUPPRESS_CONTENT_EDITABLE_WARNING || propKey === SUPPRESS_HYDRATION_WARNING); else if (registrationNameDependencies.hasOwnProperty(propKey)) {
- if (nextProp != null) {
- // We eagerly listen to this even though we haven't committed yet.
- if (typeof nextProp !== 'function') {
- warnForInvalidEventListener(propKey, nextProp);
- }
- if (propKey === 'onScroll') {
- listenToNonDelegatedEvent('scroll', domElement);
- }
- }
- if (!updatePayload && lastProp !== nextProp) {
- // This is a special case. If any listener updates we need to ensure
- // that the "current" props pointer gets updated so we need a commit
- // to update this element.
- updatePayload = [];
- }
- } else {
- // For any other property we always add it to the queue and then we
- // filter it out using the allowed property list during the commit.
- (updatePayload = updatePayload || []).push(propKey, nextProp);
- }
- }
- if (styleUpdates) {
- {
- validateShorthandPropertyCollisionInDev(styleUpdates, nextProps[STYLE]);
- }
- (updatePayload = updatePayload || []).push(STYLE, styleUpdates);
- }
- return updatePayload;
- } // Apply the diff.
- function updateProperties(domElement, updatePayload, tag, lastRawProps, nextRawProps) {
- // Update checked *before* name.
- // In the middle of an update, it is possible to have multiple checked.
- // When a checked radio tries to change name, browser makes another radio's checked false.
- if (tag === 'input' && nextRawProps.type === 'radio' && nextRawProps.name != null) {
- updateChecked(domElement, nextRawProps);
- }
- var wasCustomComponentTag = isCustomComponent(tag, lastRawProps);
- var isCustomComponentTag = isCustomComponent(tag, nextRawProps); // Apply the diff.
- updateDOMProperties(domElement, updatePayload, wasCustomComponentTag, isCustomComponentTag); // TODO: Ensure that an update gets scheduled if any of the special props
- // changed.
- switch (tag) {
- case 'input':
- // Update the wrapper around inputs *after* updating props. This has to
- // happen after `updateDOMProperties`. Otherwise HTML5 input validations
- // raise warnings and prevent the new value from being assigned.
- updateWrapper(domElement, nextRawProps);
- break;
- case 'textarea':
- updateWrapper$1(domElement, nextRawProps);
- break;
- case 'select':
- // <select> value update needs to occur after <option> children
- // reconciliation
- postUpdateWrapper(domElement, nextRawProps);
- break;
- }
- }
- function getPossibleStandardName(propName) {
- {
- var lowerCasedName = propName.toLowerCase();
- if (!possibleStandardNames.hasOwnProperty(lowerCasedName)) {
- return null;
- }
- return possibleStandardNames[lowerCasedName] || null;
- }
- }
- function diffHydratedProperties(domElement, tag, rawProps, parentNamespace, rootContainerElement, isConcurrentMode, shouldWarnDev) {
- var isCustomComponentTag;
- var extraAttributeNames;
- {
- isCustomComponentTag = isCustomComponent(tag, rawProps);
- validatePropertiesInDevelopment(tag, rawProps);
- } // TODO: Make sure that we check isMounted before firing any of these events.
- switch (tag) {
- case 'dialog':
- listenToNonDelegatedEvent('cancel', domElement);
- listenToNonDelegatedEvent('close', domElement);
- break;
- case 'iframe':
- case 'object':
- case 'embed':
- // We listen to this event in case to ensure emulated bubble
- // listeners still fire for the load event.
- listenToNonDelegatedEvent('load', domElement);
- break;
- case 'video':
- case 'audio':
- // We listen to these events in case to ensure emulated bubble
- // listeners still fire for all the media events.
- for (var i = 0; i < mediaEventTypes.length; i++) {
- listenToNonDelegatedEvent(mediaEventTypes[i], domElement);
- }
- break;
- case 'source':
- // We listen to this event in case to ensure emulated bubble
- // listeners still fire for the error event.
- listenToNonDelegatedEvent('error', domElement);
- break;
- case 'img':
- case 'image':
- case 'link':
- // We listen to these events in case to ensure emulated bubble
- // listeners still fire for error and load events.
- listenToNonDelegatedEvent('error', domElement);
- listenToNonDelegatedEvent('load', domElement);
- break;
- case 'details':
- // We listen to this event in case to ensure emulated bubble
- // listeners still fire for the toggle event.
- listenToNonDelegatedEvent('toggle', domElement);
- break;
- case 'input':
- initWrapperState(domElement, rawProps); // We listen to this event in case to ensure emulated bubble
- // listeners still fire for the invalid event.
- listenToNonDelegatedEvent('invalid', domElement);
- break;
- case 'option':
- validateProps(domElement, rawProps);
- break;
- case 'select':
- initWrapperState$1(domElement, rawProps); // We listen to this event in case to ensure emulated bubble
- // listeners still fire for the invalid event.
- listenToNonDelegatedEvent('invalid', domElement);
- break;
- case 'textarea':
- initWrapperState$2(domElement, rawProps); // We listen to this event in case to ensure emulated bubble
- // listeners still fire for the invalid event.
- listenToNonDelegatedEvent('invalid', domElement);
- break;
- }
- assertValidProps(tag, rawProps);
- {
- extraAttributeNames = new Set();
- var attributes = domElement.attributes;
- for (var _i = 0; _i < attributes.length; _i++) {
- var name = attributes[_i].name.toLowerCase();
- switch (name) {
- // Controlled attributes are not validated
- // TODO: Only ignore them on controlled tags.
- case 'value':
- break;
- case 'checked':
- break;
- case 'selected':
- break;
- default:
- // Intentionally use the original name.
- // See discussion in https://github.com/facebook/react/pull/10676.
- extraAttributeNames.add(attributes[_i].name);
- }
- }
- }
- var updatePayload = null;
- for (var propKey in rawProps) {
- if (!rawProps.hasOwnProperty(propKey)) {
- continue;
- }
- var nextProp = rawProps[propKey];
- if (propKey === CHILDREN) {
- // For text content children we compare against textContent. This
- // might match additional HTML that is hidden when we read it using
- // textContent. E.g. "foo" will match "f<span>oo</span>" but that still
- // satisfies our requirement. Our requirement is not to produce perfect
- // HTML and attributes. Ideally we should preserve structure but it's
- // ok not to if the visible content is still enough to indicate what
- // even listeners these nodes might be wired up to.
- // TODO: Warn if there is more than a single textNode as a child.
- // TODO: Should we use domElement.firstChild.nodeValue to compare?
- if (typeof nextProp === 'string') {
- if (domElement.textContent !== nextProp) {
- if (rawProps[SUPPRESS_HYDRATION_WARNING] !== true) {
- checkForUnmatchedText(domElement.textContent, nextProp, isConcurrentMode, shouldWarnDev);
- }
- updatePayload = [CHILDREN, nextProp];
- }
- } else if (typeof nextProp === 'number') {
- if (domElement.textContent !== '' + nextProp) {
- if (rawProps[SUPPRESS_HYDRATION_WARNING] !== true) {
- checkForUnmatchedText(domElement.textContent, nextProp, isConcurrentMode, shouldWarnDev);
- }
- updatePayload = [CHILDREN, '' + nextProp];
- }
- }
- } else if (registrationNameDependencies.hasOwnProperty(propKey)) {
- if (nextProp != null) {
- if (typeof nextProp !== 'function') {
- warnForInvalidEventListener(propKey, nextProp);
- }
- if (propKey === 'onScroll') {
- listenToNonDelegatedEvent('scroll', domElement);
- }
- }
- } else if (shouldWarnDev && true && // Convince Flow we've calculated it (it's DEV-only in this method.)
- typeof isCustomComponentTag === 'boolean') {
- // Validate that the properties correspond to their expected values.
- var serverValue = void 0;
- var propertyInfo = isCustomComponentTag && enableCustomElementPropertySupport ? null : getPropertyInfo(propKey);
- if (rawProps[SUPPRESS_HYDRATION_WARNING] === true); else if (propKey === SUPPRESS_CONTENT_EDITABLE_WARNING || propKey === SUPPRESS_HYDRATION_WARNING || // Controlled attributes are not validated
- // TODO: Only ignore them on controlled tags.
- propKey === 'value' || propKey === 'checked' || propKey === 'selected'); else if (propKey === DANGEROUSLY_SET_INNER_HTML) {
- var serverHTML = domElement.innerHTML;
- var nextHtml = nextProp ? nextProp[HTML$1] : undefined;
- if (nextHtml != null) {
- var expectedHTML = normalizeHTML(domElement, nextHtml);
- if (expectedHTML !== serverHTML) {
- warnForPropDifference(propKey, serverHTML, expectedHTML);
- }
- }
- } else if (propKey === STYLE) {
- // $FlowFixMe - Should be inferred as not undefined.
- extraAttributeNames.delete(propKey);
- if (canDiffStyleForHydrationWarning) {
- var expectedStyle = createDangerousStringForStyles(nextProp);
- serverValue = domElement.getAttribute('style');
- if (expectedStyle !== serverValue) {
- warnForPropDifference(propKey, serverValue, expectedStyle);
- }
- }
- } else if (isCustomComponentTag && !enableCustomElementPropertySupport) {
- // $FlowFixMe - Should be inferred as not undefined.
- extraAttributeNames.delete(propKey.toLowerCase());
- serverValue = getValueForAttribute(domElement, propKey, nextProp);
- if (nextProp !== serverValue) {
- warnForPropDifference(propKey, serverValue, nextProp);
- }
- } else if (!shouldIgnoreAttribute(propKey, propertyInfo, isCustomComponentTag) && !shouldRemoveAttribute(propKey, nextProp, propertyInfo, isCustomComponentTag)) {
- var isMismatchDueToBadCasing = false;
- if (propertyInfo !== null) {
- // $FlowFixMe - Should be inferred as not undefined.
- extraAttributeNames.delete(propertyInfo.attributeName);
- serverValue = getValueForProperty(domElement, propKey, nextProp, propertyInfo);
- } else {
- var ownNamespace = parentNamespace;
- if (ownNamespace === HTML_NAMESPACE) {
- ownNamespace = getIntrinsicNamespace(tag);
- }
- if (ownNamespace === HTML_NAMESPACE) {
- // $FlowFixMe - Should be inferred as not undefined.
- extraAttributeNames.delete(propKey.toLowerCase());
- } else {
- var standardName = getPossibleStandardName(propKey);
- if (standardName !== null && standardName !== propKey) {
- // If an SVG prop is supplied with bad casing, it will
- // be successfully parsed from HTML, but will produce a mismatch
- // (and would be incorrectly rendered on the client).
- // However, we already warn about bad casing elsewhere.
- // So we'll skip the misleading extra mismatch warning in this case.
- isMismatchDueToBadCasing = true; // $FlowFixMe - Should be inferred as not undefined.
- extraAttributeNames.delete(standardName);
- } // $FlowFixMe - Should be inferred as not undefined.
- extraAttributeNames.delete(propKey);
- }
- serverValue = getValueForAttribute(domElement, propKey, nextProp);
- }
- var dontWarnCustomElement = enableCustomElementPropertySupport;
- if (!dontWarnCustomElement && nextProp !== serverValue && !isMismatchDueToBadCasing) {
- warnForPropDifference(propKey, serverValue, nextProp);
- }
- }
- }
- }
- {
- if (shouldWarnDev) {
- if ( // $FlowFixMe - Should be inferred as not undefined.
- extraAttributeNames.size > 0 && rawProps[SUPPRESS_HYDRATION_WARNING] !== true) {
- // $FlowFixMe - Should be inferred as not undefined.
- warnForExtraAttributes(extraAttributeNames);
- }
- }
- }
- switch (tag) {
- case 'input':
- // TODO: Make sure we check if this is still unmounted or do any clean
- // up necessary since we never stop tracking anymore.
- track(domElement);
- postMountWrapper(domElement, rawProps, true);
- break;
- case 'textarea':
- // TODO: Make sure we check if this is still unmounted or do any clean
- // up necessary since we never stop tracking anymore.
- track(domElement);
- postMountWrapper$3(domElement);
- break;
- case 'select':
- case 'option':
- // For input and textarea we current always set the value property at
- // post mount to force it to diverge from attributes. However, for
- // option and select we don't quite do the same thing and select
- // is not resilient to the DOM state changing so we don't do that here.
- // TODO: Consider not doing this for input and textarea.
- break;
- default:
- if (typeof rawProps.onClick === 'function') {
- // TODO: This cast may not be sound for SVG, MathML or custom elements.
- trapClickOnNonInteractiveElement(domElement);
- }
- break;
- }
- return updatePayload;
- }
- function diffHydratedText(textNode, text, isConcurrentMode) {
- var isDifferent = textNode.nodeValue !== text;
- return isDifferent;
- }
- function warnForDeletedHydratableElement(parentNode, child) {
- {
- if (didWarnInvalidHydration) {
- return;
- }
- didWarnInvalidHydration = true;
- error('Did not expect server HTML to contain a <%s> in <%s>.', child.nodeName.toLowerCase(), parentNode.nodeName.toLowerCase());
- }
- }
- function warnForDeletedHydratableText(parentNode, child) {
- {
- if (didWarnInvalidHydration) {
- return;
- }
- didWarnInvalidHydration = true;
- error('Did not expect server HTML to contain the text node "%s" in <%s>.', child.nodeValue, parentNode.nodeName.toLowerCase());
- }
- }
- function warnForInsertedHydratedElement(parentNode, tag, props) {
- {
- if (didWarnInvalidHydration) {
- return;
- }
- didWarnInvalidHydration = true;
- error('Expected server HTML to contain a matching <%s> in <%s>.', tag, parentNode.nodeName.toLowerCase());
- }
- }
- function warnForInsertedHydratedText(parentNode, text) {
- {
- if (text === '') {
- // We expect to insert empty text nodes since they're not represented in
- // the HTML.
- // TODO: Remove this special case if we can just avoid inserting empty
- // text nodes.
- return;
- }
- if (didWarnInvalidHydration) {
- return;
- }
- didWarnInvalidHydration = true;
- error('Expected server HTML to contain a matching text node for "%s" in <%s>.', text, parentNode.nodeName.toLowerCase());
- }
- }
- function restoreControlledState$3(domElement, tag, props) {
- switch (tag) {
- case 'input':
- restoreControlledState(domElement, props);
- return;
- case 'textarea':
- restoreControlledState$2(domElement, props);
- return;
- case 'select':
- restoreControlledState$1(domElement, props);
- return;
- }
- }
- var validateDOMNesting = function () { };
- var updatedAncestorInfo = function () { };
- {
- // This validation code was written based on the HTML5 parsing spec:
- // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope
- //
- // Note: this does not catch all invalid nesting, nor does it try to (as it's
- // not clear what practical benefit doing so provides); instead, we warn only
- // for cases where the parser will give a parse tree differing from what React
- // intended. For example, <b><div></div></b> is invalid but we don't warn
- // because it still parses correctly; we do warn for other cases like nested
- // <p> tags where the beginning of the second element implicitly closes the
- // first, causing a confusing mess.
- // https://html.spec.whatwg.org/multipage/syntax.html#special
- var specialTags = ['address', 'applet', 'area', 'article', 'aside', 'base', 'basefont', 'bgsound', 'blockquote', 'body', 'br', 'button', 'caption', 'center', 'col', 'colgroup', 'dd', 'details', 'dir', 'div', 'dl', 'dt', 'embed', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'frame', 'frameset', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'iframe', 'img', 'input', 'isindex', 'li', 'link', 'listing', 'main', 'marquee', 'menu', 'menuitem', 'meta', 'nav', 'noembed', 'noframes', 'noscript', 'object', 'ol', 'p', 'param', 'plaintext', 'pre', 'script', 'section', 'select', 'source', 'style', 'summary', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'title', 'tr', 'track', 'ul', 'wbr', 'xmp']; // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope
- var inScopeTags = ['applet', 'caption', 'html', 'table', 'td', 'th', 'marquee', 'object', 'template', // https://html.spec.whatwg.org/multipage/syntax.html#html-integration-point
- // TODO: Distinguish by namespace here -- for <title>, including it here
- // errs on the side of fewer warnings
- 'foreignObject', 'desc', 'title']; // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-button-scope
- var buttonScopeTags = inScopeTags.concat(['button']); // https://html.spec.whatwg.org/multipage/syntax.html#generate-implied-end-tags
- var impliedEndTags = ['dd', 'dt', 'li', 'option', 'optgroup', 'p', 'rp', 'rt'];
- var emptyAncestorInfo = {
- current: null,
- formTag: null,
- aTagInScope: null,
- buttonTagInScope: null,
- nobrTagInScope: null,
- pTagInButtonScope: null,
- listItemTagAutoclosing: null,
- dlItemTagAutoclosing: null
- };
- updatedAncestorInfo = function (oldInfo, tag) {
- var ancestorInfo = assign({}, oldInfo || emptyAncestorInfo);
- var info = {
- tag: tag
- };
- if (inScopeTags.indexOf(tag) !== -1) {
- ancestorInfo.aTagInScope = null;
- ancestorInfo.buttonTagInScope = null;
- ancestorInfo.nobrTagInScope = null;
- }
- if (buttonScopeTags.indexOf(tag) !== -1) {
- ancestorInfo.pTagInButtonScope = null;
- } // See rules for 'li', 'dd', 'dt' start tags in
- // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody
- if (specialTags.indexOf(tag) !== -1 && tag !== 'address' && tag !== 'div' && tag !== 'p') {
- ancestorInfo.listItemTagAutoclosing = null;
- ancestorInfo.dlItemTagAutoclosing = null;
- }
- ancestorInfo.current = info;
- if (tag === 'form') {
- ancestorInfo.formTag = info;
- }
- if (tag === 'a') {
- ancestorInfo.aTagInScope = info;
- }
- if (tag === 'button') {
- ancestorInfo.buttonTagInScope = info;
- }
- if (tag === 'nobr') {
- ancestorInfo.nobrTagInScope = info;
- }
- if (tag === 'p') {
- ancestorInfo.pTagInButtonScope = info;
- }
- if (tag === 'li') {
- ancestorInfo.listItemTagAutoclosing = info;
- }
- if (tag === 'dd' || tag === 'dt') {
- ancestorInfo.dlItemTagAutoclosing = info;
- }
- return ancestorInfo;
- };
- /**
- * Returns whether
- */
- var isTagValidWithParent = function (tag, parentTag) {
- // First, let's check if we're in an unusual parsing mode...
- switch (parentTag) {
- // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inselect
- case 'select':
- return tag === 'option' || tag === 'optgroup' || tag === '#text';
- case 'optgroup':
- return tag === 'option' || tag === '#text';
- // Strictly speaking, seeing an <option> doesn't mean we're in a <select>
- // but
- case 'option':
- return tag === '#text';
- // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intd
- // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incaption
- // No special behavior since these rules fall back to "in body" mode for
- // all except special table nodes which cause bad parsing behavior anyway.
- // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intr
- case 'tr':
- return tag === 'th' || tag === 'td' || tag === 'style' || tag === 'script' || tag === 'template';
- // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intbody
- case 'tbody':
- case 'thead':
- case 'tfoot':
- return tag === 'tr' || tag === 'style' || tag === 'script' || tag === 'template';
- // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incolgroup
- case 'colgroup':
- return tag === 'col' || tag === 'template';
- // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intable
- case 'table':
- return tag === 'caption' || tag === 'colgroup' || tag === 'tbody' || tag === 'tfoot' || tag === 'thead' || tag === 'style' || tag === 'script' || tag === 'template';
- // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inhead
- case 'head':
- return tag === 'base' || tag === 'basefont' || tag === 'bgsound' || tag === 'link' || tag === 'meta' || tag === 'title' || tag === 'noscript' || tag === 'noframes' || tag === 'style' || tag === 'script' || tag === 'template';
- // https://html.spec.whatwg.org/multipage/semantics.html#the-html-element
- case 'html':
- return tag === 'head' || tag === 'body' || tag === 'frameset';
- case 'frameset':
- return tag === 'frame';
- case '#document':
- return tag === 'html';
- } // Probably in the "in body" parsing mode, so we outlaw only tag combos
- // where the parsing rules cause implicit opens or closes to be added.
- // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody
- switch (tag) {
- case 'h1':
- case 'h2':
- case 'h3':
- case 'h4':
- case 'h5':
- case 'h6':
- return parentTag !== 'h1' && parentTag !== 'h2' && parentTag !== 'h3' && parentTag !== 'h4' && parentTag !== 'h5' && parentTag !== 'h6';
- case 'rp':
- case 'rt':
- return impliedEndTags.indexOf(parentTag) === -1;
- case 'body':
- case 'caption':
- case 'col':
- case 'colgroup':
- case 'frameset':
- case 'frame':
- case 'head':
- case 'html':
- case 'tbody':
- case 'td':
- case 'tfoot':
- case 'th':
- case 'thead':
- case 'tr':
- // These tags are only valid with a few parents that have special child
- // parsing rules -- if we're down here, then none of those matched and
- // so we allow it only if we don't know what the parent is, as all other
- // cases are invalid.
- return parentTag == null;
- }
- return true;
- };
- /**
- * Returns whether
- */
- var findInvalidAncestorForTag = function (tag, ancestorInfo) {
- switch (tag) {
- case 'address':
- case 'article':
- case 'aside':
- case 'blockquote':
- case 'center':
- case 'details':
- case 'dialog':
- case 'dir':
- case 'div':
- case 'dl':
- case 'fieldset':
- case 'figcaption':
- case 'figure':
- case 'footer':
- case 'header':
- case 'hgroup':
- case 'main':
- case 'menu':
- case 'nav':
- case 'ol':
- case 'p':
- case 'section':
- case 'summary':
- case 'ul':
- case 'pre':
- case 'listing':
- case 'table':
- case 'hr':
- case 'xmp':
- case 'h1':
- case 'h2':
- case 'h3':
- case 'h4':
- case 'h5':
- case 'h6':
- return ancestorInfo.pTagInButtonScope;
- case 'form':
- return ancestorInfo.formTag || ancestorInfo.pTagInButtonScope;
- case 'li':
- return ancestorInfo.listItemTagAutoclosing;
- case 'dd':
- case 'dt':
- return ancestorInfo.dlItemTagAutoclosing;
- case 'button':
- return ancestorInfo.buttonTagInScope;
- case 'a':
- // Spec says something about storing a list of markers, but it sounds
- // equivalent to this check.
- return ancestorInfo.aTagInScope;
- case 'nobr':
- return ancestorInfo.nobrTagInScope;
- }
- return null;
- };
- var didWarn$1 = {};
- validateDOMNesting = function (childTag, childText, ancestorInfo) {
- ancestorInfo = ancestorInfo || emptyAncestorInfo;
- var parentInfo = ancestorInfo.current;
- var parentTag = parentInfo && parentInfo.tag;
- if (childText != null) {
- if (childTag != null) {
- error('validateDOMNesting: when childText is passed, childTag should be null');
- }
- childTag = '#text';
- }
- var invalidParent = isTagValidWithParent(childTag, parentTag) ? null : parentInfo;
- var invalidAncestor = invalidParent ? null : findInvalidAncestorForTag(childTag, ancestorInfo);
- var invalidParentOrAncestor = invalidParent || invalidAncestor;
- if (!invalidParentOrAncestor) {
- return;
- }
- var ancestorTag = invalidParentOrAncestor.tag;
- var warnKey = !!invalidParent + '|' + childTag + '|' + ancestorTag;
- if (didWarn$1[warnKey]) {
- return;
- }
- didWarn$1[warnKey] = true;
- var tagDisplayName = childTag;
- var whitespaceInfo = '';
- if (childTag === '#text') {
- if (/\S/.test(childText)) {
- tagDisplayName = 'Text nodes';
- } else {
- tagDisplayName = 'Whitespace text nodes';
- whitespaceInfo = " Make sure you don't have any extra whitespace between tags on " + 'each line of your source code.';
- }
- } else {
- tagDisplayName = '<' + childTag + '>';
- }
- if (invalidParent) {
- var info = '';
- if (ancestorTag === 'table' && childTag === 'tr') {
- info += ' Add a <tbody>, <thead> or <tfoot> to your code to match the DOM tree generated by ' + 'the browser.';
- }
- error('validateDOMNesting(...): %s cannot appear as a child of <%s>.%s%s', tagDisplayName, ancestorTag, whitespaceInfo, info);
- } else {
- error('validateDOMNesting(...): %s cannot appear as a descendant of ' + '<%s>.', tagDisplayName, ancestorTag);
- }
- };
- }
- var SUPPRESS_HYDRATION_WARNING$1 = 'suppressHydrationWarning';
- var SUSPENSE_START_DATA = '$';
- var SUSPENSE_END_DATA = '/$';
- var SUSPENSE_PENDING_START_DATA = '$?';
- var SUSPENSE_FALLBACK_START_DATA = '$!';
- var STYLE$1 = 'style';
- var eventsEnabled = null;
- var selectionInformation = null;
- function getRootHostContext(rootContainerInstance) {
- var type;
- var namespace;
- var nodeType = rootContainerInstance.nodeType;
- switch (nodeType) {
- case DOCUMENT_NODE:
- case DOCUMENT_FRAGMENT_NODE:
- {
- type = nodeType === DOCUMENT_NODE ? '#document' : '#fragment';
- var root = rootContainerInstance.documentElement;
- namespace = root ? root.namespaceURI : getChildNamespace(null, '');
- break;
- }
- default:
- {
- var container = nodeType === COMMENT_NODE ? rootContainerInstance.parentNode : rootContainerInstance;
- var ownNamespace = container.namespaceURI || null;
- type = container.tagName;
- namespace = getChildNamespace(ownNamespace, type);
- break;
- }
- }
- {
- var validatedTag = type.toLowerCase();
- var ancestorInfo = updatedAncestorInfo(null, validatedTag);
- return {
- namespace: namespace,
- ancestorInfo: ancestorInfo
- };
- }
- }
- function getChildHostContext(parentHostContext, type, rootContainerInstance) {
- {
- var parentHostContextDev = parentHostContext;
- var namespace = getChildNamespace(parentHostContextDev.namespace, type);
- var ancestorInfo = updatedAncestorInfo(parentHostContextDev.ancestorInfo, type);
- return {
- namespace: namespace,
- ancestorInfo: ancestorInfo
- };
- }
- }
- function getPublicInstance(instance) {
- return instance;
- }
- function prepareForCommit(containerInfo) {
- eventsEnabled = isEnabled();
- selectionInformation = getSelectionInformation();
- var activeInstance = null;
- setEnabled(false);
- return activeInstance;
- }
- function resetAfterCommit(containerInfo) {
- restoreSelection(selectionInformation);
- setEnabled(eventsEnabled);
- eventsEnabled = null;
- selectionInformation = null;
- }
- function createInstance(type, props, rootContainerInstance, hostContext, internalInstanceHandle) {
- var parentNamespace;
- {
- // TODO: take namespace into account when validating.
- var hostContextDev = hostContext;
- validateDOMNesting(type, null, hostContextDev.ancestorInfo);
- if (typeof props.children === 'string' || typeof props.children === 'number') {
- var string = '' + props.children;
- var ownAncestorInfo = updatedAncestorInfo(hostContextDev.ancestorInfo, type);
- validateDOMNesting(null, string, ownAncestorInfo);
- }
- parentNamespace = hostContextDev.namespace;
- }
- var domElement = createElement(type, props, rootContainerInstance, parentNamespace);
- precacheFiberNode(internalInstanceHandle, domElement);
- updateFiberProps(domElement, props);
- return domElement;
- }
- function appendInitialChild(parentInstance, child) {
- parentInstance.appendChild(child);
- }
- function finalizeInitialChildren(domElement, type, props, rootContainerInstance, hostContext) {
- setInitialProperties(domElement, type, props, rootContainerInstance);
- switch (type) {
- case 'button':
- case 'input':
- case 'select':
- case 'textarea':
- return !!props.autoFocus;
- case 'img':
- return true;
- default:
- return false;
- }
- }
- function prepareUpdate(domElement, type, oldProps, newProps, rootContainerInstance, hostContext) {
- {
- var hostContextDev = hostContext;
- if (typeof newProps.children !== typeof oldProps.children && (typeof newProps.children === 'string' || typeof newProps.children === 'number')) {
- var string = '' + newProps.children;
- var ownAncestorInfo = updatedAncestorInfo(hostContextDev.ancestorInfo, type);
- validateDOMNesting(null, string, ownAncestorInfo);
- }
- }
- return diffProperties(domElement, type, oldProps, newProps);
- }
- function shouldSetTextContent(type, props) {
- return type === 'textarea' || type === 'noscript' || typeof props.children === 'string' || typeof props.children === 'number' || typeof props.dangerouslySetInnerHTML === 'object' && props.dangerouslySetInnerHTML !== null && props.dangerouslySetInnerHTML.__html != null;
- }
- function createTextInstance(text, rootContainerInstance, hostContext, internalInstanceHandle) {
- {
- var hostContextDev = hostContext;
- validateDOMNesting(null, text, hostContextDev.ancestorInfo);
- }
- var textNode = createTextNode(text, rootContainerInstance);
- precacheFiberNode(internalInstanceHandle, textNode);
- return textNode;
- }
- function getCurrentEventPriority() {
- var currentEvent = window.event;
- if (currentEvent === undefined) {
- return DefaultEventPriority;
- }
- return getEventPriority(currentEvent.type);
- }
- // if a component just imports ReactDOM (e.g. for findDOMNode).
- // Some environments might not have setTimeout or clearTimeout.
- var scheduleTimeout = typeof setTimeout === 'function' ? setTimeout : undefined;
- var cancelTimeout = typeof clearTimeout === 'function' ? clearTimeout : undefined;
- var noTimeout = -1;
- var localPromise = typeof Promise === 'function' ? Promise : undefined; // -------------------
- var scheduleMicrotask = typeof queueMicrotask === 'function' ? queueMicrotask : typeof localPromise !== 'undefined' ? function (callback) {
- return localPromise.resolve(null).then(callback).catch(handleErrorInNextTick);
- } : scheduleTimeout; // TODO: Determine the best fallback here.
- function handleErrorInNextTick(error) {
- setTimeout(function () {
- throw error;
- });
- } // -------------------
- function commitMount(domElement, type, newProps, internalInstanceHandle) {
- // Despite the naming that might imply otherwise, this method only
- // fires if there is an `Update` effect scheduled during mounting.
- // This happens if `finalizeInitialChildren` returns `true` (which it
- // does to implement the `autoFocus` attribute on the client). But
- // there are also other cases when this might happen (such as patching
- // up text content during hydration mismatch). So we'll check this again.
- switch (type) {
- case 'button':
- case 'input':
- case 'select':
- case 'textarea':
- if (newProps.autoFocus) {
- domElement.focus();
- }
- return;
- case 'img':
- {
- if (newProps.src) {
- domElement.src = newProps.src;
- }
- return;
- }
- }
- }
- function commitUpdate(domElement, updatePayload, type, oldProps, newProps, internalInstanceHandle) {
- // Apply the diff to the DOM node.
- updateProperties(domElement, updatePayload, type, oldProps, newProps); // Update the props handle so that we know which props are the ones with
- // with current event handlers.
- updateFiberProps(domElement, newProps);
- }
- function resetTextContent(domElement) {
- setTextContent(domElement, '');
- }
- function commitTextUpdate(textInstance, oldText, newText) {
- textInstance.nodeValue = newText;
- }
- function appendChild(parentInstance, child) {
- parentInstance.appendChild(child);
- }
- function appendChildToContainer(container, child) {
- var parentNode;
- if (container.nodeType === COMMENT_NODE) {
- parentNode = container.parentNode;
- parentNode.insertBefore(child, container);
- } else {
- parentNode = container;
- parentNode.appendChild(child);
- } // This container might be used for a portal.
- // If something inside a portal is clicked, that click should bubble
- // through the React tree. However, on Mobile Safari the click would
- // never bubble through the *DOM* tree unless an ancestor with onclick
- // event exists. So we wouldn't see it and dispatch it.
- // This is why we ensure that non React root containers have inline onclick
- // defined.
- // https://github.com/facebook/react/issues/11918
- var reactRootContainer = container._reactRootContainer;
- if ((reactRootContainer === null || reactRootContainer === undefined) && parentNode.onclick === null) {
- // TODO: This cast may not be sound for SVG, MathML or custom elements.
- trapClickOnNonInteractiveElement(parentNode);
- }
- }
- function insertBefore(parentInstance, child, beforeChild) {
- parentInstance.insertBefore(child, beforeChild);
- }
- function insertInContainerBefore(container, child, beforeChild) {
- if (container.nodeType === COMMENT_NODE) {
- container.parentNode.insertBefore(child, beforeChild);
- } else {
- container.insertBefore(child, beforeChild);
- }
- }
- function removeChild(parentInstance, child) {
- parentInstance.removeChild(child);
- }
- function removeChildFromContainer(container, child) {
- if (container.nodeType === COMMENT_NODE) {
- container.parentNode.removeChild(child);
- } else {
- container.removeChild(child);
- }
- }
- function clearSuspenseBoundary(parentInstance, suspenseInstance) {
- var node = suspenseInstance; // Delete all nodes within this suspense boundary.
- // There might be nested nodes so we need to keep track of how
- // deep we are and only break out when we're back on top.
- var depth = 0;
- do {
- var nextNode = node.nextSibling;
- parentInstance.removeChild(node);
- if (nextNode && nextNode.nodeType === COMMENT_NODE) {
- var data = nextNode.data;
- if (data === SUSPENSE_END_DATA) {
- if (depth === 0) {
- parentInstance.removeChild(nextNode); // Retry if any event replaying was blocked on this.
- retryIfBlockedOn(suspenseInstance);
- return;
- } else {
- depth--;
- }
- } else if (data === SUSPENSE_START_DATA || data === SUSPENSE_PENDING_START_DATA || data === SUSPENSE_FALLBACK_START_DATA) {
- depth++;
- }
- }
- node = nextNode;
- } while (node); // TODO: Warn, we didn't find the end comment boundary.
- // Retry if any event replaying was blocked on this.
- retryIfBlockedOn(suspenseInstance);
- }
- function clearSuspenseBoundaryFromContainer(container, suspenseInstance) {
- if (container.nodeType === COMMENT_NODE) {
- clearSuspenseBoundary(container.parentNode, suspenseInstance);
- } else if (container.nodeType === ELEMENT_NODE) {
- clearSuspenseBoundary(container, suspenseInstance);
- } // Retry if any event replaying was blocked on this.
- retryIfBlockedOn(container);
- }
- function hideInstance(instance) {
- // TODO: Does this work for all element types? What about MathML? Should we
- // pass host context to this method?
- instance = instance;
- var style = instance.style;
- if (typeof style.setProperty === 'function') {
- style.setProperty('display', 'none', 'important');
- } else {
- style.display = 'none';
- }
- }
- function hideTextInstance(textInstance) {
- textInstance.nodeValue = '';
- }
- function unhideInstance(instance, props) {
- instance = instance;
- var styleProp = props[STYLE$1];
- var display = styleProp !== undefined && styleProp !== null && styleProp.hasOwnProperty('display') ? styleProp.display : null;
- instance.style.display = dangerousStyleValue('display', display);
- }
- function unhideTextInstance(textInstance, text) {
- textInstance.nodeValue = text;
- }
- function clearContainer(container) {
- if (container.nodeType === ELEMENT_NODE) {
- container.textContent = '';
- } else if (container.nodeType === DOCUMENT_NODE) {
- if (container.documentElement) {
- container.removeChild(container.documentElement);
- }
- }
- } // -------------------
- function canHydrateInstance(instance, type, props) {
- if (instance.nodeType !== ELEMENT_NODE || type.toLowerCase() !== instance.nodeName.toLowerCase()) {
- return null;
- } // This has now been refined to an element node.
- return instance;
- }
- function canHydrateTextInstance(instance, text) {
- if (text === '' || instance.nodeType !== TEXT_NODE) {
- // Empty strings are not parsed by HTML so there won't be a correct match here.
- return null;
- } // This has now been refined to a text node.
- return instance;
- }
- function canHydrateSuspenseInstance(instance) {
- if (instance.nodeType !== COMMENT_NODE) {
- // Empty strings are not parsed by HTML so there won't be a correct match here.
- return null;
- } // This has now been refined to a suspense node.
- return instance;
- }
- function isSuspenseInstancePending(instance) {
- return instance.data === SUSPENSE_PENDING_START_DATA;
- }
- function isSuspenseInstanceFallback(instance) {
- return instance.data === SUSPENSE_FALLBACK_START_DATA;
- }
- function getSuspenseInstanceFallbackErrorDetails(instance) {
- var dataset = instance.nextSibling && instance.nextSibling.dataset;
- var digest, message, stack;
- if (dataset) {
- digest = dataset.dgst;
- {
- message = dataset.msg;
- stack = dataset.stck;
- }
- }
- {
- return {
- message: message,
- digest: digest,
- stack: stack
- };
- } // let value = {message: undefined, hash: undefined};
- // const nextSibling = instance.nextSibling;
- // if (nextSibling) {
- // const dataset = ((nextSibling: any): HTMLTemplateElement).dataset;
- // value.message = dataset.msg;
- // value.hash = dataset.hash;
- // if (true) {
- // value.stack = dataset.stack;
- // }
- // }
- // return value;
- }
- function registerSuspenseInstanceRetry(instance, callback) {
- instance._reactRetry = callback;
- }
- function getNextHydratable(node) {
- // Skip non-hydratable nodes.
- for (; node != null; node = node.nextSibling) {
- var nodeType = node.nodeType;
- if (nodeType === ELEMENT_NODE || nodeType === TEXT_NODE) {
- break;
- }
- if (nodeType === COMMENT_NODE) {
- var nodeData = node.data;
- if (nodeData === SUSPENSE_START_DATA || nodeData === SUSPENSE_FALLBACK_START_DATA || nodeData === SUSPENSE_PENDING_START_DATA) {
- break;
- }
- if (nodeData === SUSPENSE_END_DATA) {
- return null;
- }
- }
- }
- return node;
- }
- function getNextHydratableSibling(instance) {
- return getNextHydratable(instance.nextSibling);
- }
- function getFirstHydratableChild(parentInstance) {
- return getNextHydratable(parentInstance.firstChild);
- }
- function getFirstHydratableChildWithinContainer(parentContainer) {
- return getNextHydratable(parentContainer.firstChild);
- }
- function getFirstHydratableChildWithinSuspenseInstance(parentInstance) {
- return getNextHydratable(parentInstance.nextSibling);
- }
- function hydrateInstance(instance, type, props, rootContainerInstance, hostContext, internalInstanceHandle, shouldWarnDev) {
- precacheFiberNode(internalInstanceHandle, instance); // TODO: Possibly defer this until the commit phase where all the events
- // get attached.
- updateFiberProps(instance, props);
- var parentNamespace;
- {
- var hostContextDev = hostContext;
- parentNamespace = hostContextDev.namespace;
- } // TODO: Temporary hack to check if we're in a concurrent root. We can delete
- // when the legacy root API is removed.
- var isConcurrentMode = (internalInstanceHandle.mode & ConcurrentMode) !== NoMode;
- return diffHydratedProperties(instance, type, props, parentNamespace, rootContainerInstance, isConcurrentMode, shouldWarnDev);
- }
- function hydrateTextInstance(textInstance, text, internalInstanceHandle, shouldWarnDev) {
- precacheFiberNode(internalInstanceHandle, textInstance); // TODO: Temporary hack to check if we're in a concurrent root. We can delete
- // when the legacy root API is removed.
- var isConcurrentMode = (internalInstanceHandle.mode & ConcurrentMode) !== NoMode;
- return diffHydratedText(textInstance, text);
- }
- function hydrateSuspenseInstance(suspenseInstance, internalInstanceHandle) {
- precacheFiberNode(internalInstanceHandle, suspenseInstance);
- }
- function getNextHydratableInstanceAfterSuspenseInstance(suspenseInstance) {
- var node = suspenseInstance.nextSibling; // Skip past all nodes within this suspense boundary.
- // There might be nested nodes so we need to keep track of how
- // deep we are and only break out when we're back on top.
- var depth = 0;
- while (node) {
- if (node.nodeType === COMMENT_NODE) {
- var data = node.data;
- if (data === SUSPENSE_END_DATA) {
- if (depth === 0) {
- return getNextHydratableSibling(node);
- } else {
- depth--;
- }
- } else if (data === SUSPENSE_START_DATA || data === SUSPENSE_FALLBACK_START_DATA || data === SUSPENSE_PENDING_START_DATA) {
- depth++;
- }
- }
- node = node.nextSibling;
- } // TODO: Warn, we didn't find the end comment boundary.
- return null;
- } // Returns the SuspenseInstance if this node is a direct child of a
- // SuspenseInstance. I.e. if its previous sibling is a Comment with
- // SUSPENSE_x_START_DATA. Otherwise, null.
- function getParentSuspenseInstance(targetInstance) {
- var node = targetInstance.previousSibling; // Skip past all nodes within this suspense boundary.
- // There might be nested nodes so we need to keep track of how
- // deep we are and only break out when we're back on top.
- var depth = 0;
- while (node) {
- if (node.nodeType === COMMENT_NODE) {
- var data = node.data;
- if (data === SUSPENSE_START_DATA || data === SUSPENSE_FALLBACK_START_DATA || data === SUSPENSE_PENDING_START_DATA) {
- if (depth === 0) {
- return node;
- } else {
- depth--;
- }
- } else if (data === SUSPENSE_END_DATA) {
- depth++;
- }
- }
- node = node.previousSibling;
- }
- return null;
- }
- function commitHydratedContainer(container) {
- // Retry if any event replaying was blocked on this.
- retryIfBlockedOn(container);
- }
- function commitHydratedSuspenseInstance(suspenseInstance) {
- // Retry if any event replaying was blocked on this.
- retryIfBlockedOn(suspenseInstance);
- }
- function shouldDeleteUnhydratedTailInstances(parentType) {
- return parentType !== 'head' && parentType !== 'body';
- }
- function didNotMatchHydratedContainerTextInstance(parentContainer, textInstance, text, isConcurrentMode) {
- var shouldWarnDev = true;
- checkForUnmatchedText(textInstance.nodeValue, text, isConcurrentMode, shouldWarnDev);
- }
- function didNotMatchHydratedTextInstance(parentType, parentProps, parentInstance, textInstance, text, isConcurrentMode) {
- if (parentProps[SUPPRESS_HYDRATION_WARNING$1] !== true) {
- var shouldWarnDev = true;
- checkForUnmatchedText(textInstance.nodeValue, text, isConcurrentMode, shouldWarnDev);
- }
- }
- function didNotHydrateInstanceWithinContainer(parentContainer, instance) {
- {
- if (instance.nodeType === ELEMENT_NODE) {
- warnForDeletedHydratableElement(parentContainer, instance);
- } else if (instance.nodeType === COMMENT_NODE); else {
- warnForDeletedHydratableText(parentContainer, instance);
- }
- }
- }
- function didNotHydrateInstanceWithinSuspenseInstance(parentInstance, instance) {
- {
- // $FlowFixMe: Only Element or Document can be parent nodes.
- var parentNode = parentInstance.parentNode;
- if (parentNode !== null) {
- if (instance.nodeType === ELEMENT_NODE) {
- warnForDeletedHydratableElement(parentNode, instance);
- } else if (instance.nodeType === COMMENT_NODE); else {
- warnForDeletedHydratableText(parentNode, instance);
- }
- }
- }
- }
- function didNotHydrateInstance(parentType, parentProps, parentInstance, instance, isConcurrentMode) {
- {
- if (isConcurrentMode || parentProps[SUPPRESS_HYDRATION_WARNING$1] !== true) {
- if (instance.nodeType === ELEMENT_NODE) {
- warnForDeletedHydratableElement(parentInstance, instance);
- } else if (instance.nodeType === COMMENT_NODE); else {
- warnForDeletedHydratableText(parentInstance, instance);
- }
- }
- }
- }
- function didNotFindHydratableInstanceWithinContainer(parentContainer, type, props) {
- {
- warnForInsertedHydratedElement(parentContainer, type);
- }
- }
- function didNotFindHydratableTextInstanceWithinContainer(parentContainer, text) {
- {
- warnForInsertedHydratedText(parentContainer, text);
- }
- }
- function didNotFindHydratableInstanceWithinSuspenseInstance(parentInstance, type, props) {
- {
- // $FlowFixMe: Only Element or Document can be parent nodes.
- var parentNode = parentInstance.parentNode;
- if (parentNode !== null) warnForInsertedHydratedElement(parentNode, type);
- }
- }
- function didNotFindHydratableTextInstanceWithinSuspenseInstance(parentInstance, text) {
- {
- // $FlowFixMe: Only Element or Document can be parent nodes.
- var parentNode = parentInstance.parentNode;
- if (parentNode !== null) warnForInsertedHydratedText(parentNode, text);
- }
- }
- function didNotFindHydratableInstance(parentType, parentProps, parentInstance, type, props, isConcurrentMode) {
- {
- if (isConcurrentMode || parentProps[SUPPRESS_HYDRATION_WARNING$1] !== true) {
- warnForInsertedHydratedElement(parentInstance, type);
- }
- }
- }
- function didNotFindHydratableTextInstance(parentType, parentProps, parentInstance, text, isConcurrentMode) {
- {
- if (isConcurrentMode || parentProps[SUPPRESS_HYDRATION_WARNING$1] !== true) {
- warnForInsertedHydratedText(parentInstance, text);
- }
- }
- }
- function errorHydratingContainer(parentContainer) {
- {
- // TODO: This gets logged by onRecoverableError, too, so we should be
- // able to remove it.
- error('An error occurred during hydration. The server HTML was replaced with client content in <%s>.', parentContainer.nodeName.toLowerCase());
- }
- }
- function preparePortalMount(portalInstance) {
- listenToAllSupportedEvents(portalInstance);
- }
- var randomKey = Math.random().toString(36).slice(2);
- var internalInstanceKey = '__reactFiber$' + randomKey;
- var internalPropsKey = '__reactProps$' + randomKey;
- var internalContainerInstanceKey = '__reactContainer$' + randomKey;
- var internalEventHandlersKey = '__reactEvents$' + randomKey;
- var internalEventHandlerListenersKey = '__reactListeners$' + randomKey;
- var internalEventHandlesSetKey = '__reactHandles$' + randomKey;
- function detachDeletedInstance(node) {
- // TODO: This function is only called on host components. I don't think all of
- // these fields are relevant.
- delete node[internalInstanceKey];
- delete node[internalPropsKey];
- delete node[internalEventHandlersKey];
- delete node[internalEventHandlerListenersKey];
- delete node[internalEventHandlesSetKey];
- }
- function precacheFiberNode(hostInst, node) {
- node[internalInstanceKey] = hostInst;
- }
- function markContainerAsRoot(hostRoot, node) {
- node[internalContainerInstanceKey] = hostRoot;
- }
- function unmarkContainerAsRoot(node) {
- node[internalContainerInstanceKey] = null;
- }
- function isContainerMarkedAsRoot(node) {
- return !!node[internalContainerInstanceKey];
- } // Given a DOM node, return the closest HostComponent or HostText fiber ancestor.
- // If the target node is part of a hydrated or not yet rendered subtree, then
- // this may also return a SuspenseComponent or HostRoot to indicate that.
- // Conceptually the HostRoot fiber is a child of the Container node. So if you
- // pass the Container node as the targetNode, you will not actually get the
- // HostRoot back. To get to the HostRoot, you need to pass a child of it.
- // The same thing applies to Suspense boundaries.
- function getClosestInstanceFromNode(targetNode) {
- var targetInst = targetNode[internalInstanceKey];
- if (targetInst) {
- // Don't return HostRoot or SuspenseComponent here.
- return targetInst;
- } // If the direct event target isn't a React owned DOM node, we need to look
- // to see if one of its parents is a React owned DOM node.
- var parentNode = targetNode.parentNode;
- while (parentNode) {
- // We'll check if this is a container root that could include
- // React nodes in the future. We need to check this first because
- // if we're a child of a dehydrated container, we need to first
- // find that inner container before moving on to finding the parent
- // instance. Note that we don't check this field on the targetNode
- // itself because the fibers are conceptually between the container
- // node and the first child. It isn't surrounding the container node.
- // If it's not a container, we check if it's an instance.
- targetInst = parentNode[internalContainerInstanceKey] || parentNode[internalInstanceKey];
- if (targetInst) {
- // Since this wasn't the direct target of the event, we might have
- // stepped past dehydrated DOM nodes to get here. However they could
- // also have been non-React nodes. We need to answer which one.
- // If we the instance doesn't have any children, then there can't be
- // a nested suspense boundary within it. So we can use this as a fast
- // bailout. Most of the time, when people add non-React children to
- // the tree, it is using a ref to a child-less DOM node.
- // Normally we'd only need to check one of the fibers because if it
- // has ever gone from having children to deleting them or vice versa
- // it would have deleted the dehydrated boundary nested inside already.
- // However, since the HostRoot starts out with an alternate it might
- // have one on the alternate so we need to check in case this was a
- // root.
- var alternate = targetInst.alternate;
- if (targetInst.child !== null || alternate !== null && alternate.child !== null) {
- // Next we need to figure out if the node that skipped past is
- // nested within a dehydrated boundary and if so, which one.
- var suspenseInstance = getParentSuspenseInstance(targetNode);
- while (suspenseInstance !== null) {
- // We found a suspense instance. That means that we haven't
- // hydrated it yet. Even though we leave the comments in the
- // DOM after hydrating, and there are boundaries in the DOM
- // that could already be hydrated, we wouldn't have found them
- // through this pass since if the target is hydrated it would
- // have had an internalInstanceKey on it.
- // Let's get the fiber associated with the SuspenseComponent
- // as the deepest instance.
- var targetSuspenseInst = suspenseInstance[internalInstanceKey];
- if (targetSuspenseInst) {
- return targetSuspenseInst;
- } // If we don't find a Fiber on the comment, it might be because
- // we haven't gotten to hydrate it yet. There might still be a
- // parent boundary that hasn't above this one so we need to find
- // the outer most that is known.
- suspenseInstance = getParentSuspenseInstance(suspenseInstance); // If we don't find one, then that should mean that the parent
- // host component also hasn't hydrated yet. We can return it
- // below since it will bail out on the isMounted check later.
- }
- }
- return targetInst;
- }
- targetNode = parentNode;
- parentNode = targetNode.parentNode;
- }
- return null;
- }
- /**
- * Given a DOM node, return the ReactDOMComponent or ReactDOMTextComponent
- * instance, or null if the node was not rendered by this React.
- */
- function getInstanceFromNode(node) {
- var inst = node[internalInstanceKey] || node[internalContainerInstanceKey];
- if (inst) {
- if (inst.tag === HostComponent || inst.tag === HostText || inst.tag === SuspenseComponent || inst.tag === HostRoot) {
- return inst;
- } else {
- return null;
- }
- }
- return null;
- }
- /**
- * Given a ReactDOMComponent or ReactDOMTextComponent, return the corresponding
- * DOM node.
- */
- function getNodeFromInstance(inst) {
- if (inst.tag === HostComponent || inst.tag === HostText) {
- // In Fiber this, is just the state node right now. We assume it will be
- // a host component or host text.
- return inst.stateNode;
- } // Without this first invariant, passing a non-DOM-component triggers the next
- // invariant for a missing parent, which is super confusing.
- throw new Error('getNodeFromInstance: Invalid argument.');
- }
- function getFiberCurrentPropsFromNode(node) {
- return node[internalPropsKey] || null;
- }
- function updateFiberProps(node, props) {
- node[internalPropsKey] = props;
- }
- function getEventListenerSet(node) {
- var elementListenerSet = node[internalEventHandlersKey];
- if (elementListenerSet === undefined) {
- elementListenerSet = node[internalEventHandlersKey] = new Set();
- }
- return elementListenerSet;
- }
- var loggedTypeFailures = {};
- var ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame;
- function setCurrentlyValidatingElement(element) {
- {
- if (element) {
- var owner = element._owner;
- var stack = describeUnknownElementTypeFrameInDEV(element.type, element._source, owner ? owner.type : null);
- ReactDebugCurrentFrame$1.setExtraStackFrame(stack);
- } else {
- ReactDebugCurrentFrame$1.setExtraStackFrame(null);
- }
- }
- }
- function checkPropTypes(typeSpecs, values, location, componentName, element) {
- {
- // $FlowFixMe This is okay but Flow doesn't know it.
- var has = Function.call.bind(hasOwnProperty);
- for (var typeSpecName in typeSpecs) {
- if (has(typeSpecs, typeSpecName)) {
- var error$1 = void 0; // Prop type validation may throw. In case they do, we don't want to
- // fail the render phase where it didn't fail before. So we log it.
- // After these have been cleaned up, we'll let them throw.
- try {
- // This is intentionally an invariant that gets caught. It's the same
- // behavior as without this statement except with a better message.
- if (typeof typeSpecs[typeSpecName] !== 'function') {
- // eslint-disable-next-line react-internal/prod-error-codes
- var err = Error((componentName || 'React class') + ': ' + location + ' type `' + typeSpecName + '` is invalid; ' + 'it must be a function, usually from the `prop-types` package, but received `' + typeof typeSpecs[typeSpecName] + '`.' + 'This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`.');
- err.name = 'Invariant Violation';
- throw err;
- }
- error$1 = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED');
- } catch (ex) {
- error$1 = ex;
- }
- if (error$1 && !(error$1 instanceof Error)) {
- setCurrentlyValidatingElement(element);
- error('%s: type specification of %s' + ' `%s` is invalid; the type checker ' + 'function must return `null` or an `Error` but returned a %s. ' + 'You may have forgotten to pass an argument to the type checker ' + 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + 'shape all require an argument).', componentName || 'React class', location, typeSpecName, typeof error$1);
- setCurrentlyValidatingElement(null);
- }
- if (error$1 instanceof Error && !(error$1.message in loggedTypeFailures)) {
- // Only monitor this failure once because there tends to be a lot of the
- // same error.
- loggedTypeFailures[error$1.message] = true;
- setCurrentlyValidatingElement(element);
- error('Failed %s type: %s', location, error$1.message);
- setCurrentlyValidatingElement(null);
- }
- }
- }
- }
- }
- var valueStack = [];
- var fiberStack;
- {
- fiberStack = [];
- }
- var index = -1;
- function createCursor(defaultValue) {
- return {
- current: defaultValue
- };
- }
- function pop(cursor, fiber) {
- if (index < 0) {
- {
- error('Unexpected pop.');
- }
- return;
- }
- {
- if (fiber !== fiberStack[index]) {
- error('Unexpected Fiber popped.');
- }
- }
- cursor.current = valueStack[index];
- valueStack[index] = null;
- {
- fiberStack[index] = null;
- }
- index--;
- }
- function push(cursor, value, fiber) {
- index++;
- valueStack[index] = cursor.current;
- {
- fiberStack[index] = fiber;
- }
- cursor.current = value;
- }
- var warnedAboutMissingGetChildContext;
- {
- warnedAboutMissingGetChildContext = {};
- }
- var emptyContextObject = {};
- {
- Object.freeze(emptyContextObject);
- } // A cursor to the current merged context object on the stack.
- var contextStackCursor = createCursor(emptyContextObject); // A cursor to a boolean indicating whether the context has changed.
- var didPerformWorkStackCursor = createCursor(false); // Keep track of the previous context object that was on the stack.
- // We use this to get access to the parent context after we have already
- // pushed the next context provider, and now need to merge their contexts.
- var previousContext = emptyContextObject;
- function getUnmaskedContext(workInProgress, Component, didPushOwnContextIfProvider) {
- {
- if (didPushOwnContextIfProvider && isContextProvider(Component)) {
- // If the fiber is a context provider itself, when we read its context
- // we may have already pushed its own child context on the stack. A context
- // provider should not "see" its own child context. Therefore we read the
- // previous (parent) context instead for a context provider.
- return previousContext;
- }
- return contextStackCursor.current;
- }
- }
- function cacheContext(workInProgress, unmaskedContext, maskedContext) {
- {
- var instance = workInProgress.stateNode;
- instance.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext;
- instance.__reactInternalMemoizedMaskedChildContext = maskedContext;
- }
- }
- function getMaskedContext(workInProgress, unmaskedContext) {
- {
- var type = workInProgress.type;
- var contextTypes = type.contextTypes;
- if (!contextTypes) {
- return emptyContextObject;
- } // Avoid recreating masked context unless unmasked context has changed.
- // Failing to do this will result in unnecessary calls to componentWillReceiveProps.
- // This may trigger infinite loops if componentWillReceiveProps calls setState.
- var instance = workInProgress.stateNode;
- if (instance && instance.__reactInternalMemoizedUnmaskedChildContext === unmaskedContext) {
- return instance.__reactInternalMemoizedMaskedChildContext;
- }
- var context = {};
- for (var key in contextTypes) {
- context[key] = unmaskedContext[key];
- }
- {
- var name = getComponentNameFromFiber(workInProgress) || 'Unknown';
- checkPropTypes(contextTypes, context, 'context', name);
- } // Cache unmasked context so we can avoid recreating masked context unless necessary.
- // Context is created before the class component is instantiated so check for instance.
- if (instance) {
- cacheContext(workInProgress, unmaskedContext, context);
- }
- return context;
- }
- }
- function hasContextChanged() {
- {
- return didPerformWorkStackCursor.current;
- }
- }
- function isContextProvider(type) {
- {
- var childContextTypes = type.childContextTypes;
- return childContextTypes !== null && childContextTypes !== undefined;
- }
- }
- function popContext(fiber) {
- {
- pop(didPerformWorkStackCursor, fiber);
- pop(contextStackCursor, fiber);
- }
- }
- function popTopLevelContextObject(fiber) {
- {
- pop(didPerformWorkStackCursor, fiber);
- pop(contextStackCursor, fiber);
- }
- }
- function pushTopLevelContextObject(fiber, context, didChange) {
- {
- if (contextStackCursor.current !== emptyContextObject) {
- throw new Error('Unexpected context found on stack. ' + 'This error is likely caused by a bug in React. Please file an issue.');
- }
- push(contextStackCursor, context, fiber);
- push(didPerformWorkStackCursor, didChange, fiber);
- }
- }
- function processChildContext(fiber, type, parentContext) {
- {
- var instance = fiber.stateNode;
- var childContextTypes = type.childContextTypes; // TODO (bvaughn) Replace this behavior with an invariant() in the future.
- // It has only been added in Fiber to match the (unintentional) behavior in Stack.
- if (typeof instance.getChildContext !== 'function') {
- {
- var componentName = getComponentNameFromFiber(fiber) || 'Unknown';
- if (!warnedAboutMissingGetChildContext[componentName]) {
- warnedAboutMissingGetChildContext[componentName] = true;
- error('%s.childContextTypes is specified but there is no getChildContext() method ' + 'on the instance. You can either define getChildContext() on %s or remove ' + 'childContextTypes from it.', componentName, componentName);
- }
- }
- return parentContext;
- }
- var childContext = instance.getChildContext();
- for (var contextKey in childContext) {
- if (!(contextKey in childContextTypes)) {
- throw new Error((getComponentNameFromFiber(fiber) || 'Unknown') + ".getChildContext(): key \"" + contextKey + "\" is not defined in childContextTypes.");
- }
- }
- {
- var name = getComponentNameFromFiber(fiber) || 'Unknown';
- checkPropTypes(childContextTypes, childContext, 'child context', name);
- }
- return assign({}, parentContext, childContext);
- }
- }
- function pushContextProvider(workInProgress) {
- {
- var instance = workInProgress.stateNode; // We push the context as early as possible to ensure stack integrity.
- // If the instance does not exist yet, we will push null at first,
- // and replace it on the stack later when invalidating the context.
- var memoizedMergedChildContext = instance && instance.__reactInternalMemoizedMergedChildContext || emptyContextObject; // Remember the parent context so we can merge with it later.
- // Inherit the parent's did-perform-work value to avoid inadvertently blocking updates.
- previousContext = contextStackCursor.current;
- push(contextStackCursor, memoizedMergedChildContext, workInProgress);
- push(didPerformWorkStackCursor, didPerformWorkStackCursor.current, workInProgress);
- return true;
- }
- }
- function invalidateContextProvider(workInProgress, type, didChange) {
- {
- var instance = workInProgress.stateNode;
- if (!instance) {
- throw new Error('Expected to have an instance by this point. ' + 'This error is likely caused by a bug in React. Please file an issue.');
- }
- if (didChange) {
- // Merge parent and own context.
- // Skip this if we're not updating due to sCU.
- // This avoids unnecessarily recomputing memoized values.
- var mergedContext = processChildContext(workInProgress, type, previousContext);
- instance.__reactInternalMemoizedMergedChildContext = mergedContext; // Replace the old (or empty) context with the new one.
- // It is important to unwind the context in the reverse order.
- pop(didPerformWorkStackCursor, workInProgress);
- pop(contextStackCursor, workInProgress); // Now push the new context and mark that it has changed.
- push(contextStackCursor, mergedContext, workInProgress);
- push(didPerformWorkStackCursor, didChange, workInProgress);
- } else {
- pop(didPerformWorkStackCursor, workInProgress);
- push(didPerformWorkStackCursor, didChange, workInProgress);
- }
- }
- }
- function findCurrentUnmaskedContext(fiber) {
- {
- // Currently this is only used with renderSubtreeIntoContainer; not sure if it
- // makes sense elsewhere
- if (!isFiberMounted(fiber) || fiber.tag !== ClassComponent) {
- throw new Error('Expected subtree parent to be a mounted class component. ' + 'This error is likely caused by a bug in React. Please file an issue.');
- }
- var node = fiber;
- do {
- switch (node.tag) {
- case HostRoot:
- return node.stateNode.context;
- case ClassComponent:
- {
- var Component = node.type;
- if (isContextProvider(Component)) {
- return node.stateNode.__reactInternalMemoizedMergedChildContext;
- }
- break;
- }
- }
- node = node.return;
- } while (node !== null);
- throw new Error('Found unexpected detached subtree parent. ' + 'This error is likely caused by a bug in React. Please file an issue.');
- }
- }
- var LegacyRoot = 0;
- var ConcurrentRoot = 1;
- var syncQueue = null;
- var includesLegacySyncCallbacks = false;
- var isFlushingSyncQueue = false;
- function scheduleSyncCallback(callback) {
- // Push this callback into an internal queue. We'll flush these either in
- // the next tick, or earlier if something calls `flushSyncCallbackQueue`.
- if (syncQueue === null) {
- syncQueue = [callback];
- } else {
- // Push onto existing queue. Don't need to schedule a callback because
- // we already scheduled one when we created the queue.
- syncQueue.push(callback);
- }
- }
- function scheduleLegacySyncCallback(callback) {
- includesLegacySyncCallbacks = true;
- scheduleSyncCallback(callback);
- }
- function flushSyncCallbacksOnlyInLegacyMode() {
- // Only flushes the queue if there's a legacy sync callback scheduled.
- // TODO: There's only a single type of callback: performSyncOnWorkOnRoot. So
- // it might make more sense for the queue to be a list of roots instead of a
- // list of generic callbacks. Then we can have two: one for legacy roots, one
- // for concurrent roots. And this method would only flush the legacy ones.
- if (includesLegacySyncCallbacks) {
- flushSyncCallbacks();
- }
- }
- function flushSyncCallbacks() {
- if (!isFlushingSyncQueue && syncQueue !== null) {
- // Prevent re-entrance.
- isFlushingSyncQueue = true;
- var i = 0;
- var previousUpdatePriority = getCurrentUpdatePriority();
- try {
- var isSync = true;
- var queue = syncQueue; // TODO: Is this necessary anymore? The only user code that runs in this
- // queue is in the render or commit phases.
- setCurrentUpdatePriority(DiscreteEventPriority);
- for (; i < queue.length; i++) {
- var callback = queue[i];
- do {
- callback = callback(isSync);
- } while (callback !== null);
- }
- syncQueue = null;
- includesLegacySyncCallbacks = false;
- } catch (error) {
- // If something throws, leave the remaining callbacks on the queue.
- if (syncQueue !== null) {
- syncQueue = syncQueue.slice(i + 1);
- } // Resume flushing in the next tick
- scheduleCallback(ImmediatePriority, flushSyncCallbacks);
- throw error;
- } finally {
- setCurrentUpdatePriority(previousUpdatePriority);
- isFlushingSyncQueue = false;
- }
- }
- return null;
- }
- // TODO: Use the unified fiber stack module instead of this local one?
- // Intentionally not using it yet to derisk the initial implementation, because
- // the way we push/pop these values is a bit unusual. If there's a mistake, I'd
- // rather the ids be wrong than crash the whole reconciler.
- var forkStack = [];
- var forkStackIndex = 0;
- var treeForkProvider = null;
- var treeForkCount = 0;
- var idStack = [];
- var idStackIndex = 0;
- var treeContextProvider = null;
- var treeContextId = 1;
- var treeContextOverflow = '';
- function isForkedChild(workInProgress) {
- warnIfNotHydrating();
- return (workInProgress.flags & Forked) !== NoFlags;
- }
- function getForksAtLevel(workInProgress) {
- warnIfNotHydrating();
- return treeForkCount;
- }
- function getTreeId() {
- var overflow = treeContextOverflow;
- var idWithLeadingBit = treeContextId;
- var id = idWithLeadingBit & ~getLeadingBit(idWithLeadingBit);
- return id.toString(32) + overflow;
- }
- function pushTreeFork(workInProgress, totalChildren) {
- // This is called right after we reconcile an array (or iterator) of child
- // fibers, because that's the only place where we know how many children in
- // the whole set without doing extra work later, or storing addtional
- // information on the fiber.
- //
- // That's why this function is separate from pushTreeId — it's called during
- // the render phase of the fork parent, not the child, which is where we push
- // the other context values.
- //
- // In the Fizz implementation this is much simpler because the child is
- // rendered in the same callstack as the parent.
- //
- // It might be better to just add a `forks` field to the Fiber type. It would
- // make this module simpler.
- warnIfNotHydrating();
- forkStack[forkStackIndex++] = treeForkCount;
- forkStack[forkStackIndex++] = treeForkProvider;
- treeForkProvider = workInProgress;
- treeForkCount = totalChildren;
- }
- function pushTreeId(workInProgress, totalChildren, index) {
- warnIfNotHydrating();
- idStack[idStackIndex++] = treeContextId;
- idStack[idStackIndex++] = treeContextOverflow;
- idStack[idStackIndex++] = treeContextProvider;
- treeContextProvider = workInProgress;
- var baseIdWithLeadingBit = treeContextId;
- var baseOverflow = treeContextOverflow; // The leftmost 1 marks the end of the sequence, non-inclusive. It's not part
- // of the id; we use it to account for leading 0s.
- var baseLength = getBitLength(baseIdWithLeadingBit) - 1;
- var baseId = baseIdWithLeadingBit & ~(1 << baseLength);
- var slot = index + 1;
- var length = getBitLength(totalChildren) + baseLength; // 30 is the max length we can store without overflowing, taking into
- // consideration the leading 1 we use to mark the end of the sequence.
- if (length > 30) {
- // We overflowed the bitwise-safe range. Fall back to slower algorithm.
- // This branch assumes the length of the base id is greater than 5; it won't
- // work for smaller ids, because you need 5 bits per character.
- //
- // We encode the id in multiple steps: first the base id, then the
- // remaining digits.
- //
- // Each 5 bit sequence corresponds to a single base 32 character. So for
- // example, if the current id is 23 bits long, we can convert 20 of those
- // bits into a string of 4 characters, with 3 bits left over.
- //
- // First calculate how many bits in the base id represent a complete
- // sequence of characters.
- var numberOfOverflowBits = baseLength - baseLength % 5; // Then create a bitmask that selects only those bits.
- var newOverflowBits = (1 << numberOfOverflowBits) - 1; // Select the bits, and convert them to a base 32 string.
- var newOverflow = (baseId & newOverflowBits).toString(32); // Now we can remove those bits from the base id.
- var restOfBaseId = baseId >> numberOfOverflowBits;
- var restOfBaseLength = baseLength - numberOfOverflowBits; // Finally, encode the rest of the bits using the normal algorithm. Because
- // we made more room, this time it won't overflow.
- var restOfLength = getBitLength(totalChildren) + restOfBaseLength;
- var restOfNewBits = slot << restOfBaseLength;
- var id = restOfNewBits | restOfBaseId;
- var overflow = newOverflow + baseOverflow;
- treeContextId = 1 << restOfLength | id;
- treeContextOverflow = overflow;
- } else {
- // Normal path
- var newBits = slot << baseLength;
- var _id = newBits | baseId;
- var _overflow = baseOverflow;
- treeContextId = 1 << length | _id;
- treeContextOverflow = _overflow;
- }
- }
- function pushMaterializedTreeId(workInProgress) {
- warnIfNotHydrating(); // This component materialized an id. This will affect any ids that appear
- // in its children.
- var returnFiber = workInProgress.return;
- if (returnFiber !== null) {
- var numberOfForks = 1;
- var slotIndex = 0;
- pushTreeFork(workInProgress, numberOfForks);
- pushTreeId(workInProgress, numberOfForks, slotIndex);
- }
- }
- function getBitLength(number) {
- return 32 - clz32(number);
- }
- function getLeadingBit(id) {
- return 1 << getBitLength(id) - 1;
- }
- function popTreeContext(workInProgress) {
- // Restore the previous values.
- // This is a bit more complicated than other context-like modules in Fiber
- // because the same Fiber may appear on the stack multiple times and for
- // different reasons. We have to keep popping until the work-in-progress is
- // no longer at the top of the stack.
- while (workInProgress === treeForkProvider) {
- treeForkProvider = forkStack[--forkStackIndex];
- forkStack[forkStackIndex] = null;
- treeForkCount = forkStack[--forkStackIndex];
- forkStack[forkStackIndex] = null;
- }
- while (workInProgress === treeContextProvider) {
- treeContextProvider = idStack[--idStackIndex];
- idStack[idStackIndex] = null;
- treeContextOverflow = idStack[--idStackIndex];
- idStack[idStackIndex] = null;
- treeContextId = idStack[--idStackIndex];
- idStack[idStackIndex] = null;
- }
- }
- function getSuspendedTreeContext() {
- warnIfNotHydrating();
- if (treeContextProvider !== null) {
- return {
- id: treeContextId,
- overflow: treeContextOverflow
- };
- } else {
- return null;
- }
- }
- function restoreSuspendedTreeContext(workInProgress, suspendedContext) {
- warnIfNotHydrating();
- idStack[idStackIndex++] = treeContextId;
- idStack[idStackIndex++] = treeContextOverflow;
- idStack[idStackIndex++] = treeContextProvider;
- treeContextId = suspendedContext.id;
- treeContextOverflow = suspendedContext.overflow;
- treeContextProvider = workInProgress;
- }
- function warnIfNotHydrating() {
- {
- if (!getIsHydrating()) {
- error('Expected to be hydrating. This is a bug in React. Please file ' + 'an issue.');
- }
- }
- }
- // This may have been an insertion or a hydration.
- var hydrationParentFiber = null;
- var nextHydratableInstance = null;
- var isHydrating = false; // This flag allows for warning supression when we expect there to be mismatches
- // due to earlier mismatches or a suspended fiber.
- var didSuspendOrErrorDEV = false; // Hydration errors that were thrown inside this boundary
- var hydrationErrors = null;
- function warnIfHydrating() {
- {
- if (isHydrating) {
- error('We should not be hydrating here. This is a bug in React. Please file a bug.');
- }
- }
- }
- function markDidThrowWhileHydratingDEV() {
- {
- didSuspendOrErrorDEV = true;
- }
- }
- function didSuspendOrErrorWhileHydratingDEV() {
- {
- return didSuspendOrErrorDEV;
- }
- }
- function enterHydrationState(fiber) {
- var parentInstance = fiber.stateNode.containerInfo;
- nextHydratableInstance = getFirstHydratableChildWithinContainer(parentInstance);
- hydrationParentFiber = fiber;
- isHydrating = true;
- hydrationErrors = null;
- didSuspendOrErrorDEV = false;
- return true;
- }
- function reenterHydrationStateFromDehydratedSuspenseInstance(fiber, suspenseInstance, treeContext) {
- nextHydratableInstance = getFirstHydratableChildWithinSuspenseInstance(suspenseInstance);
- hydrationParentFiber = fiber;
- isHydrating = true;
- hydrationErrors = null;
- didSuspendOrErrorDEV = false;
- if (treeContext !== null) {
- restoreSuspendedTreeContext(fiber, treeContext);
- }
- return true;
- }
- function warnUnhydratedInstance(returnFiber, instance) {
- {
- switch (returnFiber.tag) {
- case HostRoot:
- {
- didNotHydrateInstanceWithinContainer(returnFiber.stateNode.containerInfo, instance);
- break;
- }
- case HostComponent:
- {
- var isConcurrentMode = (returnFiber.mode & ConcurrentMode) !== NoMode;
- didNotHydrateInstance(returnFiber.type, returnFiber.memoizedProps, returnFiber.stateNode, instance, // TODO: Delete this argument when we remove the legacy root API.
- isConcurrentMode);
- break;
- }
- case SuspenseComponent:
- {
- var suspenseState = returnFiber.memoizedState;
- if (suspenseState.dehydrated !== null) didNotHydrateInstanceWithinSuspenseInstance(suspenseState.dehydrated, instance);
- break;
- }
- }
- }
- }
- function deleteHydratableInstance(returnFiber, instance) {
- warnUnhydratedInstance(returnFiber, instance);
- var childToDelete = createFiberFromHostInstanceForDeletion();
- childToDelete.stateNode = instance;
- childToDelete.return = returnFiber;
- var deletions = returnFiber.deletions;
- if (deletions === null) {
- returnFiber.deletions = [childToDelete];
- returnFiber.flags |= ChildDeletion;
- } else {
- deletions.push(childToDelete);
- }
- }
- function warnNonhydratedInstance(returnFiber, fiber) {
- {
- if (didSuspendOrErrorDEV) {
- // Inside a boundary that already suspended. We're currently rendering the
- // siblings of a suspended node. The mismatch may be due to the missing
- // data, so it's probably a false positive.
- return;
- }
- switch (returnFiber.tag) {
- case HostRoot:
- {
- var parentContainer = returnFiber.stateNode.containerInfo;
- switch (fiber.tag) {
- case HostComponent:
- var type = fiber.type;
- var props = fiber.pendingProps;
- didNotFindHydratableInstanceWithinContainer(parentContainer, type);
- break;
- case HostText:
- var text = fiber.pendingProps;
- didNotFindHydratableTextInstanceWithinContainer(parentContainer, text);
- break;
- }
- break;
- }
- case HostComponent:
- {
- var parentType = returnFiber.type;
- var parentProps = returnFiber.memoizedProps;
- var parentInstance = returnFiber.stateNode;
- switch (fiber.tag) {
- case HostComponent:
- {
- var _type = fiber.type;
- var _props = fiber.pendingProps;
- var isConcurrentMode = (returnFiber.mode & ConcurrentMode) !== NoMode;
- didNotFindHydratableInstance(parentType, parentProps, parentInstance, _type, _props, // TODO: Delete this argument when we remove the legacy root API.
- isConcurrentMode);
- break;
- }
- case HostText:
- {
- var _text = fiber.pendingProps;
- var _isConcurrentMode = (returnFiber.mode & ConcurrentMode) !== NoMode;
- didNotFindHydratableTextInstance(parentType, parentProps, parentInstance, _text, // TODO: Delete this argument when we remove the legacy root API.
- _isConcurrentMode);
- break;
- }
- }
- break;
- }
- case SuspenseComponent:
- {
- var suspenseState = returnFiber.memoizedState;
- var _parentInstance = suspenseState.dehydrated;
- if (_parentInstance !== null) switch (fiber.tag) {
- case HostComponent:
- var _type2 = fiber.type;
- var _props2 = fiber.pendingProps;
- didNotFindHydratableInstanceWithinSuspenseInstance(_parentInstance, _type2);
- break;
- case HostText:
- var _text2 = fiber.pendingProps;
- didNotFindHydratableTextInstanceWithinSuspenseInstance(_parentInstance, _text2);
- break;
- }
- break;
- }
- default:
- return;
- }
- }
- }
- function insertNonHydratedInstance(returnFiber, fiber) {
- fiber.flags = fiber.flags & ~Hydrating | Placement;
- warnNonhydratedInstance(returnFiber, fiber);
- }
- function tryHydrate(fiber, nextInstance) {
- switch (fiber.tag) {
- case HostComponent:
- {
- var type = fiber.type;
- var props = fiber.pendingProps;
- var instance = canHydrateInstance(nextInstance, type);
- if (instance !== null) {
- fiber.stateNode = instance;
- hydrationParentFiber = fiber;
- nextHydratableInstance = getFirstHydratableChild(instance);
- return true;
- }
- return false;
- }
- case HostText:
- {
- var text = fiber.pendingProps;
- var textInstance = canHydrateTextInstance(nextInstance, text);
- if (textInstance !== null) {
- fiber.stateNode = textInstance;
- hydrationParentFiber = fiber; // Text Instances don't have children so there's nothing to hydrate.
- nextHydratableInstance = null;
- return true;
- }
- return false;
- }
- case SuspenseComponent:
- {
- var suspenseInstance = canHydrateSuspenseInstance(nextInstance);
- if (suspenseInstance !== null) {
- var suspenseState = {
- dehydrated: suspenseInstance,
- treeContext: getSuspendedTreeContext(),
- retryLane: OffscreenLane
- };
- fiber.memoizedState = suspenseState; // Store the dehydrated fragment as a child fiber.
- // This simplifies the code for getHostSibling and deleting nodes,
- // since it doesn't have to consider all Suspense boundaries and
- // check if they're dehydrated ones or not.
- var dehydratedFragment = createFiberFromDehydratedFragment(suspenseInstance);
- dehydratedFragment.return = fiber;
- fiber.child = dehydratedFragment;
- hydrationParentFiber = fiber; // While a Suspense Instance does have children, we won't step into
- // it during the first pass. Instead, we'll reenter it later.
- nextHydratableInstance = null;
- return true;
- }
- return false;
- }
- default:
- return false;
- }
- }
- function shouldClientRenderOnMismatch(fiber) {
- return (fiber.mode & ConcurrentMode) !== NoMode && (fiber.flags & DidCapture) === NoFlags;
- }
- function throwOnHydrationMismatch(fiber) {
- throw new Error('Hydration failed because the initial UI does not match what was ' + 'rendered on the server.');
- }
- function tryToClaimNextHydratableInstance(fiber) {
- if (!isHydrating) {
- return;
- }
- var nextInstance = nextHydratableInstance;
- if (!nextInstance) {
- if (shouldClientRenderOnMismatch(fiber)) {
- warnNonhydratedInstance(hydrationParentFiber, fiber);
- throwOnHydrationMismatch();
- } // Nothing to hydrate. Make it an insertion.
- insertNonHydratedInstance(hydrationParentFiber, fiber);
- isHydrating = false;
- hydrationParentFiber = fiber;
- return;
- }
- var firstAttemptedInstance = nextInstance;
- if (!tryHydrate(fiber, nextInstance)) {
- if (shouldClientRenderOnMismatch(fiber)) {
- warnNonhydratedInstance(hydrationParentFiber, fiber);
- throwOnHydrationMismatch();
- } // If we can't hydrate this instance let's try the next one.
- // We use this as a heuristic. It's based on intuition and not data so it
- // might be flawed or unnecessary.
- nextInstance = getNextHydratableSibling(firstAttemptedInstance);
- var prevHydrationParentFiber = hydrationParentFiber;
- if (!nextInstance || !tryHydrate(fiber, nextInstance)) {
- // Nothing to hydrate. Make it an insertion.
- insertNonHydratedInstance(hydrationParentFiber, fiber);
- isHydrating = false;
- hydrationParentFiber = fiber;
- return;
- } // We matched the next one, we'll now assume that the first one was
- // superfluous and we'll delete it. Since we can't eagerly delete it
- // we'll have to schedule a deletion. To do that, this node needs a dummy
- // fiber associated with it.
- deleteHydratableInstance(prevHydrationParentFiber, firstAttemptedInstance);
- }
- }
- function prepareToHydrateHostInstance(fiber, rootContainerInstance, hostContext) {
- var instance = fiber.stateNode;
- var shouldWarnIfMismatchDev = !didSuspendOrErrorDEV;
- var updatePayload = hydrateInstance(instance, fiber.type, fiber.memoizedProps, rootContainerInstance, hostContext, fiber, shouldWarnIfMismatchDev); // TODO: Type this specific to this type of component.
- fiber.updateQueue = updatePayload; // If the update payload indicates that there is a change or if there
- // is a new ref we mark this as an update.
- if (updatePayload !== null) {
- return true;
- }
- return false;
- }
- function prepareToHydrateHostTextInstance(fiber) {
- var textInstance = fiber.stateNode;
- var textContent = fiber.memoizedProps;
- var shouldUpdate = hydrateTextInstance(textInstance, textContent, fiber);
- if (shouldUpdate) {
- // We assume that prepareToHydrateHostTextInstance is called in a context where the
- // hydration parent is the parent host component of this host text.
- var returnFiber = hydrationParentFiber;
- if (returnFiber !== null) {
- switch (returnFiber.tag) {
- case HostRoot:
- {
- var parentContainer = returnFiber.stateNode.containerInfo;
- var isConcurrentMode = (returnFiber.mode & ConcurrentMode) !== NoMode;
- didNotMatchHydratedContainerTextInstance(parentContainer, textInstance, textContent, // TODO: Delete this argument when we remove the legacy root API.
- isConcurrentMode);
- break;
- }
- case HostComponent:
- {
- var parentType = returnFiber.type;
- var parentProps = returnFiber.memoizedProps;
- var parentInstance = returnFiber.stateNode;
- var _isConcurrentMode2 = (returnFiber.mode & ConcurrentMode) !== NoMode;
- didNotMatchHydratedTextInstance(parentType, parentProps, parentInstance, textInstance, textContent, // TODO: Delete this argument when we remove the legacy root API.
- _isConcurrentMode2);
- break;
- }
- }
- }
- }
- return shouldUpdate;
- }
- function prepareToHydrateHostSuspenseInstance(fiber) {
- var suspenseState = fiber.memoizedState;
- var suspenseInstance = suspenseState !== null ? suspenseState.dehydrated : null;
- if (!suspenseInstance) {
- throw new Error('Expected to have a hydrated suspense instance. ' + 'This error is likely caused by a bug in React. Please file an issue.');
- }
- hydrateSuspenseInstance(suspenseInstance, fiber);
- }
- function skipPastDehydratedSuspenseInstance(fiber) {
- var suspenseState = fiber.memoizedState;
- var suspenseInstance = suspenseState !== null ? suspenseState.dehydrated : null;
- if (!suspenseInstance) {
- throw new Error('Expected to have a hydrated suspense instance. ' + 'This error is likely caused by a bug in React. Please file an issue.');
- }
- return getNextHydratableInstanceAfterSuspenseInstance(suspenseInstance);
- }
- function popToNextHostParent(fiber) {
- var parent = fiber.return;
- while (parent !== null && parent.tag !== HostComponent && parent.tag !== HostRoot && parent.tag !== SuspenseComponent) {
- parent = parent.return;
- }
- hydrationParentFiber = parent;
- }
- function popHydrationState(fiber) {
- if (fiber !== hydrationParentFiber) {
- // We're deeper than the current hydration context, inside an inserted
- // tree.
- return false;
- }
- if (!isHydrating) {
- // If we're not currently hydrating but we're in a hydration context, then
- // we were an insertion and now need to pop up reenter hydration of our
- // siblings.
- popToNextHostParent(fiber);
- isHydrating = true;
- return false;
- } // If we have any remaining hydratable nodes, we need to delete them now.
- // We only do this deeper than head and body since they tend to have random
- // other nodes in them. We also ignore components with pure text content in
- // side of them. We also don't delete anything inside the root container.
- if (fiber.tag !== HostRoot && (fiber.tag !== HostComponent || shouldDeleteUnhydratedTailInstances(fiber.type) && !shouldSetTextContent(fiber.type, fiber.memoizedProps))) {
- var nextInstance = nextHydratableInstance;
- if (nextInstance) {
- if (shouldClientRenderOnMismatch(fiber)) {
- warnIfUnhydratedTailNodes(fiber);
- throwOnHydrationMismatch();
- } else {
- while (nextInstance) {
- deleteHydratableInstance(fiber, nextInstance);
- nextInstance = getNextHydratableSibling(nextInstance);
- }
- }
- }
- }
- popToNextHostParent(fiber);
- if (fiber.tag === SuspenseComponent) {
- nextHydratableInstance = skipPastDehydratedSuspenseInstance(fiber);
- } else {
- nextHydratableInstance = hydrationParentFiber ? getNextHydratableSibling(fiber.stateNode) : null;
- }
- return true;
- }
- function hasUnhydratedTailNodes() {
- return isHydrating && nextHydratableInstance !== null;
- }
- function warnIfUnhydratedTailNodes(fiber) {
- var nextInstance = nextHydratableInstance;
- while (nextInstance) {
- warnUnhydratedInstance(fiber, nextInstance);
- nextInstance = getNextHydratableSibling(nextInstance);
- }
- }
- function resetHydrationState() {
- hydrationParentFiber = null;
- nextHydratableInstance = null;
- isHydrating = false;
- didSuspendOrErrorDEV = false;
- }
- function upgradeHydrationErrorsToRecoverable() {
- if (hydrationErrors !== null) {
- // Successfully completed a forced client render. The errors that occurred
- // during the hydration attempt are now recovered. We will log them in
- // commit phase, once the entire tree has finished.
- queueRecoverableErrors(hydrationErrors);
- hydrationErrors = null;
- }
- }
- function getIsHydrating() {
- return isHydrating;
- }
- function queueHydrationError(error) {
- if (hydrationErrors === null) {
- hydrationErrors = [error];
- } else {
- hydrationErrors.push(error);
- }
- }
- var ReactCurrentBatchConfig$1 = ReactSharedInternals.ReactCurrentBatchConfig;
- var NoTransition = null;
- function requestCurrentTransition() {
- return ReactCurrentBatchConfig$1.transition;
- }
- var ReactStrictModeWarnings = {
- recordUnsafeLifecycleWarnings: function (fiber, instance) { },
- flushPendingUnsafeLifecycleWarnings: function () { },
- recordLegacyContextWarning: function (fiber, instance) { },
- flushLegacyContextWarning: function () { },
- discardPendingWarnings: function () { }
- };
- {
- var findStrictRoot = function (fiber) {
- var maybeStrictRoot = null;
- var node = fiber;
- while (node !== null) {
- if (node.mode & StrictLegacyMode) {
- maybeStrictRoot = node;
- }
- node = node.return;
- }
- return maybeStrictRoot;
- };
- var setToSortedString = function (set) {
- var array = [];
- set.forEach(function (value) {
- array.push(value);
- });
- return array.sort().join(', ');
- };
- var pendingComponentWillMountWarnings = [];
- var pendingUNSAFE_ComponentWillMountWarnings = [];
- var pendingComponentWillReceivePropsWarnings = [];
- var pendingUNSAFE_ComponentWillReceivePropsWarnings = [];
- var pendingComponentWillUpdateWarnings = [];
- var pendingUNSAFE_ComponentWillUpdateWarnings = []; // Tracks components we have already warned about.
- var didWarnAboutUnsafeLifecycles = new Set();
- ReactStrictModeWarnings.recordUnsafeLifecycleWarnings = function (fiber, instance) {
- // Dedupe strategy: Warn once per component.
- if (didWarnAboutUnsafeLifecycles.has(fiber.type)) {
- return;
- }
- if (typeof instance.componentWillMount === 'function' && // Don't warn about react-lifecycles-compat polyfilled components.
- instance.componentWillMount.__suppressDeprecationWarning !== true) {
- pendingComponentWillMountWarnings.push(fiber);
- }
- if (fiber.mode & StrictLegacyMode && typeof instance.UNSAFE_componentWillMount === 'function') {
- pendingUNSAFE_ComponentWillMountWarnings.push(fiber);
- }
- if (typeof instance.componentWillReceiveProps === 'function' && instance.componentWillReceiveProps.__suppressDeprecationWarning !== true) {
- pendingComponentWillReceivePropsWarnings.push(fiber);
- }
- if (fiber.mode & StrictLegacyMode && typeof instance.UNSAFE_componentWillReceiveProps === 'function') {
- pendingUNSAFE_ComponentWillReceivePropsWarnings.push(fiber);
- }
- if (typeof instance.componentWillUpdate === 'function' && instance.componentWillUpdate.__suppressDeprecationWarning !== true) {
- pendingComponentWillUpdateWarnings.push(fiber);
- }
- if (fiber.mode & StrictLegacyMode && typeof instance.UNSAFE_componentWillUpdate === 'function') {
- pendingUNSAFE_ComponentWillUpdateWarnings.push(fiber);
- }
- };
- ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings = function () {
- // We do an initial pass to gather component names
- var componentWillMountUniqueNames = new Set();
- if (pendingComponentWillMountWarnings.length > 0) {
- pendingComponentWillMountWarnings.forEach(function (fiber) {
- componentWillMountUniqueNames.add(getComponentNameFromFiber(fiber) || 'Component');
- didWarnAboutUnsafeLifecycles.add(fiber.type);
- });
- pendingComponentWillMountWarnings = [];
- }
- var UNSAFE_componentWillMountUniqueNames = new Set();
- if (pendingUNSAFE_ComponentWillMountWarnings.length > 0) {
- pendingUNSAFE_ComponentWillMountWarnings.forEach(function (fiber) {
- UNSAFE_componentWillMountUniqueNames.add(getComponentNameFromFiber(fiber) || 'Component');
- didWarnAboutUnsafeLifecycles.add(fiber.type);
- });
- pendingUNSAFE_ComponentWillMountWarnings = [];
- }
- var componentWillReceivePropsUniqueNames = new Set();
- if (pendingComponentWillReceivePropsWarnings.length > 0) {
- pendingComponentWillReceivePropsWarnings.forEach(function (fiber) {
- componentWillReceivePropsUniqueNames.add(getComponentNameFromFiber(fiber) || 'Component');
- didWarnAboutUnsafeLifecycles.add(fiber.type);
- });
- pendingComponentWillReceivePropsWarnings = [];
- }
- var UNSAFE_componentWillReceivePropsUniqueNames = new Set();
- if (pendingUNSAFE_ComponentWillReceivePropsWarnings.length > 0) {
- pendingUNSAFE_ComponentWillReceivePropsWarnings.forEach(function (fiber) {
- UNSAFE_componentWillReceivePropsUniqueNames.add(getComponentNameFromFiber(fiber) || 'Component');
- didWarnAboutUnsafeLifecycles.add(fiber.type);
- });
- pendingUNSAFE_ComponentWillReceivePropsWarnings = [];
- }
- var componentWillUpdateUniqueNames = new Set();
- if (pendingComponentWillUpdateWarnings.length > 0) {
- pendingComponentWillUpdateWarnings.forEach(function (fiber) {
- componentWillUpdateUniqueNames.add(getComponentNameFromFiber(fiber) || 'Component');
- didWarnAboutUnsafeLifecycles.add(fiber.type);
- });
- pendingComponentWillUpdateWarnings = [];
- }
- var UNSAFE_componentWillUpdateUniqueNames = new Set();
- if (pendingUNSAFE_ComponentWillUpdateWarnings.length > 0) {
- pendingUNSAFE_ComponentWillUpdateWarnings.forEach(function (fiber) {
- UNSAFE_componentWillUpdateUniqueNames.add(getComponentNameFromFiber(fiber) || 'Component');
- didWarnAboutUnsafeLifecycles.add(fiber.type);
- });
- pendingUNSAFE_ComponentWillUpdateWarnings = [];
- } // Finally, we flush all the warnings
- // UNSAFE_ ones before the deprecated ones, since they'll be 'louder'
- if (UNSAFE_componentWillMountUniqueNames.size > 0) {
- var sortedNames = setToSortedString(UNSAFE_componentWillMountUniqueNames);
- error('Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. ' + 'See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n' + '* Move code with side effects to componentDidMount, and set initial state in the constructor.\n' + '\nPlease update the following components: %s', sortedNames);
- }
- if (UNSAFE_componentWillReceivePropsUniqueNames.size > 0) {
- var _sortedNames = setToSortedString(UNSAFE_componentWillReceivePropsUniqueNames);
- error('Using UNSAFE_componentWillReceiveProps in strict mode is not recommended ' + 'and may indicate bugs in your code. ' + 'See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n' + '* Move data fetching code or side effects to componentDidUpdate.\n' + "* If you're updating state whenever props change, " + 'refactor your code to use memoization techniques or move it to ' + 'static getDerivedStateFromProps. Learn more at: https://reactjs.org/link/derived-state\n' + '\nPlease update the following components: %s', _sortedNames);
- }
- if (UNSAFE_componentWillUpdateUniqueNames.size > 0) {
- var _sortedNames2 = setToSortedString(UNSAFE_componentWillUpdateUniqueNames);
- error('Using UNSAFE_componentWillUpdate in strict mode is not recommended ' + 'and may indicate bugs in your code. ' + 'See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n' + '* Move data fetching code or side effects to componentDidUpdate.\n' + '\nPlease update the following components: %s', _sortedNames2);
- }
- if (componentWillMountUniqueNames.size > 0) {
- var _sortedNames3 = setToSortedString(componentWillMountUniqueNames);
- warn('componentWillMount has been renamed, and is not recommended for use. ' + 'See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n' + '* Move code with side effects to componentDidMount, and set initial state in the constructor.\n' + '* Rename componentWillMount to UNSAFE_componentWillMount to suppress ' + 'this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. ' + 'To rename all deprecated lifecycles to their new names, you can run ' + '`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n' + '\nPlease update the following components: %s', _sortedNames3);
- }
- if (componentWillReceivePropsUniqueNames.size > 0) {
- var _sortedNames4 = setToSortedString(componentWillReceivePropsUniqueNames);
- warn('componentWillReceiveProps has been renamed, and is not recommended for use. ' + 'See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n' + '* Move data fetching code or side effects to componentDidUpdate.\n' + "* If you're updating state whenever props change, refactor your " + 'code to use memoization techniques or move it to ' + 'static getDerivedStateFromProps. Learn more at: https://reactjs.org/link/derived-state\n' + '* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress ' + 'this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. ' + 'To rename all deprecated lifecycles to their new names, you can run ' + '`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n' + '\nPlease update the following components: %s', _sortedNames4);
- }
- if (componentWillUpdateUniqueNames.size > 0) {
- var _sortedNames5 = setToSortedString(componentWillUpdateUniqueNames);
- warn('componentWillUpdate has been renamed, and is not recommended for use. ' + 'See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n' + '* Move data fetching code or side effects to componentDidUpdate.\n' + '* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress ' + 'this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. ' + 'To rename all deprecated lifecycles to their new names, you can run ' + '`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n' + '\nPlease update the following components: %s', _sortedNames5);
- }
- };
- var pendingLegacyContextWarning = new Map(); // Tracks components we have already warned about.
- var didWarnAboutLegacyContext = new Set();
- ReactStrictModeWarnings.recordLegacyContextWarning = function (fiber, instance) {
- var strictRoot = findStrictRoot(fiber);
- if (strictRoot === null) {
- error('Expected to find a StrictMode component in a strict mode tree. ' + 'This error is likely caused by a bug in React. Please file an issue.');
- return;
- } // Dedup strategy: Warn once per component.
- if (didWarnAboutLegacyContext.has(fiber.type)) {
- return;
- }
- var warningsForRoot = pendingLegacyContextWarning.get(strictRoot);
- if (fiber.type.contextTypes != null || fiber.type.childContextTypes != null || instance !== null && typeof instance.getChildContext === 'function') {
- if (warningsForRoot === undefined) {
- warningsForRoot = [];
- pendingLegacyContextWarning.set(strictRoot, warningsForRoot);
- }
- warningsForRoot.push(fiber);
- }
- };
- ReactStrictModeWarnings.flushLegacyContextWarning = function () {
- pendingLegacyContextWarning.forEach(function (fiberArray, strictRoot) {
- if (fiberArray.length === 0) {
- return;
- }
- var firstFiber = fiberArray[0];
- var uniqueNames = new Set();
- fiberArray.forEach(function (fiber) {
- uniqueNames.add(getComponentNameFromFiber(fiber) || 'Component');
- didWarnAboutLegacyContext.add(fiber.type);
- });
- var sortedNames = setToSortedString(uniqueNames);
- try {
- setCurrentFiber(firstFiber);
- error('Legacy context API has been detected within a strict-mode tree.' + '\n\nThe old API will be supported in all 16.x releases, but applications ' + 'using it should migrate to the new version.' + '\n\nPlease update the following components: %s' + '\n\nLearn more about this warning here: https://reactjs.org/link/legacy-context', sortedNames);
- } finally {
- resetCurrentFiber();
- }
- });
- };
- ReactStrictModeWarnings.discardPendingWarnings = function () {
- pendingComponentWillMountWarnings = [];
- pendingUNSAFE_ComponentWillMountWarnings = [];
- pendingComponentWillReceivePropsWarnings = [];
- pendingUNSAFE_ComponentWillReceivePropsWarnings = [];
- pendingComponentWillUpdateWarnings = [];
- pendingUNSAFE_ComponentWillUpdateWarnings = [];
- pendingLegacyContextWarning = new Map();
- };
- }
- function resolveDefaultProps(Component, baseProps) {
- if (Component && Component.defaultProps) {
- // Resolve default props. Taken from ReactElement
- var props = assign({}, baseProps);
- var defaultProps = Component.defaultProps;
- for (var propName in defaultProps) {
- if (props[propName] === undefined) {
- props[propName] = defaultProps[propName];
- }
- }
- return props;
- }
- return baseProps;
- }
- var valueCursor = createCursor(null);
- var rendererSigil;
- {
- // Use this to detect multiple renderers using the same context
- rendererSigil = {};
- }
- var currentlyRenderingFiber = null;
- var lastContextDependency = null;
- var lastFullyObservedContext = null;
- var isDisallowedContextReadInDEV = false;
- function resetContextDependencies() {
- // This is called right before React yields execution, to ensure `readContext`
- // cannot be called outside the render phase.
- currentlyRenderingFiber = null;
- lastContextDependency = null;
- lastFullyObservedContext = null;
- {
- isDisallowedContextReadInDEV = false;
- }
- }
- function enterDisallowedContextReadInDEV() {
- {
- isDisallowedContextReadInDEV = true;
- }
- }
- function exitDisallowedContextReadInDEV() {
- {
- isDisallowedContextReadInDEV = false;
- }
- }
- function pushProvider(providerFiber, context, nextValue) {
- {
- push(valueCursor, context._currentValue, providerFiber);
- context._currentValue = nextValue;
- {
- if (context._currentRenderer !== undefined && context._currentRenderer !== null && context._currentRenderer !== rendererSigil) {
- error('Detected multiple renderers concurrently rendering the ' + 'same context provider. This is currently unsupported.');
- }
- context._currentRenderer = rendererSigil;
- }
- }
- }
- function popProvider(context, providerFiber) {
- var currentValue = valueCursor.current;
- pop(valueCursor, providerFiber);
- {
- {
- context._currentValue = currentValue;
- }
- }
- }
- function scheduleContextWorkOnParentPath(parent, renderLanes, propagationRoot) {
- // Update the child lanes of all the ancestors, including the alternates.
- var node = parent;
- while (node !== null) {
- var alternate = node.alternate;
- if (!isSubsetOfLanes(node.childLanes, renderLanes)) {
- node.childLanes = mergeLanes(node.childLanes, renderLanes);
- if (alternate !== null) {
- alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes);
- }
- } else if (alternate !== null && !isSubsetOfLanes(alternate.childLanes, renderLanes)) {
- alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes);
- }
- if (node === propagationRoot) {
- break;
- }
- node = node.return;
- }
- {
- if (node !== propagationRoot) {
- error('Expected to find the propagation root when scheduling context work. ' + 'This error is likely caused by a bug in React. Please file an issue.');
- }
- }
- }
- function propagateContextChange(workInProgress, context, renderLanes) {
- {
- propagateContextChange_eager(workInProgress, context, renderLanes);
- }
- }
- function propagateContextChange_eager(workInProgress, context, renderLanes) {
- var fiber = workInProgress.child;
- if (fiber !== null) {
- // Set the return pointer of the child to the work-in-progress fiber.
- fiber.return = workInProgress;
- }
- while (fiber !== null) {
- var nextFiber = void 0; // Visit this fiber.
- var list = fiber.dependencies;
- if (list !== null) {
- nextFiber = fiber.child;
- var dependency = list.firstContext;
- while (dependency !== null) {
- // Check if the context matches.
- if (dependency.context === context) {
- // Match! Schedule an update on this fiber.
- if (fiber.tag === ClassComponent) {
- // Schedule a force update on the work-in-progress.
- var lane = pickArbitraryLane(renderLanes);
- var update = createUpdate(NoTimestamp, lane);
- update.tag = ForceUpdate; // TODO: Because we don't have a work-in-progress, this will add the
- // update to the current fiber, too, which means it will persist even if
- // this render is thrown away. Since it's a race condition, not sure it's
- // worth fixing.
- // Inlined `enqueueUpdate` to remove interleaved update check
- var updateQueue = fiber.updateQueue;
- if (updateQueue === null); else {
- var sharedQueue = updateQueue.shared;
- var pending = sharedQueue.pending;
- if (pending === null) {
- // This is the first update. Create a circular list.
- update.next = update;
- } else {
- update.next = pending.next;
- pending.next = update;
- }
- sharedQueue.pending = update;
- }
- }
- fiber.lanes = mergeLanes(fiber.lanes, renderLanes);
- var alternate = fiber.alternate;
- if (alternate !== null) {
- alternate.lanes = mergeLanes(alternate.lanes, renderLanes);
- }
- scheduleContextWorkOnParentPath(fiber.return, renderLanes, workInProgress); // Mark the updated lanes on the list, too.
- list.lanes = mergeLanes(list.lanes, renderLanes); // Since we already found a match, we can stop traversing the
- // dependency list.
- break;
- }
- dependency = dependency.next;
- }
- } else if (fiber.tag === ContextProvider) {
- // Don't scan deeper if this is a matching provider
- nextFiber = fiber.type === workInProgress.type ? null : fiber.child;
- } else if (fiber.tag === DehydratedFragment) {
- // If a dehydrated suspense boundary is in this subtree, we don't know
- // if it will have any context consumers in it. The best we can do is
- // mark it as having updates.
- var parentSuspense = fiber.return;
- if (parentSuspense === null) {
- throw new Error('We just came from a parent so we must have had a parent. This is a bug in React.');
- }
- parentSuspense.lanes = mergeLanes(parentSuspense.lanes, renderLanes);
- var _alternate = parentSuspense.alternate;
- if (_alternate !== null) {
- _alternate.lanes = mergeLanes(_alternate.lanes, renderLanes);
- } // This is intentionally passing this fiber as the parent
- // because we want to schedule this fiber as having work
- // on its children. We'll use the childLanes on
- // this fiber to indicate that a context has changed.
- scheduleContextWorkOnParentPath(parentSuspense, renderLanes, workInProgress);
- nextFiber = fiber.sibling;
- } else {
- // Traverse down.
- nextFiber = fiber.child;
- }
- if (nextFiber !== null) {
- // Set the return pointer of the child to the work-in-progress fiber.
- nextFiber.return = fiber;
- } else {
- // No child. Traverse to next sibling.
- nextFiber = fiber;
- while (nextFiber !== null) {
- if (nextFiber === workInProgress) {
- // We're back to the root of this subtree. Exit.
- nextFiber = null;
- break;
- }
- var sibling = nextFiber.sibling;
- if (sibling !== null) {
- // Set the return pointer of the sibling to the work-in-progress fiber.
- sibling.return = nextFiber.return;
- nextFiber = sibling;
- break;
- } // No more siblings. Traverse up.
- nextFiber = nextFiber.return;
- }
- }
- fiber = nextFiber;
- }
- }
- function prepareToReadContext(workInProgress, renderLanes) {
- currentlyRenderingFiber = workInProgress;
- lastContextDependency = null;
- lastFullyObservedContext = null;
- var dependencies = workInProgress.dependencies;
- if (dependencies !== null) {
- {
- var firstContext = dependencies.firstContext;
- if (firstContext !== null) {
- if (includesSomeLane(dependencies.lanes, renderLanes)) {
- // Context list has a pending update. Mark that this fiber performed work.
- markWorkInProgressReceivedUpdate();
- } // Reset the work-in-progress list
- dependencies.firstContext = null;
- }
- }
- }
- }
- function readContext(context) {
- {
- // This warning would fire if you read context inside a Hook like useMemo.
- // Unlike the class check below, it's not enforced in production for perf.
- if (isDisallowedContextReadInDEV) {
- error('Context can only be read while React is rendering. ' + 'In classes, you can read it in the render method or getDerivedStateFromProps. ' + 'In function components, you can read it directly in the function body, but not ' + 'inside Hooks like useReducer() or useMemo().');
- }
- }
- var value = context._currentValue;
- if (lastFullyObservedContext === context); else {
- var contextItem = {
- context: context,
- memoizedValue: value,
- next: null
- };
- if (lastContextDependency === null) {
- if (currentlyRenderingFiber === null) {
- throw new Error('Context can only be read while React is rendering. ' + 'In classes, you can read it in the render method or getDerivedStateFromProps. ' + 'In function components, you can read it directly in the function body, but not ' + 'inside Hooks like useReducer() or useMemo().');
- } // This is the first dependency for this component. Create a new list.
- lastContextDependency = contextItem;
- currentlyRenderingFiber.dependencies = {
- lanes: NoLanes,
- firstContext: contextItem
- };
- } else {
- // Append a new context item.
- lastContextDependency = lastContextDependency.next = contextItem;
- }
- }
- return value;
- }
- // render. When this render exits, either because it finishes or because it is
- // interrupted, the interleaved updates will be transferred onto the main part
- // of the queue.
- var concurrentQueues = null;
- function pushConcurrentUpdateQueue(queue) {
- if (concurrentQueues === null) {
- concurrentQueues = [queue];
- } else {
- concurrentQueues.push(queue);
- }
- }
- function finishQueueingConcurrentUpdates() {
- // Transfer the interleaved updates onto the main queue. Each queue has a
- // `pending` field and an `interleaved` field. When they are not null, they
- // point to the last node in a circular linked list. We need to append the
- // interleaved list to the end of the pending list by joining them into a
- // single, circular list.
- if (concurrentQueues !== null) {
- for (var i = 0; i < concurrentQueues.length; i++) {
- var queue = concurrentQueues[i];
- var lastInterleavedUpdate = queue.interleaved;
- if (lastInterleavedUpdate !== null) {
- queue.interleaved = null;
- var firstInterleavedUpdate = lastInterleavedUpdate.next;
- var lastPendingUpdate = queue.pending;
- if (lastPendingUpdate !== null) {
- var firstPendingUpdate = lastPendingUpdate.next;
- lastPendingUpdate.next = firstInterleavedUpdate;
- lastInterleavedUpdate.next = firstPendingUpdate;
- }
- queue.pending = lastInterleavedUpdate;
- }
- }
- concurrentQueues = null;
- }
- }
- function enqueueConcurrentHookUpdate(fiber, queue, update, lane) {
- var interleaved = queue.interleaved;
- if (interleaved === null) {
- // This is the first update. Create a circular list.
- update.next = update; // At the end of the current render, this queue's interleaved updates will
- // be transferred to the pending queue.
- pushConcurrentUpdateQueue(queue);
- } else {
- update.next = interleaved.next;
- interleaved.next = update;
- }
- queue.interleaved = update;
- return markUpdateLaneFromFiberToRoot(fiber, lane);
- }
- function enqueueConcurrentHookUpdateAndEagerlyBailout(fiber, queue, update, lane) {
- var interleaved = queue.interleaved;
- if (interleaved === null) {
- // This is the first update. Create a circular list.
- update.next = update; // At the end of the current render, this queue's interleaved updates will
- // be transferred to the pending queue.
- pushConcurrentUpdateQueue(queue);
- } else {
- update.next = interleaved.next;
- interleaved.next = update;
- }
- queue.interleaved = update;
- }
- function enqueueConcurrentClassUpdate(fiber, queue, update, lane) {
- var interleaved = queue.interleaved;
- if (interleaved === null) {
- // This is the first update. Create a circular list.
- update.next = update; // At the end of the current render, this queue's interleaved updates will
- // be transferred to the pending queue.
- pushConcurrentUpdateQueue(queue);
- } else {
- update.next = interleaved.next;
- interleaved.next = update;
- }
- queue.interleaved = update;
- return markUpdateLaneFromFiberToRoot(fiber, lane);
- }
- function enqueueConcurrentRenderForLane(fiber, lane) {
- return markUpdateLaneFromFiberToRoot(fiber, lane);
- } // Calling this function outside this module should only be done for backwards
- // compatibility and should always be accompanied by a warning.
- var unsafe_markUpdateLaneFromFiberToRoot = markUpdateLaneFromFiberToRoot;
- function markUpdateLaneFromFiberToRoot(sourceFiber, lane) {
- // Update the source fiber's lanes
- sourceFiber.lanes = mergeLanes(sourceFiber.lanes, lane);
- var alternate = sourceFiber.alternate;
- if (alternate !== null) {
- alternate.lanes = mergeLanes(alternate.lanes, lane);
- }
- {
- if (alternate === null && (sourceFiber.flags & (Placement | Hydrating)) !== NoFlags) {
- warnAboutUpdateOnNotYetMountedFiberInDEV(sourceFiber);
- }
- } // Walk the parent path to the root and update the child lanes.
- var node = sourceFiber;
- var parent = sourceFiber.return;
- while (parent !== null) {
- parent.childLanes = mergeLanes(parent.childLanes, lane);
- alternate = parent.alternate;
- if (alternate !== null) {
- alternate.childLanes = mergeLanes(alternate.childLanes, lane);
- } else {
- {
- if ((parent.flags & (Placement | Hydrating)) !== NoFlags) {
- warnAboutUpdateOnNotYetMountedFiberInDEV(sourceFiber);
- }
- }
- }
- node = parent;
- parent = parent.return;
- }
- if (node.tag === HostRoot) {
- var root = node.stateNode;
- return root;
- } else {
- return null;
- }
- }
- var UpdateState = 0;
- var ReplaceState = 1;
- var ForceUpdate = 2;
- var CaptureUpdate = 3; // Global state that is reset at the beginning of calling `processUpdateQueue`.
- // It should only be read right after calling `processUpdateQueue`, via
- // `checkHasForceUpdateAfterProcessing`.
- var hasForceUpdate = false;
- var didWarnUpdateInsideUpdate;
- var currentlyProcessingQueue;
- {
- didWarnUpdateInsideUpdate = false;
- currentlyProcessingQueue = null;
- }
- function initializeUpdateQueue(fiber) {
- var queue = {
- baseState: fiber.memoizedState,
- firstBaseUpdate: null,
- lastBaseUpdate: null,
- shared: {
- pending: null,
- interleaved: null,
- lanes: NoLanes
- },
- effects: null
- };
- fiber.updateQueue = queue;
- }
- function cloneUpdateQueue(current, workInProgress) {
- // Clone the update queue from current. Unless it's already a clone.
- var queue = workInProgress.updateQueue;
- var currentQueue = current.updateQueue;
- if (queue === currentQueue) {
- var clone = {
- baseState: currentQueue.baseState,
- firstBaseUpdate: currentQueue.firstBaseUpdate,
- lastBaseUpdate: currentQueue.lastBaseUpdate,
- shared: currentQueue.shared,
- effects: currentQueue.effects
- };
- workInProgress.updateQueue = clone;
- }
- }
- function createUpdate(eventTime, lane) {
- var update = {
- eventTime: eventTime,
- lane: lane,
- tag: UpdateState,
- payload: null,
- callback: null,
- next: null
- };
- return update;
- }
- function enqueueUpdate(fiber, update, lane) {
- var updateQueue = fiber.updateQueue;
- if (updateQueue === null) {
- // Only occurs if the fiber has been unmounted.
- return null;
- }
- var sharedQueue = updateQueue.shared;
- {
- if (currentlyProcessingQueue === sharedQueue && !didWarnUpdateInsideUpdate) {
- error('An update (setState, replaceState, or forceUpdate) was scheduled ' + 'from inside an update function. Update functions should be pure, ' + 'with zero side-effects. Consider using componentDidUpdate or a ' + 'callback.');
- didWarnUpdateInsideUpdate = true;
- }
- }
- if (isUnsafeClassRenderPhaseUpdate()) {
- // This is an unsafe render phase update. Add directly to the update
- // queue so we can process it immediately during the current render.
- var pending = sharedQueue.pending;
- if (pending === null) {
- // This is the first update. Create a circular list.
- update.next = update;
- } else {
- update.next = pending.next;
- pending.next = update;
- }
- sharedQueue.pending = update; // Update the childLanes even though we're most likely already rendering
- // this fiber. This is for backwards compatibility in the case where you
- // update a different component during render phase than the one that is
- // currently renderings (a pattern that is accompanied by a warning).
- return unsafe_markUpdateLaneFromFiberToRoot(fiber, lane);
- } else {
- return enqueueConcurrentClassUpdate(fiber, sharedQueue, update, lane);
- }
- }
- function entangleTransitions(root, fiber, lane) {
- var updateQueue = fiber.updateQueue;
- if (updateQueue === null) {
- // Only occurs if the fiber has been unmounted.
- return;
- }
- var sharedQueue = updateQueue.shared;
- if (isTransitionLane(lane)) {
- var queueLanes = sharedQueue.lanes; // If any entangled lanes are no longer pending on the root, then they must
- // have finished. We can remove them from the shared queue, which represents
- // a superset of the actually pending lanes. In some cases we may entangle
- // more than we need to, but that's OK. In fact it's worse if we *don't*
- // entangle when we should.
- queueLanes = intersectLanes(queueLanes, root.pendingLanes); // Entangle the new transition lane with the other transition lanes.
- var newQueueLanes = mergeLanes(queueLanes, lane);
- sharedQueue.lanes = newQueueLanes; // Even if queue.lanes already include lane, we don't know for certain if
- // the lane finished since the last time we entangled it. So we need to
- // entangle it again, just to be sure.
- markRootEntangled(root, newQueueLanes);
- }
- }
- function enqueueCapturedUpdate(workInProgress, capturedUpdate) {
- // Captured updates are updates that are thrown by a child during the render
- // phase. They should be discarded if the render is aborted. Therefore,
- // we should only put them on the work-in-progress queue, not the current one.
- var queue = workInProgress.updateQueue; // Check if the work-in-progress queue is a clone.
- var current = workInProgress.alternate;
- if (current !== null) {
- var currentQueue = current.updateQueue;
- if (queue === currentQueue) {
- // The work-in-progress queue is the same as current. This happens when
- // we bail out on a parent fiber that then captures an error thrown by
- // a child. Since we want to append the update only to the work-in
- // -progress queue, we need to clone the updates. We usually clone during
- // processUpdateQueue, but that didn't happen in this case because we
- // skipped over the parent when we bailed out.
- var newFirst = null;
- var newLast = null;
- var firstBaseUpdate = queue.firstBaseUpdate;
- if (firstBaseUpdate !== null) {
- // Loop through the updates and clone them.
- var update = firstBaseUpdate;
- do {
- var clone = {
- eventTime: update.eventTime,
- lane: update.lane,
- tag: update.tag,
- payload: update.payload,
- callback: update.callback,
- next: null
- };
- if (newLast === null) {
- newFirst = newLast = clone;
- } else {
- newLast.next = clone;
- newLast = clone;
- }
- update = update.next;
- } while (update !== null); // Append the captured update the end of the cloned list.
- if (newLast === null) {
- newFirst = newLast = capturedUpdate;
- } else {
- newLast.next = capturedUpdate;
- newLast = capturedUpdate;
- }
- } else {
- // There are no base updates.
- newFirst = newLast = capturedUpdate;
- }
- queue = {
- baseState: currentQueue.baseState,
- firstBaseUpdate: newFirst,
- lastBaseUpdate: newLast,
- shared: currentQueue.shared,
- effects: currentQueue.effects
- };
- workInProgress.updateQueue = queue;
- return;
- }
- } // Append the update to the end of the list.
- var lastBaseUpdate = queue.lastBaseUpdate;
- if (lastBaseUpdate === null) {
- queue.firstBaseUpdate = capturedUpdate;
- } else {
- lastBaseUpdate.next = capturedUpdate;
- }
- queue.lastBaseUpdate = capturedUpdate;
- }
- function getStateFromUpdate(workInProgress, queue, update, prevState, nextProps, instance) {
- switch (update.tag) {
- case ReplaceState:
- {
- var payload = update.payload;
- if (typeof payload === 'function') {
- // Updater function
- {
- enterDisallowedContextReadInDEV();
- }
- var nextState = payload.call(instance, prevState, nextProps);
- {
- if (workInProgress.mode & StrictLegacyMode) {
- setIsStrictModeForDevtools(true);
- try {
- payload.call(instance, prevState, nextProps);
- } finally {
- setIsStrictModeForDevtools(false);
- }
- }
- exitDisallowedContextReadInDEV();
- }
- return nextState;
- } // State object
- return payload;
- }
- case CaptureUpdate:
- {
- workInProgress.flags = workInProgress.flags & ~ShouldCapture | DidCapture;
- }
- // Intentional fallthrough
- case UpdateState:
- {
- var _payload = update.payload;
- var partialState;
- if (typeof _payload === 'function') {
- // Updater function
- {
- enterDisallowedContextReadInDEV();
- }
- partialState = _payload.call(instance, prevState, nextProps);
- {
- if (workInProgress.mode & StrictLegacyMode) {
- setIsStrictModeForDevtools(true);
- try {
- _payload.call(instance, prevState, nextProps);
- } finally {
- setIsStrictModeForDevtools(false);
- }
- }
- exitDisallowedContextReadInDEV();
- }
- } else {
- // Partial state object
- partialState = _payload;
- }
- if (partialState === null || partialState === undefined) {
- // Null and undefined are treated as no-ops.
- return prevState;
- } // Merge the partial state and the previous state.
- return assign({}, prevState, partialState);
- }
- case ForceUpdate:
- {
- hasForceUpdate = true;
- return prevState;
- }
- }
- return prevState;
- }
- function processUpdateQueue(workInProgress, props, instance, renderLanes) {
- // This is always non-null on a ClassComponent or HostRoot
- var queue = workInProgress.updateQueue;
- hasForceUpdate = false;
- {
- currentlyProcessingQueue = queue.shared;
- }
- var firstBaseUpdate = queue.firstBaseUpdate;
- var lastBaseUpdate = queue.lastBaseUpdate; // Check if there are pending updates. If so, transfer them to the base queue.
- var pendingQueue = queue.shared.pending;
- if (pendingQueue !== null) {
- queue.shared.pending = null; // The pending queue is circular. Disconnect the pointer between first
- // and last so that it's non-circular.
- var lastPendingUpdate = pendingQueue;
- var firstPendingUpdate = lastPendingUpdate.next;
- lastPendingUpdate.next = null; // Append pending updates to base queue
- if (lastBaseUpdate === null) {
- firstBaseUpdate = firstPendingUpdate;
- } else {
- lastBaseUpdate.next = firstPendingUpdate;
- }
- lastBaseUpdate = lastPendingUpdate; // If there's a current queue, and it's different from the base queue, then
- // we need to transfer the updates to that queue, too. Because the base
- // queue is a singly-linked list with no cycles, we can append to both
- // lists and take advantage of structural sharing.
- // TODO: Pass `current` as argument
- var current = workInProgress.alternate;
- if (current !== null) {
- // This is always non-null on a ClassComponent or HostRoot
- var currentQueue = current.updateQueue;
- var currentLastBaseUpdate = currentQueue.lastBaseUpdate;
- if (currentLastBaseUpdate !== lastBaseUpdate) {
- if (currentLastBaseUpdate === null) {
- currentQueue.firstBaseUpdate = firstPendingUpdate;
- } else {
- currentLastBaseUpdate.next = firstPendingUpdate;
- }
- currentQueue.lastBaseUpdate = lastPendingUpdate;
- }
- }
- } // These values may change as we process the queue.
- if (firstBaseUpdate !== null) {
- // Iterate through the list of updates to compute the result.
- var newState = queue.baseState; // TODO: Don't need to accumulate this. Instead, we can remove renderLanes
- // from the original lanes.
- var newLanes = NoLanes;
- var newBaseState = null;
- var newFirstBaseUpdate = null;
- var newLastBaseUpdate = null;
- var update = firstBaseUpdate;
- do {
- var updateLane = update.lane;
- var updateEventTime = update.eventTime;
- if (!isSubsetOfLanes(renderLanes, updateLane)) {
- // Priority is insufficient. Skip this update. If this is the first
- // skipped update, the previous update/state is the new base
- // update/state.
- var clone = {
- eventTime: updateEventTime,
- lane: updateLane,
- tag: update.tag,
- payload: update.payload,
- callback: update.callback,
- next: null
- };
- if (newLastBaseUpdate === null) {
- newFirstBaseUpdate = newLastBaseUpdate = clone;
- newBaseState = newState;
- } else {
- newLastBaseUpdate = newLastBaseUpdate.next = clone;
- } // Update the remaining priority in the queue.
- newLanes = mergeLanes(newLanes, updateLane);
- } else {
- // This update does have sufficient priority.
- if (newLastBaseUpdate !== null) {
- var _clone = {
- eventTime: updateEventTime,
- // This update is going to be committed so we never want uncommit
- // it. Using NoLane works because 0 is a subset of all bitmasks, so
- // this will never be skipped by the check above.
- lane: NoLane,
- tag: update.tag,
- payload: update.payload,
- callback: update.callback,
- next: null
- };
- newLastBaseUpdate = newLastBaseUpdate.next = _clone;
- } // Process this update.
- newState = getStateFromUpdate(workInProgress, queue, update, newState, props, instance);
- var callback = update.callback;
- if (callback !== null && // If the update was already committed, we should not queue its
- // callback again.
- update.lane !== NoLane) {
- workInProgress.flags |= Callback;
- var effects = queue.effects;
- if (effects === null) {
- queue.effects = [update];
- } else {
- effects.push(update);
- }
- }
- }
- update = update.next;
- if (update === null) {
- pendingQueue = queue.shared.pending;
- if (pendingQueue === null) {
- break;
- } else {
- // An update was scheduled from inside a reducer. Add the new
- // pending updates to the end of the list and keep processing.
- var _lastPendingUpdate = pendingQueue; // Intentionally unsound. Pending updates form a circular list, but we
- // unravel them when transferring them to the base queue.
- var _firstPendingUpdate = _lastPendingUpdate.next;
- _lastPendingUpdate.next = null;
- update = _firstPendingUpdate;
- queue.lastBaseUpdate = _lastPendingUpdate;
- queue.shared.pending = null;
- }
- }
- } while (true);
- if (newLastBaseUpdate === null) {
- newBaseState = newState;
- }
- queue.baseState = newBaseState;
- queue.firstBaseUpdate = newFirstBaseUpdate;
- queue.lastBaseUpdate = newLastBaseUpdate; // Interleaved updates are stored on a separate queue. We aren't going to
- // process them during this render, but we do need to track which lanes
- // are remaining.
- var lastInterleaved = queue.shared.interleaved;
- if (lastInterleaved !== null) {
- var interleaved = lastInterleaved;
- do {
- newLanes = mergeLanes(newLanes, interleaved.lane);
- interleaved = interleaved.next;
- } while (interleaved !== lastInterleaved);
- } else if (firstBaseUpdate === null) {
- // `queue.lanes` is used for entangling transitions. We can set it back to
- // zero once the queue is empty.
- queue.shared.lanes = NoLanes;
- } // Set the remaining expiration time to be whatever is remaining in the queue.
- // This should be fine because the only two other things that contribute to
- // expiration time are props and context. We're already in the middle of the
- // begin phase by the time we start processing the queue, so we've already
- // dealt with the props. Context in components that specify
- // shouldComponentUpdate is tricky; but we'll have to account for
- // that regardless.
- markSkippedUpdateLanes(newLanes);
- workInProgress.lanes = newLanes;
- workInProgress.memoizedState = newState;
- }
- {
- currentlyProcessingQueue = null;
- }
- }
- function callCallback(callback, context) {
- if (typeof callback !== 'function') {
- throw new Error('Invalid argument passed as callback. Expected a function. Instead ' + ("received: " + callback));
- }
- callback.call(context);
- }
- function resetHasForceUpdateBeforeProcessing() {
- hasForceUpdate = false;
- }
- function checkHasForceUpdateAfterProcessing() {
- return hasForceUpdate;
- }
- function commitUpdateQueue(finishedWork, finishedQueue, instance) {
- // Commit the effects
- var effects = finishedQueue.effects;
- finishedQueue.effects = null;
- if (effects !== null) {
- for (var i = 0; i < effects.length; i++) {
- var effect = effects[i];
- var callback = effect.callback;
- if (callback !== null) {
- effect.callback = null;
- callCallback(callback, instance);
- }
- }
- }
- }
- var fakeInternalInstance = {}; // React.Component uses a shared frozen object by default.
- // We'll use it to determine whether we need to initialize legacy refs.
- var emptyRefsObject = new React.Component().refs;
- var didWarnAboutStateAssignmentForComponent;
- var didWarnAboutUninitializedState;
- var didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate;
- var didWarnAboutLegacyLifecyclesAndDerivedState;
- var didWarnAboutUndefinedDerivedState;
- var warnOnUndefinedDerivedState;
- var warnOnInvalidCallback;
- var didWarnAboutDirectlyAssigningPropsToState;
- var didWarnAboutContextTypeAndContextTypes;
- var didWarnAboutInvalidateContextType;
- {
- didWarnAboutStateAssignmentForComponent = new Set();
- didWarnAboutUninitializedState = new Set();
- didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate = new Set();
- didWarnAboutLegacyLifecyclesAndDerivedState = new Set();
- didWarnAboutDirectlyAssigningPropsToState = new Set();
- didWarnAboutUndefinedDerivedState = new Set();
- didWarnAboutContextTypeAndContextTypes = new Set();
- didWarnAboutInvalidateContextType = new Set();
- var didWarnOnInvalidCallback = new Set();
- warnOnInvalidCallback = function (callback, callerName) {
- if (callback === null || typeof callback === 'function') {
- return;
- }
- var key = callerName + '_' + callback;
- if (!didWarnOnInvalidCallback.has(key)) {
- didWarnOnInvalidCallback.add(key);
- error('%s(...): Expected the last optional `callback` argument to be a ' + 'function. Instead received: %s.', callerName, callback);
- }
- };
- warnOnUndefinedDerivedState = function (type, partialState) {
- if (partialState === undefined) {
- var componentName = getComponentNameFromType(type) || 'Component';
- if (!didWarnAboutUndefinedDerivedState.has(componentName)) {
- didWarnAboutUndefinedDerivedState.add(componentName);
- error('%s.getDerivedStateFromProps(): A valid state object (or null) must be returned. ' + 'You have returned undefined.', componentName);
- }
- }
- }; // This is so gross but it's at least non-critical and can be removed if
- // it causes problems. This is meant to give a nicer error message for
- // ReactDOM15.unstable_renderSubtreeIntoContainer(reactDOM16Component,
- // ...)) which otherwise throws a "_processChildContext is not a function"
- // exception.
- Object.defineProperty(fakeInternalInstance, '_processChildContext', {
- enumerable: false,
- value: function () {
- throw new Error('_processChildContext is not available in React 16+. This likely ' + 'means you have multiple copies of React and are attempting to nest ' + 'a React 15 tree inside a React 16 tree using ' + "unstable_renderSubtreeIntoContainer, which isn't supported. Try " + 'to make sure you have only one copy of React (and ideally, switch ' + 'to ReactDOM.createPortal).');
- }
- });
- Object.freeze(fakeInternalInstance);
- }
- function applyDerivedStateFromProps(workInProgress, ctor, getDerivedStateFromProps, nextProps) {
- var prevState = workInProgress.memoizedState;
- var partialState = getDerivedStateFromProps(nextProps, prevState);
- {
- if (workInProgress.mode & StrictLegacyMode) {
- setIsStrictModeForDevtools(true);
- try {
- // Invoke the function an extra time to help detect side-effects.
- partialState = getDerivedStateFromProps(nextProps, prevState);
- } finally {
- setIsStrictModeForDevtools(false);
- }
- }
- warnOnUndefinedDerivedState(ctor, partialState);
- } // Merge the partial state and the previous state.
- var memoizedState = partialState === null || partialState === undefined ? prevState : assign({}, prevState, partialState);
- workInProgress.memoizedState = memoizedState; // Once the update queue is empty, persist the derived state onto the
- // base state.
- if (workInProgress.lanes === NoLanes) {
- // Queue is always non-null for classes
- var updateQueue = workInProgress.updateQueue;
- updateQueue.baseState = memoizedState;
- }
- }
- var classComponentUpdater = {
- isMounted: isMounted,
- enqueueSetState: function (inst, payload, callback) {
- var fiber = get(inst);
- var eventTime = requestEventTime();
- var lane = requestUpdateLane(fiber);
- var update = createUpdate(eventTime, lane);
- update.payload = payload;
- if (callback !== undefined && callback !== null) {
- {
- warnOnInvalidCallback(callback, 'setState');
- }
- update.callback = callback;
- }
- var root = enqueueUpdate(fiber, update, lane);
- if (root !== null) {
- scheduleUpdateOnFiber(root, fiber, lane, eventTime);
- entangleTransitions(root, fiber, lane);
- }
- {
- markStateUpdateScheduled(fiber, lane);
- }
- },
- enqueueReplaceState: function (inst, payload, callback) {
- var fiber = get(inst);
- var eventTime = requestEventTime();
- var lane = requestUpdateLane(fiber);
- var update = createUpdate(eventTime, lane);
- update.tag = ReplaceState;
- update.payload = payload;
- if (callback !== undefined && callback !== null) {
- {
- warnOnInvalidCallback(callback, 'replaceState');
- }
- update.callback = callback;
- }
- var root = enqueueUpdate(fiber, update, lane);
- if (root !== null) {
- scheduleUpdateOnFiber(root, fiber, lane, eventTime);
- entangleTransitions(root, fiber, lane);
- }
- {
- markStateUpdateScheduled(fiber, lane);
- }
- },
- enqueueForceUpdate: function (inst, callback) {
- var fiber = get(inst);
- var eventTime = requestEventTime();
- var lane = requestUpdateLane(fiber);
- var update = createUpdate(eventTime, lane);
- update.tag = ForceUpdate;
- if (callback !== undefined && callback !== null) {
- {
- warnOnInvalidCallback(callback, 'forceUpdate');
- }
- update.callback = callback;
- }
- var root = enqueueUpdate(fiber, update, lane);
- if (root !== null) {
- scheduleUpdateOnFiber(root, fiber, lane, eventTime);
- entangleTransitions(root, fiber, lane);
- }
- {
- markForceUpdateScheduled(fiber, lane);
- }
- }
- };
- function checkShouldComponentUpdate(workInProgress, ctor, oldProps, newProps, oldState, newState, nextContext) {
- var instance = workInProgress.stateNode;
- if (typeof instance.shouldComponentUpdate === 'function') {
- var shouldUpdate = instance.shouldComponentUpdate(newProps, newState, nextContext);
- {
- if (workInProgress.mode & StrictLegacyMode) {
- setIsStrictModeForDevtools(true);
- try {
- // Invoke the function an extra time to help detect side-effects.
- shouldUpdate = instance.shouldComponentUpdate(newProps, newState, nextContext);
- } finally {
- setIsStrictModeForDevtools(false);
- }
- }
- if (shouldUpdate === undefined) {
- error('%s.shouldComponentUpdate(): Returned undefined instead of a ' + 'boolean value. Make sure to return true or false.', getComponentNameFromType(ctor) || 'Component');
- }
- }
- return shouldUpdate;
- }
- if (ctor.prototype && ctor.prototype.isPureReactComponent) {
- return !shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState);
- }
- return true;
- }
- function checkClassInstance(workInProgress, ctor, newProps) {
- var instance = workInProgress.stateNode;
- {
- var name = getComponentNameFromType(ctor) || 'Component';
- var renderPresent = instance.render;
- if (!renderPresent) {
- if (ctor.prototype && typeof ctor.prototype.render === 'function') {
- error('%s(...): No `render` method found on the returned component ' + 'instance: did you accidentally return an object from the constructor?', name);
- } else {
- error('%s(...): No `render` method found on the returned component ' + 'instance: you may have forgotten to define `render`.', name);
- }
- }
- if (instance.getInitialState && !instance.getInitialState.isReactClassApproved && !instance.state) {
- error('getInitialState was defined on %s, a plain JavaScript class. ' + 'This is only supported for classes created using React.createClass. ' + 'Did you mean to define a state property instead?', name);
- }
- if (instance.getDefaultProps && !instance.getDefaultProps.isReactClassApproved) {
- error('getDefaultProps was defined on %s, a plain JavaScript class. ' + 'This is only supported for classes created using React.createClass. ' + 'Use a static property to define defaultProps instead.', name);
- }
- if (instance.propTypes) {
- error('propTypes was defined as an instance property on %s. Use a static ' + 'property to define propTypes instead.', name);
- }
- if (instance.contextType) {
- error('contextType was defined as an instance property on %s. Use a static ' + 'property to define contextType instead.', name);
- }
- {
- if (instance.contextTypes) {
- error('contextTypes was defined as an instance property on %s. Use a static ' + 'property to define contextTypes instead.', name);
- }
- if (ctor.contextType && ctor.contextTypes && !didWarnAboutContextTypeAndContextTypes.has(ctor)) {
- didWarnAboutContextTypeAndContextTypes.add(ctor);
- error('%s declares both contextTypes and contextType static properties. ' + 'The legacy contextTypes property will be ignored.', name);
- }
- }
- if (typeof instance.componentShouldUpdate === 'function') {
- error('%s has a method called ' + 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' + 'The name is phrased as a question because the function is ' + 'expected to return a value.', name);
- }
- if (ctor.prototype && ctor.prototype.isPureReactComponent && typeof instance.shouldComponentUpdate !== 'undefined') {
- error('%s has a method called shouldComponentUpdate(). ' + 'shouldComponentUpdate should not be used when extending React.PureComponent. ' + 'Please extend React.Component if shouldComponentUpdate is used.', getComponentNameFromType(ctor) || 'A pure component');
- }
- if (typeof instance.componentDidUnmount === 'function') {
- error('%s has a method called ' + 'componentDidUnmount(). But there is no such lifecycle method. ' + 'Did you mean componentWillUnmount()?', name);
- }
- if (typeof instance.componentDidReceiveProps === 'function') {
- error('%s has a method called ' + 'componentDidReceiveProps(). But there is no such lifecycle method. ' + 'If you meant to update the state in response to changing props, ' + 'use componentWillReceiveProps(). If you meant to fetch data or ' + 'run side-effects or mutations after React has updated the UI, use componentDidUpdate().', name);
- }
- if (typeof instance.componentWillRecieveProps === 'function') {
- error('%s has a method called ' + 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?', name);
- }
- if (typeof instance.UNSAFE_componentWillRecieveProps === 'function') {
- error('%s has a method called ' + 'UNSAFE_componentWillRecieveProps(). Did you mean UNSAFE_componentWillReceiveProps()?', name);
- }
- var hasMutatedProps = instance.props !== newProps;
- if (instance.props !== undefined && hasMutatedProps) {
- error('%s(...): When calling super() in `%s`, make sure to pass ' + "up the same props that your component's constructor was passed.", name, name);
- }
- if (instance.defaultProps) {
- error('Setting defaultProps as an instance property on %s is not supported and will be ignored.' + ' Instead, define defaultProps as a static property on %s.', name, name);
- }
- if (typeof instance.getSnapshotBeforeUpdate === 'function' && typeof instance.componentDidUpdate !== 'function' && !didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.has(ctor)) {
- didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.add(ctor);
- error('%s: getSnapshotBeforeUpdate() should be used with componentDidUpdate(). ' + 'This component defines getSnapshotBeforeUpdate() only.', getComponentNameFromType(ctor));
- }
- if (typeof instance.getDerivedStateFromProps === 'function') {
- error('%s: getDerivedStateFromProps() is defined as an instance method ' + 'and will be ignored. Instead, declare it as a static method.', name);
- }
- if (typeof instance.getDerivedStateFromError === 'function') {
- error('%s: getDerivedStateFromError() is defined as an instance method ' + 'and will be ignored. Instead, declare it as a static method.', name);
- }
- if (typeof ctor.getSnapshotBeforeUpdate === 'function') {
- error('%s: getSnapshotBeforeUpdate() is defined as a static method ' + 'and will be ignored. Instead, declare it as an instance method.', name);
- }
- var _state = instance.state;
- if (_state && (typeof _state !== 'object' || isArray(_state))) {
- error('%s.state: must be set to an object or null', name);
- }
- if (typeof instance.getChildContext === 'function' && typeof ctor.childContextTypes !== 'object') {
- error('%s.getChildContext(): childContextTypes must be defined in order to ' + 'use getChildContext().', name);
- }
- }
- }
- function adoptClassInstance(workInProgress, instance) {
- instance.updater = classComponentUpdater;
- workInProgress.stateNode = instance; // The instance needs access to the fiber so that it can schedule updates
- set(instance, workInProgress);
- {
- instance._reactInternalInstance = fakeInternalInstance;
- }
- }
- function constructClassInstance(workInProgress, ctor, props) {
- var isLegacyContextConsumer = false;
- var unmaskedContext = emptyContextObject;
- var context = emptyContextObject;
- var contextType = ctor.contextType;
- {
- if ('contextType' in ctor) {
- var isValid = // Allow null for conditional declaration
- contextType === null || contextType !== undefined && contextType.$$typeof === REACT_CONTEXT_TYPE && contextType._context === undefined; // Not a <Context.Consumer>
- if (!isValid && !didWarnAboutInvalidateContextType.has(ctor)) {
- didWarnAboutInvalidateContextType.add(ctor);
- var addendum = '';
- if (contextType === undefined) {
- addendum = ' However, it is set to undefined. ' + 'This can be caused by a typo or by mixing up named and default imports. ' + 'This can also happen due to a circular dependency, so ' + 'try moving the createContext() call to a separate file.';
- } else if (typeof contextType !== 'object') {
- addendum = ' However, it is set to a ' + typeof contextType + '.';
- } else if (contextType.$$typeof === REACT_PROVIDER_TYPE) {
- addendum = ' Did you accidentally pass the Context.Provider instead?';
- } else if (contextType._context !== undefined) {
- // <Context.Consumer>
- addendum = ' Did you accidentally pass the Context.Consumer instead?';
- } else {
- addendum = ' However, it is set to an object with keys {' + Object.keys(contextType).join(', ') + '}.';
- }
- error('%s defines an invalid contextType. ' + 'contextType should point to the Context object returned by React.createContext().%s', getComponentNameFromType(ctor) || 'Component', addendum);
- }
- }
- }
- if (typeof contextType === 'object' && contextType !== null) {
- context = readContext(contextType);
- } else {
- unmaskedContext = getUnmaskedContext(workInProgress, ctor, true);
- var contextTypes = ctor.contextTypes;
- isLegacyContextConsumer = contextTypes !== null && contextTypes !== undefined;
- context = isLegacyContextConsumer ? getMaskedContext(workInProgress, unmaskedContext) : emptyContextObject;
- }
- var instance = new ctor(props, context); // Instantiate twice to help detect side-effects.
- {
- if (workInProgress.mode & StrictLegacyMode) {
- setIsStrictModeForDevtools(true);
- try {
- instance = new ctor(props, context); // eslint-disable-line no-new
- } finally {
- setIsStrictModeForDevtools(false);
- }
- }
- }
- var state = workInProgress.memoizedState = instance.state !== null && instance.state !== undefined ? instance.state : null;
- adoptClassInstance(workInProgress, instance);
- {
- if (typeof ctor.getDerivedStateFromProps === 'function' && state === null) {
- var componentName = getComponentNameFromType(ctor) || 'Component';
- if (!didWarnAboutUninitializedState.has(componentName)) {
- didWarnAboutUninitializedState.add(componentName);
- error('`%s` uses `getDerivedStateFromProps` but its initial state is ' + '%s. This is not recommended. Instead, define the initial state by ' + 'assigning an object to `this.state` in the constructor of `%s`. ' + 'This ensures that `getDerivedStateFromProps` arguments have a consistent shape.', componentName, instance.state === null ? 'null' : 'undefined', componentName);
- }
- } // If new component APIs are defined, "unsafe" lifecycles won't be called.
- // Warn about these lifecycles if they are present.
- // Don't warn about react-lifecycles-compat polyfilled methods though.
- if (typeof ctor.getDerivedStateFromProps === 'function' || typeof instance.getSnapshotBeforeUpdate === 'function') {
- var foundWillMountName = null;
- var foundWillReceivePropsName = null;
- var foundWillUpdateName = null;
- if (typeof instance.componentWillMount === 'function' && instance.componentWillMount.__suppressDeprecationWarning !== true) {
- foundWillMountName = 'componentWillMount';
- } else if (typeof instance.UNSAFE_componentWillMount === 'function') {
- foundWillMountName = 'UNSAFE_componentWillMount';
- }
- if (typeof instance.componentWillReceiveProps === 'function' && instance.componentWillReceiveProps.__suppressDeprecationWarning !== true) {
- foundWillReceivePropsName = 'componentWillReceiveProps';
- } else if (typeof instance.UNSAFE_componentWillReceiveProps === 'function') {
- foundWillReceivePropsName = 'UNSAFE_componentWillReceiveProps';
- }
- if (typeof instance.componentWillUpdate === 'function' && instance.componentWillUpdate.__suppressDeprecationWarning !== true) {
- foundWillUpdateName = 'componentWillUpdate';
- } else if (typeof instance.UNSAFE_componentWillUpdate === 'function') {
- foundWillUpdateName = 'UNSAFE_componentWillUpdate';
- }
- if (foundWillMountName !== null || foundWillReceivePropsName !== null || foundWillUpdateName !== null) {
- var _componentName = getComponentNameFromType(ctor) || 'Component';
- var newApiName = typeof ctor.getDerivedStateFromProps === 'function' ? 'getDerivedStateFromProps()' : 'getSnapshotBeforeUpdate()';
- if (!didWarnAboutLegacyLifecyclesAndDerivedState.has(_componentName)) {
- didWarnAboutLegacyLifecyclesAndDerivedState.add(_componentName);
- error('Unsafe legacy lifecycles will not be called for components using new component APIs.\n\n' + '%s uses %s but also contains the following legacy lifecycles:%s%s%s\n\n' + 'The above lifecycles should be removed. Learn more about this warning here:\n' + 'https://reactjs.org/link/unsafe-component-lifecycles', _componentName, newApiName, foundWillMountName !== null ? "\n " + foundWillMountName : '', foundWillReceivePropsName !== null ? "\n " + foundWillReceivePropsName : '', foundWillUpdateName !== null ? "\n " + foundWillUpdateName : '');
- }
- }
- }
- } // Cache unmasked context so we can avoid recreating masked context unless necessary.
- // ReactFiberContext usually updates this cache but can't for newly-created instances.
- if (isLegacyContextConsumer) {
- cacheContext(workInProgress, unmaskedContext, context);
- }
- return instance;
- }
- function callComponentWillMount(workInProgress, instance) {
- var oldState = instance.state;
- if (typeof instance.componentWillMount === 'function') {
- instance.componentWillMount();
- }
- if (typeof instance.UNSAFE_componentWillMount === 'function') {
- instance.UNSAFE_componentWillMount();
- }
- if (oldState !== instance.state) {
- {
- error('%s.componentWillMount(): Assigning directly to this.state is ' + "deprecated (except inside a component's " + 'constructor). Use setState instead.', getComponentNameFromFiber(workInProgress) || 'Component');
- }
- classComponentUpdater.enqueueReplaceState(instance, instance.state, null);
- }
- }
- function callComponentWillReceiveProps(workInProgress, instance, newProps, nextContext) {
- var oldState = instance.state;
- if (typeof instance.componentWillReceiveProps === 'function') {
- instance.componentWillReceiveProps(newProps, nextContext);
- }
- if (typeof instance.UNSAFE_componentWillReceiveProps === 'function') {
- instance.UNSAFE_componentWillReceiveProps(newProps, nextContext);
- }
- if (instance.state !== oldState) {
- {
- var componentName = getComponentNameFromFiber(workInProgress) || 'Component';
- if (!didWarnAboutStateAssignmentForComponent.has(componentName)) {
- didWarnAboutStateAssignmentForComponent.add(componentName);
- error('%s.componentWillReceiveProps(): Assigning directly to ' + "this.state is deprecated (except inside a component's " + 'constructor). Use setState instead.', componentName);
- }
- }
- classComponentUpdater.enqueueReplaceState(instance, instance.state, null);
- }
- } // Invokes the mount life-cycles on a previously never rendered instance.
- function mountClassInstance(workInProgress, ctor, newProps, renderLanes) {
- {
- checkClassInstance(workInProgress, ctor, newProps);
- }
- var instance = workInProgress.stateNode;
- instance.props = newProps;
- instance.state = workInProgress.memoizedState;
- instance.refs = emptyRefsObject;
- initializeUpdateQueue(workInProgress);
- var contextType = ctor.contextType;
- if (typeof contextType === 'object' && contextType !== null) {
- instance.context = readContext(contextType);
- } else {
- var unmaskedContext = getUnmaskedContext(workInProgress, ctor, true);
- instance.context = getMaskedContext(workInProgress, unmaskedContext);
- }
- {
- if (instance.state === newProps) {
- var componentName = getComponentNameFromType(ctor) || 'Component';
- if (!didWarnAboutDirectlyAssigningPropsToState.has(componentName)) {
- didWarnAboutDirectlyAssigningPropsToState.add(componentName);
- error('%s: It is not recommended to assign props directly to state ' + "because updates to props won't be reflected in state. " + 'In most cases, it is better to use props directly.', componentName);
- }
- }
- if (workInProgress.mode & StrictLegacyMode) {
- ReactStrictModeWarnings.recordLegacyContextWarning(workInProgress, instance);
- }
- {
- ReactStrictModeWarnings.recordUnsafeLifecycleWarnings(workInProgress, instance);
- }
- }
- instance.state = workInProgress.memoizedState;
- var getDerivedStateFromProps = ctor.getDerivedStateFromProps;
- if (typeof getDerivedStateFromProps === 'function') {
- applyDerivedStateFromProps(workInProgress, ctor, getDerivedStateFromProps, newProps);
- instance.state = workInProgress.memoizedState;
- } // In order to support react-lifecycles-compat polyfilled components,
- // Unsafe lifecycles should not be invoked for components using the new APIs.
- if (typeof ctor.getDerivedStateFromProps !== 'function' && typeof instance.getSnapshotBeforeUpdate !== 'function' && (typeof instance.UNSAFE_componentWillMount === 'function' || typeof instance.componentWillMount === 'function')) {
- callComponentWillMount(workInProgress, instance); // If we had additional state updates during this life-cycle, let's
- // process them now.
- processUpdateQueue(workInProgress, newProps, instance, renderLanes);
- instance.state = workInProgress.memoizedState;
- }
- if (typeof instance.componentDidMount === 'function') {
- var fiberFlags = Update;
- {
- fiberFlags |= LayoutStatic;
- }
- if ((workInProgress.mode & StrictEffectsMode) !== NoMode) {
- fiberFlags |= MountLayoutDev;
- }
- workInProgress.flags |= fiberFlags;
- }
- }
- function resumeMountClassInstance(workInProgress, ctor, newProps, renderLanes) {
- var instance = workInProgress.stateNode;
- var oldProps = workInProgress.memoizedProps;
- instance.props = oldProps;
- var oldContext = instance.context;
- var contextType = ctor.contextType;
- var nextContext = emptyContextObject;
- if (typeof contextType === 'object' && contextType !== null) {
- nextContext = readContext(contextType);
- } else {
- var nextLegacyUnmaskedContext = getUnmaskedContext(workInProgress, ctor, true);
- nextContext = getMaskedContext(workInProgress, nextLegacyUnmaskedContext);
- }
- var getDerivedStateFromProps = ctor.getDerivedStateFromProps;
- var hasNewLifecycles = typeof getDerivedStateFromProps === 'function' || typeof instance.getSnapshotBeforeUpdate === 'function'; // Note: During these life-cycles, instance.props/instance.state are what
- // ever the previously attempted to render - not the "current". However,
- // during componentDidUpdate we pass the "current" props.
- // In order to support react-lifecycles-compat polyfilled components,
- // Unsafe lifecycles should not be invoked for components using the new APIs.
- if (!hasNewLifecycles && (typeof instance.UNSAFE_componentWillReceiveProps === 'function' || typeof instance.componentWillReceiveProps === 'function')) {
- if (oldProps !== newProps || oldContext !== nextContext) {
- callComponentWillReceiveProps(workInProgress, instance, newProps, nextContext);
- }
- }
- resetHasForceUpdateBeforeProcessing();
- var oldState = workInProgress.memoizedState;
- var newState = instance.state = oldState;
- processUpdateQueue(workInProgress, newProps, instance, renderLanes);
- newState = workInProgress.memoizedState;
- if (oldProps === newProps && oldState === newState && !hasContextChanged() && !checkHasForceUpdateAfterProcessing()) {
- // If an update was already in progress, we should schedule an Update
- // effect even though we're bailing out, so that cWU/cDU are called.
- if (typeof instance.componentDidMount === 'function') {
- var fiberFlags = Update;
- {
- fiberFlags |= LayoutStatic;
- }
- if ((workInProgress.mode & StrictEffectsMode) !== NoMode) {
- fiberFlags |= MountLayoutDev;
- }
- workInProgress.flags |= fiberFlags;
- }
- return false;
- }
- if (typeof getDerivedStateFromProps === 'function') {
- applyDerivedStateFromProps(workInProgress, ctor, getDerivedStateFromProps, newProps);
- newState = workInProgress.memoizedState;
- }
- var shouldUpdate = checkHasForceUpdateAfterProcessing() || checkShouldComponentUpdate(workInProgress, ctor, oldProps, newProps, oldState, newState, nextContext);
- if (shouldUpdate) {
- // In order to support react-lifecycles-compat polyfilled components,
- // Unsafe lifecycles should not be invoked for components using the new APIs.
- if (!hasNewLifecycles && (typeof instance.UNSAFE_componentWillMount === 'function' || typeof instance.componentWillMount === 'function')) {
- if (typeof instance.componentWillMount === 'function') {
- instance.componentWillMount();
- }
- if (typeof instance.UNSAFE_componentWillMount === 'function') {
- instance.UNSAFE_componentWillMount();
- }
- }
- if (typeof instance.componentDidMount === 'function') {
- var _fiberFlags = Update;
- {
- _fiberFlags |= LayoutStatic;
- }
- if ((workInProgress.mode & StrictEffectsMode) !== NoMode) {
- _fiberFlags |= MountLayoutDev;
- }
- workInProgress.flags |= _fiberFlags;
- }
- } else {
- // If an update was already in progress, we should schedule an Update
- // effect even though we're bailing out, so that cWU/cDU are called.
- if (typeof instance.componentDidMount === 'function') {
- var _fiberFlags2 = Update;
- {
- _fiberFlags2 |= LayoutStatic;
- }
- if ((workInProgress.mode & StrictEffectsMode) !== NoMode) {
- _fiberFlags2 |= MountLayoutDev;
- }
- workInProgress.flags |= _fiberFlags2;
- } // If shouldComponentUpdate returned false, we should still update the
- // memoized state to indicate that this work can be reused.
- workInProgress.memoizedProps = newProps;
- workInProgress.memoizedState = newState;
- } // Update the existing instance's state, props, and context pointers even
- // if shouldComponentUpdate returns false.
- instance.props = newProps;
- instance.state = newState;
- instance.context = nextContext;
- return shouldUpdate;
- } // Invokes the update life-cycles and returns false if it shouldn't rerender.
- function updateClassInstance(current, workInProgress, ctor, newProps, renderLanes) {
- var instance = workInProgress.stateNode;
- cloneUpdateQueue(current, workInProgress);
- var unresolvedOldProps = workInProgress.memoizedProps;
- var oldProps = workInProgress.type === workInProgress.elementType ? unresolvedOldProps : resolveDefaultProps(workInProgress.type, unresolvedOldProps);
- instance.props = oldProps;
- var unresolvedNewProps = workInProgress.pendingProps;
- var oldContext = instance.context;
- var contextType = ctor.contextType;
- var nextContext = emptyContextObject;
- if (typeof contextType === 'object' && contextType !== null) {
- nextContext = readContext(contextType);
- } else {
- var nextUnmaskedContext = getUnmaskedContext(workInProgress, ctor, true);
- nextContext = getMaskedContext(workInProgress, nextUnmaskedContext);
- }
- var getDerivedStateFromProps = ctor.getDerivedStateFromProps;
- var hasNewLifecycles = typeof getDerivedStateFromProps === 'function' || typeof instance.getSnapshotBeforeUpdate === 'function'; // Note: During these life-cycles, instance.props/instance.state are what
- // ever the previously attempted to render - not the "current". However,
- // during componentDidUpdate we pass the "current" props.
- // In order to support react-lifecycles-compat polyfilled components,
- // Unsafe lifecycles should not be invoked for components using the new APIs.
- if (!hasNewLifecycles && (typeof instance.UNSAFE_componentWillReceiveProps === 'function' || typeof instance.componentWillReceiveProps === 'function')) {
- if (unresolvedOldProps !== unresolvedNewProps || oldContext !== nextContext) {
- callComponentWillReceiveProps(workInProgress, instance, newProps, nextContext);
- }
- }
- resetHasForceUpdateBeforeProcessing();
- var oldState = workInProgress.memoizedState;
- var newState = instance.state = oldState;
- processUpdateQueue(workInProgress, newProps, instance, renderLanes);
- newState = workInProgress.memoizedState;
- if (unresolvedOldProps === unresolvedNewProps && oldState === newState && !hasContextChanged() && !checkHasForceUpdateAfterProcessing() && !(enableLazyContextPropagation)) {
- // If an update was already in progress, we should schedule an Update
- // effect even though we're bailing out, so that cWU/cDU are called.
- if (typeof instance.componentDidUpdate === 'function') {
- if (unresolvedOldProps !== current.memoizedProps || oldState !== current.memoizedState) {
- workInProgress.flags |= Update;
- }
- }
- if (typeof instance.getSnapshotBeforeUpdate === 'function') {
- if (unresolvedOldProps !== current.memoizedProps || oldState !== current.memoizedState) {
- workInProgress.flags |= Snapshot;
- }
- }
- return false;
- }
- if (typeof getDerivedStateFromProps === 'function') {
- applyDerivedStateFromProps(workInProgress, ctor, getDerivedStateFromProps, newProps);
- newState = workInProgress.memoizedState;
- }
- var shouldUpdate = checkHasForceUpdateAfterProcessing() || checkShouldComponentUpdate(workInProgress, ctor, oldProps, newProps, oldState, newState, nextContext) || // TODO: In some cases, we'll end up checking if context has changed twice,
- // both before and after `shouldComponentUpdate` has been called. Not ideal,
- // but I'm loath to refactor this function. This only happens for memoized
- // components so it's not that common.
- enableLazyContextPropagation;
- if (shouldUpdate) {
- // In order to support react-lifecycles-compat polyfilled components,
- // Unsafe lifecycles should not be invoked for components using the new APIs.
- if (!hasNewLifecycles && (typeof instance.UNSAFE_componentWillUpdate === 'function' || typeof instance.componentWillUpdate === 'function')) {
- if (typeof instance.componentWillUpdate === 'function') {
- instance.componentWillUpdate(newProps, newState, nextContext);
- }
- if (typeof instance.UNSAFE_componentWillUpdate === 'function') {
- instance.UNSAFE_componentWillUpdate(newProps, newState, nextContext);
- }
- }
- if (typeof instance.componentDidUpdate === 'function') {
- workInProgress.flags |= Update;
- }
- if (typeof instance.getSnapshotBeforeUpdate === 'function') {
- workInProgress.flags |= Snapshot;
- }
- } else {
- // If an update was already in progress, we should schedule an Update
- // effect even though we're bailing out, so that cWU/cDU are called.
- if (typeof instance.componentDidUpdate === 'function') {
- if (unresolvedOldProps !== current.memoizedProps || oldState !== current.memoizedState) {
- workInProgress.flags |= Update;
- }
- }
- if (typeof instance.getSnapshotBeforeUpdate === 'function') {
- if (unresolvedOldProps !== current.memoizedProps || oldState !== current.memoizedState) {
- workInProgress.flags |= Snapshot;
- }
- } // If shouldComponentUpdate returned false, we should still update the
- // memoized props/state to indicate that this work can be reused.
- workInProgress.memoizedProps = newProps;
- workInProgress.memoizedState = newState;
- } // Update the existing instance's state, props, and context pointers even
- // if shouldComponentUpdate returns false.
- instance.props = newProps;
- instance.state = newState;
- instance.context = nextContext;
- return shouldUpdate;
- }
- var didWarnAboutMaps;
- var didWarnAboutGenerators;
- var didWarnAboutStringRefs;
- var ownerHasKeyUseWarning;
- var ownerHasFunctionTypeWarning;
- var warnForMissingKey = function (child, returnFiber) { };
- {
- didWarnAboutMaps = false;
- didWarnAboutGenerators = false;
- didWarnAboutStringRefs = {};
- /**
- * Warn if there's no key explicitly set on dynamic arrays of children or
- * object keys are not valid. This allows us to keep track of children between
- * updates.
- */
- ownerHasKeyUseWarning = {};
- ownerHasFunctionTypeWarning = {};
- warnForMissingKey = function (child, returnFiber) {
- if (child === null || typeof child !== 'object') {
- return;
- }
- if (!child._store || child._store.validated || child.key != null) {
- return;
- }
- if (typeof child._store !== 'object') {
- throw new Error('React Component in warnForMissingKey should have a _store. ' + 'This error is likely caused by a bug in React. Please file an issue.');
- }
- child._store.validated = true;
- var componentName = getComponentNameFromFiber(returnFiber) || 'Component';
- if (ownerHasKeyUseWarning[componentName]) {
- return;
- }
- ownerHasKeyUseWarning[componentName] = true;
- error('Each child in a list should have a unique ' + '"key" prop. See https://reactjs.org/link/warning-keys for ' + 'more information.');
- };
- }
- function coerceRef(returnFiber, current, element) {
- var mixedRef = element.ref;
- if (mixedRef !== null && typeof mixedRef !== 'function' && typeof mixedRef !== 'object') {
- {
- // TODO: Clean this up once we turn on the string ref warning for
- // everyone, because the strict mode case will no longer be relevant
- if ((returnFiber.mode & StrictLegacyMode || warnAboutStringRefs) && // We warn in ReactElement.js if owner and self are equal for string refs
- // because these cannot be automatically converted to an arrow function
- // using a codemod. Therefore, we don't have to warn about string refs again.
- !(element._owner && element._self && element._owner.stateNode !== element._self)) {
- var componentName = getComponentNameFromFiber(returnFiber) || 'Component';
- if (!didWarnAboutStringRefs[componentName]) {
- {
- error('A string ref, "%s", has been found within a strict mode tree. ' + 'String refs are a source of potential bugs and should be avoided. ' + 'We recommend using useRef() or createRef() instead. ' + 'Learn more about using refs safely here: ' + 'https://reactjs.org/link/strict-mode-string-ref', mixedRef);
- }
- didWarnAboutStringRefs[componentName] = true;
- }
- }
- }
- if (element._owner) {
- var owner = element._owner;
- var inst;
- if (owner) {
- var ownerFiber = owner;
- if (ownerFiber.tag !== ClassComponent) {
- throw new Error('Function components cannot have string refs. ' + 'We recommend using useRef() instead. ' + 'Learn more about using refs safely here: ' + 'https://reactjs.org/link/strict-mode-string-ref');
- }
- inst = ownerFiber.stateNode;
- }
- if (!inst) {
- throw new Error("Missing owner for string ref " + mixedRef + ". This error is likely caused by a " + 'bug in React. Please file an issue.');
- } // Assigning this to a const so Flow knows it won't change in the closure
- var resolvedInst = inst;
- {
- checkPropStringCoercion(mixedRef, 'ref');
- }
- var stringRef = '' + mixedRef; // Check if previous string ref matches new string ref
- if (current !== null && current.ref !== null && typeof current.ref === 'function' && current.ref._stringRef === stringRef) {
- return current.ref;
- }
- var ref = function (value) {
- var refs = resolvedInst.refs;
- if (refs === emptyRefsObject) {
- // This is a lazy pooled frozen object, so we need to initialize.
- refs = resolvedInst.refs = {};
- }
- if (value === null) {
- delete refs[stringRef];
- } else {
- refs[stringRef] = value;
- }
- };
- ref._stringRef = stringRef;
- return ref;
- } else {
- if (typeof mixedRef !== 'string') {
- throw new Error('Expected ref to be a function, a string, an object returned by React.createRef(), or null.');
- }
- if (!element._owner) {
- throw new Error("Element ref was specified as a string (" + mixedRef + ") but no owner was set. This could happen for one of" + ' the following reasons:\n' + '1. You may be adding a ref to a function component\n' + "2. You may be adding a ref to a component that was not created inside a component's render method\n" + '3. You have multiple copies of React loaded\n' + 'See https://reactjs.org/link/refs-must-have-owner for more information.');
- }
- }
- }
- return mixedRef;
- }
- function throwOnInvalidObjectType(returnFiber, newChild) {
- var childString = Object.prototype.toString.call(newChild);
- throw new Error("Objects are not valid as a React child (found: " + (childString === '[object Object]' ? 'object with keys {' + Object.keys(newChild).join(', ') + '}' : childString) + "). " + 'If you meant to render a collection of children, use an array ' + 'instead.');
- }
- function warnOnFunctionType(returnFiber) {
- {
- var componentName = getComponentNameFromFiber(returnFiber) || 'Component';
- if (ownerHasFunctionTypeWarning[componentName]) {
- return;
- }
- ownerHasFunctionTypeWarning[componentName] = true;
- error('Functions are not valid as a React child. This may happen if ' + 'you return a Component instead of <Component /> from render. ' + 'Or maybe you meant to call this function rather than return it.');
- }
- }
- function resolveLazy(lazyType) {
- var payload = lazyType._payload;
- var init = lazyType._init;
- return init(payload);
- } // This wrapper function exists because I expect to clone the code in each path
- // to be able to optimize each path individually by branching early. This needs
- // a compiler or we can do it manually. Helpers that don't need this branching
- // live outside of this function.
- function ChildReconciler(shouldTrackSideEffects) {
- function deleteChild(returnFiber, childToDelete) {
- if (!shouldTrackSideEffects) {
- // Noop.
- return;
- }
- var deletions = returnFiber.deletions;
- if (deletions === null) {
- returnFiber.deletions = [childToDelete];
- returnFiber.flags |= ChildDeletion;
- } else {
- deletions.push(childToDelete);
- }
- }
- function deleteRemainingChildren(returnFiber, currentFirstChild) {
- if (!shouldTrackSideEffects) {
- // Noop.
- return null;
- } // TODO: For the shouldClone case, this could be micro-optimized a bit by
- // assuming that after the first child we've already added everything.
- var childToDelete = currentFirstChild;
- while (childToDelete !== null) {
- deleteChild(returnFiber, childToDelete);
- childToDelete = childToDelete.sibling;
- }
- return null;
- }
- function mapRemainingChildren(returnFiber, currentFirstChild) {
- // Add the remaining children to a temporary map so that we can find them by
- // keys quickly. Implicit (null) keys get added to this set with their index
- // instead.
- var existingChildren = new Map();
- var existingChild = currentFirstChild;
- while (existingChild !== null) {
- if (existingChild.key !== null) {
- existingChildren.set(existingChild.key, existingChild);
- } else {
- existingChildren.set(existingChild.index, existingChild);
- }
- existingChild = existingChild.sibling;
- }
- return existingChildren;
- }
- function useFiber(fiber, pendingProps) {
- // We currently set sibling to null and index to 0 here because it is easy
- // to forget to do before returning it. E.g. for the single child case.
- var clone = createWorkInProgress(fiber, pendingProps);
- clone.index = 0;
- clone.sibling = null;
- return clone;
- }
- function placeChild(newFiber, lastPlacedIndex, newIndex) {
- newFiber.index = newIndex;
- if (!shouldTrackSideEffects) {
- // During hydration, the useId algorithm needs to know which fibers are
- // part of a list of children (arrays, iterators).
- newFiber.flags |= Forked;
- return lastPlacedIndex;
- }
- var current = newFiber.alternate;
- if (current !== null) {
- var oldIndex = current.index;
- if (oldIndex < lastPlacedIndex) {
- // This is a move.
- newFiber.flags |= Placement;
- return lastPlacedIndex;
- } else {
- // This item can stay in place.
- return oldIndex;
- }
- } else {
- // This is an insertion.
- newFiber.flags |= Placement;
- return lastPlacedIndex;
- }
- }
- function placeSingleChild(newFiber) {
- // This is simpler for the single child case. We only need to do a
- // placement for inserting new children.
- if (shouldTrackSideEffects && newFiber.alternate === null) {
- newFiber.flags |= Placement;
- }
- return newFiber;
- }
- function updateTextNode(returnFiber, current, textContent, lanes) {
- if (current === null || current.tag !== HostText) {
- // Insert
- var created = createFiberFromText(textContent, returnFiber.mode, lanes);
- created.return = returnFiber;
- return created;
- } else {
- // Update
- var existing = useFiber(current, textContent);
- existing.return = returnFiber;
- return existing;
- }
- }
- function updateElement(returnFiber, current, element, lanes) {
- var elementType = element.type;
- if (elementType === REACT_FRAGMENT_TYPE) {
- return updateFragment(returnFiber, current, element.props.children, lanes, element.key);
- }
- if (current !== null) {
- if (current.elementType === elementType || ( // Keep this check inline so it only runs on the false path:
- isCompatibleFamilyForHotReloading(current, element)) || // Lazy types should reconcile their resolved type.
- // We need to do this after the Hot Reloading check above,
- // because hot reloading has different semantics than prod because
- // it doesn't resuspend. So we can't let the call below suspend.
- typeof elementType === 'object' && elementType !== null && elementType.$$typeof === REACT_LAZY_TYPE && resolveLazy(elementType) === current.type) {
- // Move based on index
- var existing = useFiber(current, element.props);
- existing.ref = coerceRef(returnFiber, current, element);
- existing.return = returnFiber;
- {
- existing._debugSource = element._source;
- existing._debugOwner = element._owner;
- }
- return existing;
- }
- } // Insert
- var created = createFiberFromElement(element, returnFiber.mode, lanes);
- created.ref = coerceRef(returnFiber, current, element);
- created.return = returnFiber;
- return created;
- }
- function updatePortal(returnFiber, current, portal, lanes) {
- if (current === null || current.tag !== HostPortal || current.stateNode.containerInfo !== portal.containerInfo || current.stateNode.implementation !== portal.implementation) {
- // Insert
- var created = createFiberFromPortal(portal, returnFiber.mode, lanes);
- created.return = returnFiber;
- return created;
- } else {
- // Update
- var existing = useFiber(current, portal.children || []);
- existing.return = returnFiber;
- return existing;
- }
- }
- function updateFragment(returnFiber, current, fragment, lanes, key) {
- if (current === null || current.tag !== Fragment) {
- // Insert
- var created = createFiberFromFragment(fragment, returnFiber.mode, lanes, key);
- created.return = returnFiber;
- return created;
- } else {
- // Update
- var existing = useFiber(current, fragment);
- existing.return = returnFiber;
- return existing;
- }
- }
- function createChild(returnFiber, newChild, lanes) {
- if (typeof newChild === 'string' && newChild !== '' || typeof newChild === 'number') {
- // Text nodes don't have keys. If the previous node is implicitly keyed
- // we can continue to replace it without aborting even if it is not a text
- // node.
- var created = createFiberFromText('' + newChild, returnFiber.mode, lanes);
- created.return = returnFiber;
- return created;
- }
- if (typeof newChild === 'object' && newChild !== null) {
- switch (newChild.$$typeof) {
- case REACT_ELEMENT_TYPE:
- {
- var _created = createFiberFromElement(newChild, returnFiber.mode, lanes);
- _created.ref = coerceRef(returnFiber, null, newChild);
- _created.return = returnFiber;
- return _created;
- }
- case REACT_PORTAL_TYPE:
- {
- var _created2 = createFiberFromPortal(newChild, returnFiber.mode, lanes);
- _created2.return = returnFiber;
- return _created2;
- }
- case REACT_LAZY_TYPE:
- {
- var payload = newChild._payload;
- var init = newChild._init;
- return createChild(returnFiber, init(payload), lanes);
- }
- }
- if (isArray(newChild) || getIteratorFn(newChild)) {
- var _created3 = createFiberFromFragment(newChild, returnFiber.mode, lanes, null);
- _created3.return = returnFiber;
- return _created3;
- }
- throwOnInvalidObjectType(returnFiber, newChild);
- }
- {
- if (typeof newChild === 'function') {
- warnOnFunctionType(returnFiber);
- }
- }
- return null;
- }
- function updateSlot(returnFiber, oldFiber, newChild, lanes) {
- // Update the fiber if the keys match, otherwise return null.
- var key = oldFiber !== null ? oldFiber.key : null;
- if (typeof newChild === 'string' && newChild !== '' || typeof newChild === 'number') {
- // Text nodes don't have keys. If the previous node is implicitly keyed
- // we can continue to replace it without aborting even if it is not a text
- // node.
- if (key !== null) {
- return null;
- }
- return updateTextNode(returnFiber, oldFiber, '' + newChild, lanes);
- }
- if (typeof newChild === 'object' && newChild !== null) {
- switch (newChild.$$typeof) {
- case REACT_ELEMENT_TYPE:
- {
- if (newChild.key === key) {
- return updateElement(returnFiber, oldFiber, newChild, lanes);
- } else {
- return null;
- }
- }
- case REACT_PORTAL_TYPE:
- {
- if (newChild.key === key) {
- return updatePortal(returnFiber, oldFiber, newChild, lanes);
- } else {
- return null;
- }
- }
- case REACT_LAZY_TYPE:
- {
- var payload = newChild._payload;
- var init = newChild._init;
- return updateSlot(returnFiber, oldFiber, init(payload), lanes);
- }
- }
- if (isArray(newChild) || getIteratorFn(newChild)) {
- if (key !== null) {
- return null;
- }
- return updateFragment(returnFiber, oldFiber, newChild, lanes, null);
- }
- throwOnInvalidObjectType(returnFiber, newChild);
- }
- {
- if (typeof newChild === 'function') {
- warnOnFunctionType(returnFiber);
- }
- }
- return null;
- }
- function updateFromMap(existingChildren, returnFiber, newIdx, newChild, lanes) {
- if (typeof newChild === 'string' && newChild !== '' || typeof newChild === 'number') {
- // Text nodes don't have keys, so we neither have to check the old nor
- // new node for the key. If both are text nodes, they match.
- var matchedFiber = existingChildren.get(newIdx) || null;
- return updateTextNode(returnFiber, matchedFiber, '' + newChild, lanes);
- }
- if (typeof newChild === 'object' && newChild !== null) {
- switch (newChild.$$typeof) {
- case REACT_ELEMENT_TYPE:
- {
- var _matchedFiber = existingChildren.get(newChild.key === null ? newIdx : newChild.key) || null;
- return updateElement(returnFiber, _matchedFiber, newChild, lanes);
- }
- case REACT_PORTAL_TYPE:
- {
- var _matchedFiber2 = existingChildren.get(newChild.key === null ? newIdx : newChild.key) || null;
- return updatePortal(returnFiber, _matchedFiber2, newChild, lanes);
- }
- case REACT_LAZY_TYPE:
- var payload = newChild._payload;
- var init = newChild._init;
- return updateFromMap(existingChildren, returnFiber, newIdx, init(payload), lanes);
- }
- if (isArray(newChild) || getIteratorFn(newChild)) {
- var _matchedFiber3 = existingChildren.get(newIdx) || null;
- return updateFragment(returnFiber, _matchedFiber3, newChild, lanes, null);
- }
- throwOnInvalidObjectType(returnFiber, newChild);
- }
- {
- if (typeof newChild === 'function') {
- warnOnFunctionType(returnFiber);
- }
- }
- return null;
- }
- /**
- * Warns if there is a duplicate or missing key
- */
- function warnOnInvalidKey(child, knownKeys, returnFiber) {
- {
- if (typeof child !== 'object' || child === null) {
- return knownKeys;
- }
- switch (child.$$typeof) {
- case REACT_ELEMENT_TYPE:
- case REACT_PORTAL_TYPE:
- warnForMissingKey(child, returnFiber);
- var key = child.key;
- if (typeof key !== 'string') {
- break;
- }
- if (knownKeys === null) {
- knownKeys = new Set();
- knownKeys.add(key);
- break;
- }
- if (!knownKeys.has(key)) {
- knownKeys.add(key);
- break;
- }
- error('Encountered two children with the same key, `%s`. ' + 'Keys should be unique so that components maintain their identity ' + 'across updates. Non-unique keys may cause children to be ' + 'duplicated and/or omitted — the behavior is unsupported and ' + 'could change in a future version.', key);
- break;
- case REACT_LAZY_TYPE:
- var payload = child._payload;
- var init = child._init;
- warnOnInvalidKey(init(payload), knownKeys, returnFiber);
- break;
- }
- }
- return knownKeys;
- }
- function reconcileChildrenArray(returnFiber, currentFirstChild, newChildren, lanes) {
- // This algorithm can't optimize by searching from both ends since we
- // don't have backpointers on fibers. I'm trying to see how far we can get
- // with that model. If it ends up not being worth the tradeoffs, we can
- // add it later.
- // Even with a two ended optimization, we'd want to optimize for the case
- // where there are few changes and brute force the comparison instead of
- // going for the Map. It'd like to explore hitting that path first in
- // forward-only mode and only go for the Map once we notice that we need
- // lots of look ahead. This doesn't handle reversal as well as two ended
- // search but that's unusual. Besides, for the two ended optimization to
- // work on Iterables, we'd need to copy the whole set.
- // In this first iteration, we'll just live with hitting the bad case
- // (adding everything to a Map) in for every insert/move.
- // If you change this code, also update reconcileChildrenIterator() which
- // uses the same algorithm.
- {
- // First, validate keys.
- var knownKeys = null;
- for (var i = 0; i < newChildren.length; i++) {
- var child = newChildren[i];
- knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber);
- }
- }
- var resultingFirstChild = null;
- var previousNewFiber = null;
- var oldFiber = currentFirstChild;
- var lastPlacedIndex = 0;
- var newIdx = 0;
- var nextOldFiber = null;
- for (; oldFiber !== null && newIdx < newChildren.length; newIdx++) {
- if (oldFiber.index > newIdx) {
- nextOldFiber = oldFiber;
- oldFiber = null;
- } else {
- nextOldFiber = oldFiber.sibling;
- }
- var newFiber = updateSlot(returnFiber, oldFiber, newChildren[newIdx], lanes);
- if (newFiber === null) {
- // TODO: This breaks on empty slots like null children. That's
- // unfortunate because it triggers the slow path all the time. We need
- // a better way to communicate whether this was a miss or null,
- // boolean, undefined, etc.
- if (oldFiber === null) {
- oldFiber = nextOldFiber;
- }
- break;
- }
- if (shouldTrackSideEffects) {
- if (oldFiber && newFiber.alternate === null) {
- // We matched the slot, but we didn't reuse the existing fiber, so we
- // need to delete the existing child.
- deleteChild(returnFiber, oldFiber);
- }
- }
- lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx);
- if (previousNewFiber === null) {
- // TODO: Move out of the loop. This only happens for the first run.
- resultingFirstChild = newFiber;
- } else {
- // TODO: Defer siblings if we're not at the right index for this slot.
- // I.e. if we had null values before, then we want to defer this
- // for each null value. However, we also don't want to call updateSlot
- // with the previous one.
- previousNewFiber.sibling = newFiber;
- }
- previousNewFiber = newFiber;
- oldFiber = nextOldFiber;
- }
- if (newIdx === newChildren.length) {
- // We've reached the end of the new children. We can delete the rest.
- deleteRemainingChildren(returnFiber, oldFiber);
- if (getIsHydrating()) {
- var numberOfForks = newIdx;
- pushTreeFork(returnFiber, numberOfForks);
- }
- return resultingFirstChild;
- }
- if (oldFiber === null) {
- // If we don't have any more existing children we can choose a fast path
- // since the rest will all be insertions.
- for (; newIdx < newChildren.length; newIdx++) {
- var _newFiber = createChild(returnFiber, newChildren[newIdx], lanes);
- if (_newFiber === null) {
- continue;
- }
- lastPlacedIndex = placeChild(_newFiber, lastPlacedIndex, newIdx);
- if (previousNewFiber === null) {
- // TODO: Move out of the loop. This only happens for the first run.
- resultingFirstChild = _newFiber;
- } else {
- previousNewFiber.sibling = _newFiber;
- }
- previousNewFiber = _newFiber;
- }
- if (getIsHydrating()) {
- var _numberOfForks = newIdx;
- pushTreeFork(returnFiber, _numberOfForks);
- }
- return resultingFirstChild;
- } // Add all children to a key map for quick lookups.
- var existingChildren = mapRemainingChildren(returnFiber, oldFiber); // Keep scanning and use the map to restore deleted items as moves.
- for (; newIdx < newChildren.length; newIdx++) {
- var _newFiber2 = updateFromMap(existingChildren, returnFiber, newIdx, newChildren[newIdx], lanes);
- if (_newFiber2 !== null) {
- if (shouldTrackSideEffects) {
- if (_newFiber2.alternate !== null) {
- // The new fiber is a work in progress, but if there exists a
- // current, that means that we reused the fiber. We need to delete
- // it from the child list so that we don't add it to the deletion
- // list.
- existingChildren.delete(_newFiber2.key === null ? newIdx : _newFiber2.key);
- }
- }
- lastPlacedIndex = placeChild(_newFiber2, lastPlacedIndex, newIdx);
- if (previousNewFiber === null) {
- resultingFirstChild = _newFiber2;
- } else {
- previousNewFiber.sibling = _newFiber2;
- }
- previousNewFiber = _newFiber2;
- }
- }
- if (shouldTrackSideEffects) {
- // Any existing children that weren't consumed above were deleted. We need
- // to add them to the deletion list.
- existingChildren.forEach(function (child) {
- return deleteChild(returnFiber, child);
- });
- }
- if (getIsHydrating()) {
- var _numberOfForks2 = newIdx;
- pushTreeFork(returnFiber, _numberOfForks2);
- }
- return resultingFirstChild;
- }
- function reconcileChildrenIterator(returnFiber, currentFirstChild, newChildrenIterable, lanes) {
- // This is the same implementation as reconcileChildrenArray(),
- // but using the iterator instead.
- var iteratorFn = getIteratorFn(newChildrenIterable);
- if (typeof iteratorFn !== 'function') {
- throw new Error('An object is not an iterable. This error is likely caused by a bug in ' + 'React. Please file an issue.');
- }
- {
- // We don't support rendering Generators because it's a mutation.
- // See https://github.com/facebook/react/issues/12995
- if (typeof Symbol === 'function' && // $FlowFixMe Flow doesn't know about toStringTag
- newChildrenIterable[Symbol.toStringTag] === 'Generator') {
- if (!didWarnAboutGenerators) {
- error('Using Generators as children is unsupported and will likely yield ' + 'unexpected results because enumerating a generator mutates it. ' + 'You may convert it to an array with `Array.from()` or the ' + '`[...spread]` operator before rendering. Keep in mind ' + 'you might need to polyfill these features for older browsers.');
- }
- didWarnAboutGenerators = true;
- } // Warn about using Maps as children
- if (newChildrenIterable.entries === iteratorFn) {
- if (!didWarnAboutMaps) {
- error('Using Maps as children is not supported. ' + 'Use an array of keyed ReactElements instead.');
- }
- didWarnAboutMaps = true;
- } // First, validate keys.
- // We'll get a different iterator later for the main pass.
- var _newChildren = iteratorFn.call(newChildrenIterable);
- if (_newChildren) {
- var knownKeys = null;
- var _step = _newChildren.next();
- for (; !_step.done; _step = _newChildren.next()) {
- var child = _step.value;
- knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber);
- }
- }
- }
- var newChildren = iteratorFn.call(newChildrenIterable);
- if (newChildren == null) {
- throw new Error('An iterable object provided no iterator.');
- }
- var resultingFirstChild = null;
- var previousNewFiber = null;
- var oldFiber = currentFirstChild;
- var lastPlacedIndex = 0;
- var newIdx = 0;
- var nextOldFiber = null;
- var step = newChildren.next();
- for (; oldFiber !== null && !step.done; newIdx++, step = newChildren.next()) {
- if (oldFiber.index > newIdx) {
- nextOldFiber = oldFiber;
- oldFiber = null;
- } else {
- nextOldFiber = oldFiber.sibling;
- }
- var newFiber = updateSlot(returnFiber, oldFiber, step.value, lanes);
- if (newFiber === null) {
- // TODO: This breaks on empty slots like null children. That's
- // unfortunate because it triggers the slow path all the time. We need
- // a better way to communicate whether this was a miss or null,
- // boolean, undefined, etc.
- if (oldFiber === null) {
- oldFiber = nextOldFiber;
- }
- break;
- }
- if (shouldTrackSideEffects) {
- if (oldFiber && newFiber.alternate === null) {
- // We matched the slot, but we didn't reuse the existing fiber, so we
- // need to delete the existing child.
- deleteChild(returnFiber, oldFiber);
- }
- }
- lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx);
- if (previousNewFiber === null) {
- // TODO: Move out of the loop. This only happens for the first run.
- resultingFirstChild = newFiber;
- } else {
- // TODO: Defer siblings if we're not at the right index for this slot.
- // I.e. if we had null values before, then we want to defer this
- // for each null value. However, we also don't want to call updateSlot
- // with the previous one.
- previousNewFiber.sibling = newFiber;
- }
- previousNewFiber = newFiber;
- oldFiber = nextOldFiber;
- }
- if (step.done) {
- // We've reached the end of the new children. We can delete the rest.
- deleteRemainingChildren(returnFiber, oldFiber);
- if (getIsHydrating()) {
- var numberOfForks = newIdx;
- pushTreeFork(returnFiber, numberOfForks);
- }
- return resultingFirstChild;
- }
- if (oldFiber === null) {
- // If we don't have any more existing children we can choose a fast path
- // since the rest will all be insertions.
- for (; !step.done; newIdx++, step = newChildren.next()) {
- var _newFiber3 = createChild(returnFiber, step.value, lanes);
- if (_newFiber3 === null) {
- continue;
- }
- lastPlacedIndex = placeChild(_newFiber3, lastPlacedIndex, newIdx);
- if (previousNewFiber === null) {
- // TODO: Move out of the loop. This only happens for the first run.
- resultingFirstChild = _newFiber3;
- } else {
- previousNewFiber.sibling = _newFiber3;
- }
- previousNewFiber = _newFiber3;
- }
- if (getIsHydrating()) {
- var _numberOfForks3 = newIdx;
- pushTreeFork(returnFiber, _numberOfForks3);
- }
- return resultingFirstChild;
- } // Add all children to a key map for quick lookups.
- var existingChildren = mapRemainingChildren(returnFiber, oldFiber); // Keep scanning and use the map to restore deleted items as moves.
- for (; !step.done; newIdx++, step = newChildren.next()) {
- var _newFiber4 = updateFromMap(existingChildren, returnFiber, newIdx, step.value, lanes);
- if (_newFiber4 !== null) {
- if (shouldTrackSideEffects) {
- if (_newFiber4.alternate !== null) {
- // The new fiber is a work in progress, but if there exists a
- // current, that means that we reused the fiber. We need to delete
- // it from the child list so that we don't add it to the deletion
- // list.
- existingChildren.delete(_newFiber4.key === null ? newIdx : _newFiber4.key);
- }
- }
- lastPlacedIndex = placeChild(_newFiber4, lastPlacedIndex, newIdx);
- if (previousNewFiber === null) {
- resultingFirstChild = _newFiber4;
- } else {
- previousNewFiber.sibling = _newFiber4;
- }
- previousNewFiber = _newFiber4;
- }
- }
- if (shouldTrackSideEffects) {
- // Any existing children that weren't consumed above were deleted. We need
- // to add them to the deletion list.
- existingChildren.forEach(function (child) {
- return deleteChild(returnFiber, child);
- });
- }
- if (getIsHydrating()) {
- var _numberOfForks4 = newIdx;
- pushTreeFork(returnFiber, _numberOfForks4);
- }
- return resultingFirstChild;
- }
- function reconcileSingleTextNode(returnFiber, currentFirstChild, textContent, lanes) {
- // There's no need to check for keys on text nodes since we don't have a
- // way to define them.
- if (currentFirstChild !== null && currentFirstChild.tag === HostText) {
- // We already have an existing node so let's just update it and delete
- // the rest.
- deleteRemainingChildren(returnFiber, currentFirstChild.sibling);
- var existing = useFiber(currentFirstChild, textContent);
- existing.return = returnFiber;
- return existing;
- } // The existing first child is not a text node so we need to create one
- // and delete the existing ones.
- deleteRemainingChildren(returnFiber, currentFirstChild);
- var created = createFiberFromText(textContent, returnFiber.mode, lanes);
- created.return = returnFiber;
- return created;
- }
- function reconcileSingleElement(returnFiber, currentFirstChild, element, lanes) {
- var key = element.key;
- var child = currentFirstChild;
- while (child !== null) {
- // TODO: If key === null and child.key === null, then this only applies to
- // the first item in the list.
- if (child.key === key) {
- var elementType = element.type;
- if (elementType === REACT_FRAGMENT_TYPE) {
- if (child.tag === Fragment) {
- deleteRemainingChildren(returnFiber, child.sibling);
- var existing = useFiber(child, element.props.children);
- existing.return = returnFiber;
- {
- existing._debugSource = element._source;
- existing._debugOwner = element._owner;
- }
- return existing;
- }
- } else {
- if (child.elementType === elementType || ( // Keep this check inline so it only runs on the false path:
- isCompatibleFamilyForHotReloading(child, element)) || // Lazy types should reconcile their resolved type.
- // We need to do this after the Hot Reloading check above,
- // because hot reloading has different semantics than prod because
- // it doesn't resuspend. So we can't let the call below suspend.
- typeof elementType === 'object' && elementType !== null && elementType.$$typeof === REACT_LAZY_TYPE && resolveLazy(elementType) === child.type) {
- deleteRemainingChildren(returnFiber, child.sibling);
- var _existing = useFiber(child, element.props);
- _existing.ref = coerceRef(returnFiber, child, element);
- _existing.return = returnFiber;
- {
- _existing._debugSource = element._source;
- _existing._debugOwner = element._owner;
- }
- return _existing;
- }
- } // Didn't match.
- deleteRemainingChildren(returnFiber, child);
- break;
- } else {
- deleteChild(returnFiber, child);
- }
- child = child.sibling;
- }
- if (element.type === REACT_FRAGMENT_TYPE) {
- var created = createFiberFromFragment(element.props.children, returnFiber.mode, lanes, element.key);
- created.return = returnFiber;
- return created;
- } else {
- var _created4 = createFiberFromElement(element, returnFiber.mode, lanes);
- _created4.ref = coerceRef(returnFiber, currentFirstChild, element);
- _created4.return = returnFiber;
- return _created4;
- }
- }
- function reconcileSinglePortal(returnFiber, currentFirstChild, portal, lanes) {
- var key = portal.key;
- var child = currentFirstChild;
- while (child !== null) {
- // TODO: If key === null and child.key === null, then this only applies to
- // the first item in the list.
- if (child.key === key) {
- if (child.tag === HostPortal && child.stateNode.containerInfo === portal.containerInfo && child.stateNode.implementation === portal.implementation) {
- deleteRemainingChildren(returnFiber, child.sibling);
- var existing = useFiber(child, portal.children || []);
- existing.return = returnFiber;
- return existing;
- } else {
- deleteRemainingChildren(returnFiber, child);
- break;
- }
- } else {
- deleteChild(returnFiber, child);
- }
- child = child.sibling;
- }
- var created = createFiberFromPortal(portal, returnFiber.mode, lanes);
- created.return = returnFiber;
- return created;
- } // This API will tag the children with the side-effect of the reconciliation
- // itself. They will be added to the side-effect list as we pass through the
- // children and the parent.
- function reconcileChildFibers(returnFiber, currentFirstChild, newChild, lanes) {
- // This function is not recursive.
- // If the top level item is an array, we treat it as a set of children,
- // not as a fragment. Nested arrays on the other hand will be treated as
- // fragment nodes. Recursion happens at the normal flow.
- // Handle top level unkeyed fragments as if they were arrays.
- // This leads to an ambiguity between <>{[...]}</> and <>...</>.
- // We treat the ambiguous cases above the same.
- var isUnkeyedTopLevelFragment = typeof newChild === 'object' && newChild !== null && newChild.type === REACT_FRAGMENT_TYPE && newChild.key === null;
- if (isUnkeyedTopLevelFragment) {
- newChild = newChild.props.children;
- } // Handle object types
- if (typeof newChild === 'object' && newChild !== null) {
- switch (newChild.$$typeof) {
- case REACT_ELEMENT_TYPE:
- return placeSingleChild(reconcileSingleElement(returnFiber, currentFirstChild, newChild, lanes));
- case REACT_PORTAL_TYPE:
- return placeSingleChild(reconcileSinglePortal(returnFiber, currentFirstChild, newChild, lanes));
- case REACT_LAZY_TYPE:
- var payload = newChild._payload;
- var init = newChild._init; // TODO: This function is supposed to be non-recursive.
- return reconcileChildFibers(returnFiber, currentFirstChild, init(payload), lanes);
- }
- if (isArray(newChild)) {
- return reconcileChildrenArray(returnFiber, currentFirstChild, newChild, lanes);
- }
- if (getIteratorFn(newChild)) {
- return reconcileChildrenIterator(returnFiber, currentFirstChild, newChild, lanes);
- }
- throwOnInvalidObjectType(returnFiber, newChild);
- }
- if (typeof newChild === 'string' && newChild !== '' || typeof newChild === 'number') {
- return placeSingleChild(reconcileSingleTextNode(returnFiber, currentFirstChild, '' + newChild, lanes));
- }
- {
- if (typeof newChild === 'function') {
- warnOnFunctionType(returnFiber);
- }
- } // Remaining cases are all treated as empty.
- return deleteRemainingChildren(returnFiber, currentFirstChild);
- }
- return reconcileChildFibers;
- }
- var reconcileChildFibers = ChildReconciler(true);
- var mountChildFibers = ChildReconciler(false);
- function cloneChildFibers(current, workInProgress) {
- if (current !== null && workInProgress.child !== current.child) {
- throw new Error('Resuming work not yet implemented.');
- }
- if (workInProgress.child === null) {
- return;
- }
- var currentChild = workInProgress.child;
- var newChild = createWorkInProgress(currentChild, currentChild.pendingProps);
- workInProgress.child = newChild;
- newChild.return = workInProgress;
- while (currentChild.sibling !== null) {
- currentChild = currentChild.sibling;
- newChild = newChild.sibling = createWorkInProgress(currentChild, currentChild.pendingProps);
- newChild.return = workInProgress;
- }
- newChild.sibling = null;
- } // Reset a workInProgress child set to prepare it for a second pass.
- function resetChildFibers(workInProgress, lanes) {
- var child = workInProgress.child;
- while (child !== null) {
- resetWorkInProgress(child, lanes);
- child = child.sibling;
- }
- }
- var NO_CONTEXT = {};
- var contextStackCursor$1 = createCursor(NO_CONTEXT);
- var contextFiberStackCursor = createCursor(NO_CONTEXT);
- var rootInstanceStackCursor = createCursor(NO_CONTEXT);
- function requiredContext(c) {
- if (c === NO_CONTEXT) {
- throw new Error('Expected host context to exist. This error is likely caused by a bug ' + 'in React. Please file an issue.');
- }
- return c;
- }
- function getRootHostContainer() {
- var rootInstance = requiredContext(rootInstanceStackCursor.current);
- return rootInstance;
- }
- function pushHostContainer(fiber, nextRootInstance) {
- // Push current root instance onto the stack;
- // This allows us to reset root when portals are popped.
- push(rootInstanceStackCursor, nextRootInstance, fiber); // Track the context and the Fiber that provided it.
- // This enables us to pop only Fibers that provide unique contexts.
- push(contextFiberStackCursor, fiber, fiber); // Finally, we need to push the host context to the stack.
- // However, we can't just call getRootHostContext() and push it because
- // we'd have a different number of entries on the stack depending on
- // whether getRootHostContext() throws somewhere in renderer code or not.
- // So we push an empty value first. This lets us safely unwind on errors.
- push(contextStackCursor$1, NO_CONTEXT, fiber);
- var nextRootContext = getRootHostContext(nextRootInstance); // Now that we know this function doesn't throw, replace it.
- pop(contextStackCursor$1, fiber);
- push(contextStackCursor$1, nextRootContext, fiber);
- }
- function popHostContainer(fiber) {
- pop(contextStackCursor$1, fiber);
- pop(contextFiberStackCursor, fiber);
- pop(rootInstanceStackCursor, fiber);
- }
- function getHostContext() {
- var context = requiredContext(contextStackCursor$1.current);
- return context;
- }
- function pushHostContext(fiber) {
- var rootInstance = requiredContext(rootInstanceStackCursor.current);
- var context = requiredContext(contextStackCursor$1.current);
- var nextContext = getChildHostContext(context, fiber.type); // Don't push this Fiber's context unless it's unique.
- if (context === nextContext) {
- return;
- } // Track the context and the Fiber that provided it.
- // This enables us to pop only Fibers that provide unique contexts.
- push(contextFiberStackCursor, fiber, fiber);
- push(contextStackCursor$1, nextContext, fiber);
- }
- function popHostContext(fiber) {
- // Do not pop unless this Fiber provided the current context.
- // pushHostContext() only pushes Fibers that provide unique contexts.
- if (contextFiberStackCursor.current !== fiber) {
- return;
- }
- pop(contextStackCursor$1, fiber);
- pop(contextFiberStackCursor, fiber);
- }
- var DefaultSuspenseContext = 0; // The Suspense Context is split into two parts. The lower bits is
- // inherited deeply down the subtree. The upper bits only affect
- // this immediate suspense boundary and gets reset each new
- // boundary or suspense list.
- var SubtreeSuspenseContextMask = 1; // Subtree Flags:
- // InvisibleParentSuspenseContext indicates that one of our parent Suspense
- // boundaries is not currently showing visible main content.
- // Either because it is already showing a fallback or is not mounted at all.
- // We can use this to determine if it is desirable to trigger a fallback at
- // the parent. If not, then we might need to trigger undesirable boundaries
- // and/or suspend the commit to avoid hiding the parent content.
- var InvisibleParentSuspenseContext = 1; // Shallow Flags:
- // ForceSuspenseFallback can be used by SuspenseList to force newly added
- // items into their fallback state during one of the render passes.
- var ForceSuspenseFallback = 2;
- var suspenseStackCursor = createCursor(DefaultSuspenseContext);
- function hasSuspenseContext(parentContext, flag) {
- return (parentContext & flag) !== 0;
- }
- function setDefaultShallowSuspenseContext(parentContext) {
- return parentContext & SubtreeSuspenseContextMask;
- }
- function setShallowSuspenseContext(parentContext, shallowContext) {
- return parentContext & SubtreeSuspenseContextMask | shallowContext;
- }
- function addSubtreeSuspenseContext(parentContext, subtreeContext) {
- return parentContext | subtreeContext;
- }
- function pushSuspenseContext(fiber, newContext) {
- push(suspenseStackCursor, newContext, fiber);
- }
- function popSuspenseContext(fiber) {
- pop(suspenseStackCursor, fiber);
- }
- function shouldCaptureSuspense(workInProgress, hasInvisibleParent) {
- // If it was the primary children that just suspended, capture and render the
- // fallback. Otherwise, don't capture and bubble to the next boundary.
- var nextState = workInProgress.memoizedState;
- if (nextState !== null) {
- if (nextState.dehydrated !== null) {
- // A dehydrated boundary always captures.
- return true;
- }
- return false;
- }
- var props = workInProgress.memoizedProps; // Regular boundaries always capture.
- {
- return true;
- } // If it's a boundary we should avoid, then we prefer to bubble up to the
- }
- function findFirstSuspended(row) {
- var node = row;
- while (node !== null) {
- if (node.tag === SuspenseComponent) {
- var state = node.memoizedState;
- if (state !== null) {
- var dehydrated = state.dehydrated;
- if (dehydrated === null || isSuspenseInstancePending(dehydrated) || isSuspenseInstanceFallback(dehydrated)) {
- return node;
- }
- }
- } else if (node.tag === SuspenseListComponent && // revealOrder undefined can't be trusted because it don't
- // keep track of whether it suspended or not.
- node.memoizedProps.revealOrder !== undefined) {
- var didSuspend = (node.flags & DidCapture) !== NoFlags;
- if (didSuspend) {
- return node;
- }
- } else if (node.child !== null) {
- node.child.return = node;
- node = node.child;
- continue;
- }
- if (node === row) {
- return null;
- }
- while (node.sibling === null) {
- if (node.return === null || node.return === row) {
- return null;
- }
- node = node.return;
- }
- node.sibling.return = node.return;
- node = node.sibling;
- }
- return null;
- }
- var NoFlags$1 =
- /* */
- 0; // Represents whether effect should fire.
- var HasEffect =
- /* */
- 1; // Represents the phase in which the effect (not the clean-up) fires.
- var Insertion =
- /* */
- 2;
- var Layout =
- /* */
- 4;
- var Passive$1 =
- /* */
- 8;
- // and should be reset before starting a new render.
- // This tracks which mutable sources need to be reset after a render.
- var workInProgressSources = [];
- function resetWorkInProgressVersions() {
- for (var i = 0; i < workInProgressSources.length; i++) {
- var mutableSource = workInProgressSources[i];
- {
- mutableSource._workInProgressVersionPrimary = null;
- }
- }
- workInProgressSources.length = 0;
- }
- // This ensures that the version used for server rendering matches the one
- // that is eventually read during hydration.
- // If they don't match there's a potential tear and a full deopt render is required.
- function registerMutableSourceForHydration(root, mutableSource) {
- var getVersion = mutableSource._getVersion;
- var version = getVersion(mutableSource._source); // TODO Clear this data once all pending hydration work is finished.
- // Retaining it forever may interfere with GC.
- if (root.mutableSourceEagerHydrationData == null) {
- root.mutableSourceEagerHydrationData = [mutableSource, version];
- } else {
- root.mutableSourceEagerHydrationData.push(mutableSource, version);
- }
- }
- var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher,
- ReactCurrentBatchConfig$2 = ReactSharedInternals.ReactCurrentBatchConfig;
- var didWarnAboutMismatchedHooksForComponent;
- var didWarnUncachedGetSnapshot;
- {
- didWarnAboutMismatchedHooksForComponent = new Set();
- }
- // These are set right before calling the component.
- var renderLanes = NoLanes; // The work-in-progress fiber. I've named it differently to distinguish it from
- // the work-in-progress hook.
- var currentlyRenderingFiber$1 = null; // Hooks are stored as a linked list on the fiber's memoizedState field. The
- // current hook list is the list that belongs to the current fiber. The
- // work-in-progress hook list is a new list that will be added to the
- // work-in-progress fiber.
- var currentHook = null;
- var workInProgressHook = null; // Whether an update was scheduled at any point during the render phase. This
- // does not get reset if we do another render pass; only when we're completely
- // finished evaluating this component. This is an optimization so we know
- // whether we need to clear render phase updates after a throw.
- var didScheduleRenderPhaseUpdate = false; // Where an update was scheduled only during the current render pass. This
- // gets reset after each attempt.
- // TODO: Maybe there's some way to consolidate this with
- // `didScheduleRenderPhaseUpdate`. Or with `numberOfReRenders`.
- var didScheduleRenderPhaseUpdateDuringThisPass = false; // Counts the number of useId hooks in this component.
- var localIdCounter = 0; // Used for ids that are generated completely client-side (i.e. not during
- // hydration). This counter is global, so client ids are not stable across
- // render attempts.
- var globalClientIdCounter = 0;
- var RE_RENDER_LIMIT = 25; // In DEV, this is the name of the currently executing primitive hook
- var currentHookNameInDev = null; // In DEV, this list ensures that hooks are called in the same order between renders.
- // The list stores the order of hooks used during the initial render (mount).
- // Subsequent renders (updates) reference this list.
- var hookTypesDev = null;
- var hookTypesUpdateIndexDev = -1; // In DEV, this tracks whether currently rendering component needs to ignore
- // the dependencies for Hooks that need them (e.g. useEffect or useMemo).
- // When true, such Hooks will always be "remounted". Only used during hot reload.
- var ignorePreviousDependencies = false;
- function mountHookTypesDev() {
- {
- var hookName = currentHookNameInDev;
- if (hookTypesDev === null) {
- hookTypesDev = [hookName];
- } else {
- hookTypesDev.push(hookName);
- }
- }
- }
- function updateHookTypesDev() {
- {
- var hookName = currentHookNameInDev;
- if (hookTypesDev !== null) {
- hookTypesUpdateIndexDev++;
- if (hookTypesDev[hookTypesUpdateIndexDev] !== hookName) {
- warnOnHookMismatchInDev(hookName);
- }
- }
- }
- }
- function checkDepsAreArrayDev(deps) {
- {
- if (deps !== undefined && deps !== null && !isArray(deps)) {
- // Verify deps, but only on mount to avoid extra checks.
- // It's unlikely their type would change as usually you define them inline.
- error('%s received a final argument that is not an array (instead, received `%s`). When ' + 'specified, the final argument must be an array.', currentHookNameInDev, typeof deps);
- }
- }
- }
- function warnOnHookMismatchInDev(currentHookName) {
- {
- var componentName = getComponentNameFromFiber(currentlyRenderingFiber$1);
- if (!didWarnAboutMismatchedHooksForComponent.has(componentName)) {
- didWarnAboutMismatchedHooksForComponent.add(componentName);
- if (hookTypesDev !== null) {
- var table = '';
- var secondColumnStart = 30;
- for (var i = 0; i <= hookTypesUpdateIndexDev; i++) {
- var oldHookName = hookTypesDev[i];
- var newHookName = i === hookTypesUpdateIndexDev ? currentHookName : oldHookName;
- var row = i + 1 + ". " + oldHookName; // Extra space so second column lines up
- // lol @ IE not supporting String#repeat
- while (row.length < secondColumnStart) {
- row += ' ';
- }
- row += newHookName + '\n';
- table += row;
- }
- error('React has detected a change in the order of Hooks called by %s. ' + 'This will lead to bugs and errors if not fixed. ' + 'For more information, read the Rules of Hooks: https://reactjs.org/link/rules-of-hooks\n\n' + ' Previous render Next render\n' + ' ------------------------------------------------------\n' + '%s' + ' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n', componentName, table);
- }
- }
- }
- }
- function throwInvalidHookError() {
- throw new Error('Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' + ' one of the following reasons:\n' + '1. You might have mismatching versions of React and the renderer (such as React DOM)\n' + '2. You might be breaking the Rules of Hooks\n' + '3. You might have more than one copy of React in the same app\n' + 'See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.');
- }
- function areHookInputsEqual(nextDeps, prevDeps) {
- {
- if (ignorePreviousDependencies) {
- // Only true when this component is being hot reloaded.
- return false;
- }
- }
- if (prevDeps === null) {
- {
- error('%s received a final argument during this render, but not during ' + 'the previous render. Even though the final argument is optional, ' + 'its type cannot change between renders.', currentHookNameInDev);
- }
- return false;
- }
- {
- // Don't bother comparing lengths in prod because these arrays should be
- // passed inline.
- if (nextDeps.length !== prevDeps.length) {
- error('The final argument passed to %s changed size between renders. The ' + 'order and size of this array must remain constant.\n\n' + 'Previous: %s\n' + 'Incoming: %s', currentHookNameInDev, "[" + prevDeps.join(', ') + "]", "[" + nextDeps.join(', ') + "]");
- }
- }
- for (var i = 0; i < prevDeps.length && i < nextDeps.length; i++) {
- if (objectIs(nextDeps[i], prevDeps[i])) {
- continue;
- }
- return false;
- }
- return true;
- }
- function renderWithHooks(current, workInProgress, Component, props, secondArg, nextRenderLanes) {
- renderLanes = nextRenderLanes;
- currentlyRenderingFiber$1 = workInProgress;
- {
- hookTypesDev = current !== null ? current._debugHookTypes : null;
- hookTypesUpdateIndexDev = -1; // Used for hot reloading:
- ignorePreviousDependencies = current !== null && current.type !== workInProgress.type;
- }
- workInProgress.memoizedState = null;
- workInProgress.updateQueue = null;
- workInProgress.lanes = NoLanes; // The following should have already been reset
- // currentHook = null;
- // workInProgressHook = null;
- // didScheduleRenderPhaseUpdate = false;
- // localIdCounter = 0;
- // TODO Warn if no hooks are used at all during mount, then some are used during update.
- // Currently we will identify the update render as a mount because memoizedState === null.
- // This is tricky because it's valid for certain types of components (e.g. React.lazy)
- // Using memoizedState to differentiate between mount/update only works if at least one stateful hook is used.
- // Non-stateful hooks (e.g. context) don't get added to memoizedState,
- // so memoizedState would be null during updates and mounts.
- {
- if (current !== null && current.memoizedState !== null) {
- ReactCurrentDispatcher$1.current = HooksDispatcherOnUpdateInDEV;
- } else if (hookTypesDev !== null) {
- // This dispatcher handles an edge case where a component is updating,
- // but no stateful hooks have been used.
- // We want to match the production code behavior (which will use HooksDispatcherOnMount),
- // but with the extra DEV validation to ensure hooks ordering hasn't changed.
- // This dispatcher does that.
- ReactCurrentDispatcher$1.current = HooksDispatcherOnMountWithHookTypesInDEV;
- } else {
- ReactCurrentDispatcher$1.current = HooksDispatcherOnMountInDEV;
- }
- }
- var children = Component(props, secondArg); // Check if there was a render phase update
- if (didScheduleRenderPhaseUpdateDuringThisPass) {
- // Keep rendering in a loop for as long as render phase updates continue to
- // be scheduled. Use a counter to prevent infinite loops.
- var numberOfReRenders = 0;
- do {
- didScheduleRenderPhaseUpdateDuringThisPass = false;
- localIdCounter = 0;
- if (numberOfReRenders >= RE_RENDER_LIMIT) {
- throw new Error('Too many re-renders. React limits the number of renders to prevent ' + 'an infinite loop.');
- }
- numberOfReRenders += 1;
- {
- // Even when hot reloading, allow dependencies to stabilize
- // after first render to prevent infinite render phase updates.
- ignorePreviousDependencies = false;
- } // Start over from the beginning of the list
- currentHook = null;
- workInProgressHook = null;
- workInProgress.updateQueue = null;
- {
- // Also validate hook order for cascading updates.
- hookTypesUpdateIndexDev = -1;
- }
- ReactCurrentDispatcher$1.current = HooksDispatcherOnRerenderInDEV;
- children = Component(props, secondArg);
- } while (didScheduleRenderPhaseUpdateDuringThisPass);
- } // We can assume the previous dispatcher is always this one, since we set it
- // at the beginning of the render phase and there's no re-entrance.
- ReactCurrentDispatcher$1.current = ContextOnlyDispatcher;
- {
- workInProgress._debugHookTypes = hookTypesDev;
- } // This check uses currentHook so that it works the same in DEV and prod bundles.
- // hookTypesDev could catch more cases (e.g. context) but only in DEV bundles.
- var didRenderTooFewHooks = currentHook !== null && currentHook.next !== null;
- renderLanes = NoLanes;
- currentlyRenderingFiber$1 = null;
- currentHook = null;
- workInProgressHook = null;
- {
- currentHookNameInDev = null;
- hookTypesDev = null;
- hookTypesUpdateIndexDev = -1; // Confirm that a static flag was not added or removed since the last
- // render. If this fires, it suggests that we incorrectly reset the static
- // flags in some other part of the codebase. This has happened before, for
- // example, in the SuspenseList implementation.
- if (current !== null && (current.flags & StaticMask) !== (workInProgress.flags & StaticMask) && // Disable this warning in legacy mode, because legacy Suspense is weird
- // and creates false positives. To make this work in legacy mode, we'd
- // need to mark fibers that commit in an incomplete state, somehow. For
- // now I'll disable the warning that most of the bugs that would trigger
- // it are either exclusive to concurrent mode or exist in both.
- (current.mode & ConcurrentMode) !== NoMode) {
- error('Internal React error: Expected static flag was missing. Please ' + 'notify the React team.');
- }
- }
- didScheduleRenderPhaseUpdate = false; // This is reset by checkDidRenderIdHook
- // localIdCounter = 0;
- if (didRenderTooFewHooks) {
- throw new Error('Rendered fewer hooks than expected. This may be caused by an accidental ' + 'early return statement.');
- }
- return children;
- }
- function checkDidRenderIdHook() {
- // This should be called immediately after every renderWithHooks call.
- // Conceptually, it's part of the return value of renderWithHooks; it's only a
- // separate function to avoid using an array tuple.
- var didRenderIdHook = localIdCounter !== 0;
- localIdCounter = 0;
- return didRenderIdHook;
- }
- function bailoutHooks(current, workInProgress, lanes) {
- workInProgress.updateQueue = current.updateQueue; // TODO: Don't need to reset the flags here, because they're reset in the
- // complete phase (bubbleProperties).
- if ((workInProgress.mode & StrictEffectsMode) !== NoMode) {
- workInProgress.flags &= ~(MountPassiveDev | MountLayoutDev | Passive | Update);
- } else {
- workInProgress.flags &= ~(Passive | Update);
- }
- current.lanes = removeLanes(current.lanes, lanes);
- }
- function resetHooksAfterThrow() {
- // We can assume the previous dispatcher is always this one, since we set it
- // at the beginning of the render phase and there's no re-entrance.
- ReactCurrentDispatcher$1.current = ContextOnlyDispatcher;
- if (didScheduleRenderPhaseUpdate) {
- // There were render phase updates. These are only valid for this render
- // phase, which we are now aborting. Remove the updates from the queues so
- // they do not persist to the next render. Do not remove updates from hooks
- // that weren't processed.
- //
- // Only reset the updates from the queue if it has a clone. If it does
- // not have a clone, that means it wasn't processed, and the updates were
- // scheduled before we entered the render phase.
- var hook = currentlyRenderingFiber$1.memoizedState;
- while (hook !== null) {
- var queue = hook.queue;
- if (queue !== null) {
- queue.pending = null;
- }
- hook = hook.next;
- }
- didScheduleRenderPhaseUpdate = false;
- }
- renderLanes = NoLanes;
- currentlyRenderingFiber$1 = null;
- currentHook = null;
- workInProgressHook = null;
- {
- hookTypesDev = null;
- hookTypesUpdateIndexDev = -1;
- currentHookNameInDev = null;
- isUpdatingOpaqueValueInRenderPhase = false;
- }
- didScheduleRenderPhaseUpdateDuringThisPass = false;
- localIdCounter = 0;
- }
- function mountWorkInProgressHook() {
- var hook = {
- memoizedState: null,
- baseState: null,
- baseQueue: null,
- queue: null,
- next: null
- };
- if (workInProgressHook === null) {
- // This is the first hook in the list
- currentlyRenderingFiber$1.memoizedState = workInProgressHook = hook;
- } else {
- // Append to the end of the list
- workInProgressHook = workInProgressHook.next = hook;
- }
- return workInProgressHook;
- }
- function updateWorkInProgressHook() {
- // This function is used both for updates and for re-renders triggered by a
- // render phase update. It assumes there is either a current hook we can
- // clone, or a work-in-progress hook from a previous render pass that we can
- // use as a base. When we reach the end of the base list, we must switch to
- // the dispatcher used for mounts.
- var nextCurrentHook;
- if (currentHook === null) {
- var current = currentlyRenderingFiber$1.alternate;
- if (current !== null) {
- nextCurrentHook = current.memoizedState;
- } else {
- nextCurrentHook = null;
- }
- } else {
- nextCurrentHook = currentHook.next;
- }
- var nextWorkInProgressHook;
- if (workInProgressHook === null) {
- nextWorkInProgressHook = currentlyRenderingFiber$1.memoizedState;
- } else {
- nextWorkInProgressHook = workInProgressHook.next;
- }
- if (nextWorkInProgressHook !== null) {
- // There's already a work-in-progress. Reuse it.
- workInProgressHook = nextWorkInProgressHook;
- nextWorkInProgressHook = workInProgressHook.next;
- currentHook = nextCurrentHook;
- } else {
- // Clone from the current hook.
- if (nextCurrentHook === null) {
- throw new Error('Rendered more hooks than during the previous render.');
- }
- currentHook = nextCurrentHook;
- var newHook = {
- memoizedState: currentHook.memoizedState,
- baseState: currentHook.baseState,
- baseQueue: currentHook.baseQueue,
- queue: currentHook.queue,
- next: null
- };
- if (workInProgressHook === null) {
- // This is the first hook in the list.
- currentlyRenderingFiber$1.memoizedState = workInProgressHook = newHook;
- } else {
- // Append to the end of the list.
- workInProgressHook = workInProgressHook.next = newHook;
- }
- }
- return workInProgressHook;
- }
- function createFunctionComponentUpdateQueue() {
- return {
- lastEffect: null,
- stores: null
- };
- }
- function basicStateReducer(state, action) {
- // $FlowFixMe: Flow doesn't like mixed types
- return typeof action === 'function' ? action(state) : action;
- }
- function mountReducer(reducer, initialArg, init) {
- var hook = mountWorkInProgressHook();
- var initialState;
- if (init !== undefined) {
- initialState = init(initialArg);
- } else {
- initialState = initialArg;
- }
- hook.memoizedState = hook.baseState = initialState;
- var queue = {
- pending: null,
- interleaved: null,
- lanes: NoLanes,
- dispatch: null,
- lastRenderedReducer: reducer,
- lastRenderedState: initialState
- };
- hook.queue = queue;
- var dispatch = queue.dispatch = dispatchReducerAction.bind(null, currentlyRenderingFiber$1, queue);
- return [hook.memoizedState, dispatch];
- }
- function updateReducer(reducer, initialArg, init) {
- var hook = updateWorkInProgressHook();
- var queue = hook.queue;
- if (queue === null) {
- throw new Error('Should have a queue. This is likely a bug in React. Please file an issue.');
- }
- queue.lastRenderedReducer = reducer;
- var current = currentHook; // The last rebase update that is NOT part of the base state.
- var baseQueue = current.baseQueue; // The last pending update that hasn't been processed yet.
- var pendingQueue = queue.pending;
- if (pendingQueue !== null) {
- // We have new updates that haven't been processed yet.
- // We'll add them to the base queue.
- if (baseQueue !== null) {
- // Merge the pending queue and the base queue.
- var baseFirst = baseQueue.next;
- var pendingFirst = pendingQueue.next;
- baseQueue.next = pendingFirst;
- pendingQueue.next = baseFirst;
- }
- {
- if (current.baseQueue !== baseQueue) {
- // Internal invariant that should never happen, but feasibly could in
- // the future if we implement resuming, or some form of that.
- error('Internal error: Expected work-in-progress queue to be a clone. ' + 'This is a bug in React.');
- }
- }
- current.baseQueue = baseQueue = pendingQueue;
- queue.pending = null;
- }
- if (baseQueue !== null) {
- // We have a queue to process.
- var first = baseQueue.next;
- var newState = current.baseState;
- var newBaseState = null;
- var newBaseQueueFirst = null;
- var newBaseQueueLast = null;
- var update = first;
- do {
- var updateLane = update.lane;
- if (!isSubsetOfLanes(renderLanes, updateLane)) {
- // Priority is insufficient. Skip this update. If this is the first
- // skipped update, the previous update/state is the new base
- // update/state.
- var clone = {
- lane: updateLane,
- action: update.action,
- hasEagerState: update.hasEagerState,
- eagerState: update.eagerState,
- next: null
- };
- if (newBaseQueueLast === null) {
- newBaseQueueFirst = newBaseQueueLast = clone;
- newBaseState = newState;
- } else {
- newBaseQueueLast = newBaseQueueLast.next = clone;
- } // Update the remaining priority in the queue.
- // TODO: Don't need to accumulate this. Instead, we can remove
- // renderLanes from the original lanes.
- currentlyRenderingFiber$1.lanes = mergeLanes(currentlyRenderingFiber$1.lanes, updateLane);
- markSkippedUpdateLanes(updateLane);
- } else {
- // This update does have sufficient priority.
- if (newBaseQueueLast !== null) {
- var _clone = {
- // This update is going to be committed so we never want uncommit
- // it. Using NoLane works because 0 is a subset of all bitmasks, so
- // this will never be skipped by the check above.
- lane: NoLane,
- action: update.action,
- hasEagerState: update.hasEagerState,
- eagerState: update.eagerState,
- next: null
- };
- newBaseQueueLast = newBaseQueueLast.next = _clone;
- } // Process this update.
- if (update.hasEagerState) {
- // If this update is a state update (not a reducer) and was processed eagerly,
- // we can use the eagerly computed state
- newState = update.eagerState;
- } else {
- var action = update.action;
- newState = reducer(newState, action);
- }
- }
- update = update.next;
- } while (update !== null && update !== first);
- if (newBaseQueueLast === null) {
- newBaseState = newState;
- } else {
- newBaseQueueLast.next = newBaseQueueFirst;
- } // Mark that the fiber performed work, but only if the new state is
- // different from the current state.
- if (!objectIs(newState, hook.memoizedState)) {
- markWorkInProgressReceivedUpdate();
- }
- hook.memoizedState = newState;
- hook.baseState = newBaseState;
- hook.baseQueue = newBaseQueueLast;
- queue.lastRenderedState = newState;
- } // Interleaved updates are stored on a separate queue. We aren't going to
- // process them during this render, but we do need to track which lanes
- // are remaining.
- var lastInterleaved = queue.interleaved;
- if (lastInterleaved !== null) {
- var interleaved = lastInterleaved;
- do {
- var interleavedLane = interleaved.lane;
- currentlyRenderingFiber$1.lanes = mergeLanes(currentlyRenderingFiber$1.lanes, interleavedLane);
- markSkippedUpdateLanes(interleavedLane);
- interleaved = interleaved.next;
- } while (interleaved !== lastInterleaved);
- } else if (baseQueue === null) {
- // `queue.lanes` is used for entangling transitions. We can set it back to
- // zero once the queue is empty.
- queue.lanes = NoLanes;
- }
- var dispatch = queue.dispatch;
- return [hook.memoizedState, dispatch];
- }
- function rerenderReducer(reducer, initialArg, init) {
- var hook = updateWorkInProgressHook();
- var queue = hook.queue;
- if (queue === null) {
- throw new Error('Should have a queue. This is likely a bug in React. Please file an issue.');
- }
- queue.lastRenderedReducer = reducer; // This is a re-render. Apply the new render phase updates to the previous
- // work-in-progress hook.
- var dispatch = queue.dispatch;
- var lastRenderPhaseUpdate = queue.pending;
- var newState = hook.memoizedState;
- if (lastRenderPhaseUpdate !== null) {
- // The queue doesn't persist past this render pass.
- queue.pending = null;
- var firstRenderPhaseUpdate = lastRenderPhaseUpdate.next;
- var update = firstRenderPhaseUpdate;
- do {
- // Process this render phase update. We don't have to check the
- // priority because it will always be the same as the current
- // render's.
- var action = update.action;
- newState = reducer(newState, action);
- update = update.next;
- } while (update !== firstRenderPhaseUpdate); // Mark that the fiber performed work, but only if the new state is
- // different from the current state.
- if (!objectIs(newState, hook.memoizedState)) {
- markWorkInProgressReceivedUpdate();
- }
- hook.memoizedState = newState; // Don't persist the state accumulated from the render phase updates to
- // the base state unless the queue is empty.
- // TODO: Not sure if this is the desired semantics, but it's what we
- // do for gDSFP. I can't remember why.
- if (hook.baseQueue === null) {
- hook.baseState = newState;
- }
- queue.lastRenderedState = newState;
- }
- return [newState, dispatch];
- }
- function mountMutableSource(source, getSnapshot, subscribe) {
- {
- return undefined;
- }
- }
- function updateMutableSource(source, getSnapshot, subscribe) {
- {
- return undefined;
- }
- }
- function mountSyncExternalStore(subscribe, getSnapshot, getServerSnapshot) {
- var fiber = currentlyRenderingFiber$1;
- var hook = mountWorkInProgressHook();
- var nextSnapshot;
- var isHydrating = getIsHydrating();
- if (isHydrating) {
- if (getServerSnapshot === undefined) {
- throw new Error('Missing getServerSnapshot, which is required for ' + 'server-rendered content. Will revert to client rendering.');
- }
- nextSnapshot = getServerSnapshot();
- {
- if (!didWarnUncachedGetSnapshot) {
- if (nextSnapshot !== getServerSnapshot()) {
- error('The result of getServerSnapshot should be cached to avoid an infinite loop');
- didWarnUncachedGetSnapshot = true;
- }
- }
- }
- } else {
- nextSnapshot = getSnapshot();
- {
- if (!didWarnUncachedGetSnapshot) {
- var cachedSnapshot = getSnapshot();
- if (!objectIs(nextSnapshot, cachedSnapshot)) {
- error('The result of getSnapshot should be cached to avoid an infinite loop');
- didWarnUncachedGetSnapshot = true;
- }
- }
- } // Unless we're rendering a blocking lane, schedule a consistency check.
- // Right before committing, we will walk the tree and check if any of the
- // stores were mutated.
- //
- // We won't do this if we're hydrating server-rendered content, because if
- // the content is stale, it's already visible anyway. Instead we'll patch
- // it up in a passive effect.
- var root = getWorkInProgressRoot();
- if (root === null) {
- throw new Error('Expected a work-in-progress root. This is a bug in React. Please file an issue.');
- }
- if (!includesBlockingLane(root, renderLanes)) {
- pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot);
- }
- } // Read the current snapshot from the store on every render. This breaks the
- // normal rules of React, and only works because store updates are
- // always synchronous.
- hook.memoizedState = nextSnapshot;
- var inst = {
- value: nextSnapshot,
- getSnapshot: getSnapshot
- };
- hook.queue = inst; // Schedule an effect to subscribe to the store.
- mountEffect(subscribeToStore.bind(null, fiber, inst, subscribe), [subscribe]); // Schedule an effect to update the mutable instance fields. We will update
- // this whenever subscribe, getSnapshot, or value changes. Because there's no
- // clean-up function, and we track the deps correctly, we can call pushEffect
- // directly, without storing any additional state. For the same reason, we
- // don't need to set a static flag, either.
- // TODO: We can move this to the passive phase once we add a pre-commit
- // consistency check. See the next comment.
- fiber.flags |= Passive;
- pushEffect(HasEffect | Passive$1, updateStoreInstance.bind(null, fiber, inst, nextSnapshot, getSnapshot), undefined, null);
- return nextSnapshot;
- }
- function updateSyncExternalStore(subscribe, getSnapshot, getServerSnapshot) {
- var fiber = currentlyRenderingFiber$1;
- var hook = updateWorkInProgressHook(); // Read the current snapshot from the store on every render. This breaks the
- // normal rules of React, and only works because store updates are
- // always synchronous.
- var nextSnapshot = getSnapshot();
- {
- if (!didWarnUncachedGetSnapshot) {
- var cachedSnapshot = getSnapshot();
- if (!objectIs(nextSnapshot, cachedSnapshot)) {
- error('The result of getSnapshot should be cached to avoid an infinite loop');
- didWarnUncachedGetSnapshot = true;
- }
- }
- }
- var prevSnapshot = hook.memoizedState;
- var snapshotChanged = !objectIs(prevSnapshot, nextSnapshot);
- if (snapshotChanged) {
- hook.memoizedState = nextSnapshot;
- markWorkInProgressReceivedUpdate();
- }
- var inst = hook.queue;
- updateEffect(subscribeToStore.bind(null, fiber, inst, subscribe), [subscribe]); // Whenever getSnapshot or subscribe changes, we need to check in the
- // commit phase if there was an interleaved mutation. In concurrent mode
- // this can happen all the time, but even in synchronous mode, an earlier
- // effect may have mutated the store.
- if (inst.getSnapshot !== getSnapshot || snapshotChanged || // Check if the susbcribe function changed. We can save some memory by
- // checking whether we scheduled a subscription effect above.
- workInProgressHook !== null && workInProgressHook.memoizedState.tag & HasEffect) {
- fiber.flags |= Passive;
- pushEffect(HasEffect | Passive$1, updateStoreInstance.bind(null, fiber, inst, nextSnapshot, getSnapshot), undefined, null); // Unless we're rendering a blocking lane, schedule a consistency check.
- // Right before committing, we will walk the tree and check if any of the
- // stores were mutated.
- var root = getWorkInProgressRoot();
- if (root === null) {
- throw new Error('Expected a work-in-progress root. This is a bug in React. Please file an issue.');
- }
- if (!includesBlockingLane(root, renderLanes)) {
- pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot);
- }
- }
- return nextSnapshot;
- }
- function pushStoreConsistencyCheck(fiber, getSnapshot, renderedSnapshot) {
- fiber.flags |= StoreConsistency;
- var check = {
- getSnapshot: getSnapshot,
- value: renderedSnapshot
- };
- var componentUpdateQueue = currentlyRenderingFiber$1.updateQueue;
- if (componentUpdateQueue === null) {
- componentUpdateQueue = createFunctionComponentUpdateQueue();
- currentlyRenderingFiber$1.updateQueue = componentUpdateQueue;
- componentUpdateQueue.stores = [check];
- } else {
- var stores = componentUpdateQueue.stores;
- if (stores === null) {
- componentUpdateQueue.stores = [check];
- } else {
- stores.push(check);
- }
- }
- }
- function updateStoreInstance(fiber, inst, nextSnapshot, getSnapshot) {
- // These are updated in the passive phase
- inst.value = nextSnapshot;
- inst.getSnapshot = getSnapshot; // Something may have been mutated in between render and commit. This could
- // have been in an event that fired before the passive effects, or it could
- // have been in a layout effect. In that case, we would have used the old
- // snapsho and getSnapshot values to bail out. We need to check one more time.
- if (checkIfSnapshotChanged(inst)) {
- // Force a re-render.
- forceStoreRerender(fiber);
- }
- }
- function subscribeToStore(fiber, inst, subscribe) {
- var handleStoreChange = function () {
- // The store changed. Check if the snapshot changed since the last time we
- // read from the store.
- if (checkIfSnapshotChanged(inst)) {
- // Force a re-render.
- forceStoreRerender(fiber);
- }
- }; // Subscribe to the store and return a clean-up function.
- return subscribe(handleStoreChange);
- }
- function checkIfSnapshotChanged(inst) {
- var latestGetSnapshot = inst.getSnapshot;
- var prevValue = inst.value;
- try {
- var nextValue = latestGetSnapshot();
- return !objectIs(prevValue, nextValue);
- } catch (error) {
- return true;
- }
- }
- function forceStoreRerender(fiber) {
- var root = enqueueConcurrentRenderForLane(fiber, SyncLane);
- if (root !== null) {
- scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp);
- }
- }
- function mountState(initialState) {
- var hook = mountWorkInProgressHook();
- if (typeof initialState === 'function') {
- // $FlowFixMe: Flow doesn't like mixed types
- initialState = initialState();
- }
- hook.memoizedState = hook.baseState = initialState;
- var queue = {
- pending: null,
- interleaved: null,
- lanes: NoLanes,
- dispatch: null,
- lastRenderedReducer: basicStateReducer,
- lastRenderedState: initialState
- };
- hook.queue = queue;
- var dispatch = queue.dispatch = dispatchSetState.bind(null, currentlyRenderingFiber$1, queue);
- return [hook.memoizedState, dispatch];
- }
- function updateState(initialState) {
- return updateReducer(basicStateReducer);
- }
- function rerenderState(initialState) {
- return rerenderReducer(basicStateReducer);
- }
- function pushEffect(tag, create, destroy, deps) {
- var effect = {
- tag: tag,
- create: create,
- destroy: destroy,
- deps: deps,
- // Circular
- next: null
- };
- var componentUpdateQueue = currentlyRenderingFiber$1.updateQueue;
- if (componentUpdateQueue === null) {
- componentUpdateQueue = createFunctionComponentUpdateQueue();
- currentlyRenderingFiber$1.updateQueue = componentUpdateQueue;
- componentUpdateQueue.lastEffect = effect.next = effect;
- } else {
- var lastEffect = componentUpdateQueue.lastEffect;
- if (lastEffect === null) {
- componentUpdateQueue.lastEffect = effect.next = effect;
- } else {
- var firstEffect = lastEffect.next;
- lastEffect.next = effect;
- effect.next = firstEffect;
- componentUpdateQueue.lastEffect = effect;
- }
- }
- return effect;
- }
- function mountRef(initialValue) {
- var hook = mountWorkInProgressHook();
- {
- var _ref2 = {
- current: initialValue
- };
- hook.memoizedState = _ref2;
- return _ref2;
- }
- }
- function updateRef(initialValue) {
- var hook = updateWorkInProgressHook();
- return hook.memoizedState;
- }
- function mountEffectImpl(fiberFlags, hookFlags, create, deps) {
- var hook = mountWorkInProgressHook();
- var nextDeps = deps === undefined ? null : deps;
- currentlyRenderingFiber$1.flags |= fiberFlags;
- hook.memoizedState = pushEffect(HasEffect | hookFlags, create, undefined, nextDeps);
- }
- function updateEffectImpl(fiberFlags, hookFlags, create, deps) {
- var hook = updateWorkInProgressHook();
- var nextDeps = deps === undefined ? null : deps;
- var destroy = undefined;
- if (currentHook !== null) {
- var prevEffect = currentHook.memoizedState;
- destroy = prevEffect.destroy;
- if (nextDeps !== null) {
- var prevDeps = prevEffect.deps;
- if (areHookInputsEqual(nextDeps, prevDeps)) {
- hook.memoizedState = pushEffect(hookFlags, create, destroy, nextDeps);
- return;
- }
- }
- }
- currentlyRenderingFiber$1.flags |= fiberFlags;
- hook.memoizedState = pushEffect(HasEffect | hookFlags, create, destroy, nextDeps);
- }
- function mountEffect(create, deps) {
- if ((currentlyRenderingFiber$1.mode & StrictEffectsMode) !== NoMode) {
- return mountEffectImpl(MountPassiveDev | Passive | PassiveStatic, Passive$1, create, deps);
- } else {
- return mountEffectImpl(Passive | PassiveStatic, Passive$1, create, deps);
- }
- }
- function updateEffect(create, deps) {
- return updateEffectImpl(Passive, Passive$1, create, deps);
- }
- function mountInsertionEffect(create, deps) {
- return mountEffectImpl(Update, Insertion, create, deps);
- }
- function updateInsertionEffect(create, deps) {
- return updateEffectImpl(Update, Insertion, create, deps);
- }
- function mountLayoutEffect(create, deps) {
- var fiberFlags = Update;
- {
- fiberFlags |= LayoutStatic;
- }
- if ((currentlyRenderingFiber$1.mode & StrictEffectsMode) !== NoMode) {
- fiberFlags |= MountLayoutDev;
- }
- return mountEffectImpl(fiberFlags, Layout, create, deps);
- }
- function updateLayoutEffect(create, deps) {
- return updateEffectImpl(Update, Layout, create, deps);
- }
- function imperativeHandleEffect(create, ref) {
- if (typeof ref === 'function') {
- var refCallback = ref;
- var _inst = create();
- refCallback(_inst);
- return function () {
- refCallback(null);
- };
- } else if (ref !== null && ref !== undefined) {
- var refObject = ref;
- {
- if (!refObject.hasOwnProperty('current')) {
- error('Expected useImperativeHandle() first argument to either be a ' + 'ref callback or React.createRef() object. Instead received: %s.', 'an object with keys {' + Object.keys(refObject).join(', ') + '}');
- }
- }
- var _inst2 = create();
- refObject.current = _inst2;
- return function () {
- refObject.current = null;
- };
- }
- }
- function mountImperativeHandle(ref, create, deps) {
- {
- if (typeof create !== 'function') {
- error('Expected useImperativeHandle() second argument to be a function ' + 'that creates a handle. Instead received: %s.', create !== null ? typeof create : 'null');
- }
- } // TODO: If deps are provided, should we skip comparing the ref itself?
- var effectDeps = deps !== null && deps !== undefined ? deps.concat([ref]) : null;
- var fiberFlags = Update;
- {
- fiberFlags |= LayoutStatic;
- }
- if ((currentlyRenderingFiber$1.mode & StrictEffectsMode) !== NoMode) {
- fiberFlags |= MountLayoutDev;
- }
- return mountEffectImpl(fiberFlags, Layout, imperativeHandleEffect.bind(null, create, ref), effectDeps);
- }
- function updateImperativeHandle(ref, create, deps) {
- {
- if (typeof create !== 'function') {
- error('Expected useImperativeHandle() second argument to be a function ' + 'that creates a handle. Instead received: %s.', create !== null ? typeof create : 'null');
- }
- } // TODO: If deps are provided, should we skip comparing the ref itself?
- var effectDeps = deps !== null && deps !== undefined ? deps.concat([ref]) : null;
- return updateEffectImpl(Update, Layout, imperativeHandleEffect.bind(null, create, ref), effectDeps);
- }
- function mountDebugValue(value, formatterFn) {// This hook is normally a no-op.
- // The react-debug-hooks package injects its own implementation
- // so that e.g. DevTools can display custom hook values.
- }
- var updateDebugValue = mountDebugValue;
- function mountCallback(callback, deps) {
- var hook = mountWorkInProgressHook();
- var nextDeps = deps === undefined ? null : deps;
- hook.memoizedState = [callback, nextDeps];
- return callback;
- }
- function updateCallback(callback, deps) {
- var hook = updateWorkInProgressHook();
- var nextDeps = deps === undefined ? null : deps;
- var prevState = hook.memoizedState;
- if (prevState !== null) {
- if (nextDeps !== null) {
- var prevDeps = prevState[1];
- if (areHookInputsEqual(nextDeps, prevDeps)) {
- return prevState[0];
- }
- }
- }
- hook.memoizedState = [callback, nextDeps];
- return callback;
- }
- function mountMemo(nextCreate, deps) {
- var hook = mountWorkInProgressHook();
- var nextDeps = deps === undefined ? null : deps;
- var nextValue = nextCreate();
- hook.memoizedState = [nextValue, nextDeps];
- return nextValue;
- }
- function updateMemo(nextCreate, deps) {
- var hook = updateWorkInProgressHook();
- var nextDeps = deps === undefined ? null : deps;
- var prevState = hook.memoizedState;
- if (prevState !== null) {
- // Assume these are defined. If they're not, areHookInputsEqual will warn.
- if (nextDeps !== null) {
- var prevDeps = prevState[1];
- if (areHookInputsEqual(nextDeps, prevDeps)) {
- return prevState[0];
- }
- }
- }
- var nextValue = nextCreate();
- hook.memoizedState = [nextValue, nextDeps];
- return nextValue;
- }
- function mountDeferredValue(value) {
- var hook = mountWorkInProgressHook();
- hook.memoizedState = value;
- return value;
- }
- function updateDeferredValue(value) {
- var hook = updateWorkInProgressHook();
- var resolvedCurrentHook = currentHook;
- var prevValue = resolvedCurrentHook.memoizedState;
- return updateDeferredValueImpl(hook, prevValue, value);
- }
- function rerenderDeferredValue(value) {
- var hook = updateWorkInProgressHook();
- if (currentHook === null) {
- // This is a rerender during a mount.
- hook.memoizedState = value;
- return value;
- } else {
- // This is a rerender during an update.
- var prevValue = currentHook.memoizedState;
- return updateDeferredValueImpl(hook, prevValue, value);
- }
- }
- function updateDeferredValueImpl(hook, prevValue, value) {
- var shouldDeferValue = !includesOnlyNonUrgentLanes(renderLanes);
- if (shouldDeferValue) {
- // This is an urgent update. If the value has changed, keep using the
- // previous value and spawn a deferred render to update it later.
- if (!objectIs(value, prevValue)) {
- // Schedule a deferred render
- var deferredLane = claimNextTransitionLane();
- currentlyRenderingFiber$1.lanes = mergeLanes(currentlyRenderingFiber$1.lanes, deferredLane);
- markSkippedUpdateLanes(deferredLane); // Set this to true to indicate that the rendered value is inconsistent
- // from the latest value. The name "baseState" doesn't really match how we
- // use it because we're reusing a state hook field instead of creating a
- // new one.
- hook.baseState = true;
- } // Reuse the previous value
- return prevValue;
- } else {
- // This is not an urgent update, so we can use the latest value regardless
- // of what it is. No need to defer it.
- // However, if we're currently inside a spawned render, then we need to mark
- // this as an update to prevent the fiber from bailing out.
- //
- // `baseState` is true when the current value is different from the rendered
- // value. The name doesn't really match how we use it because we're reusing
- // a state hook field instead of creating a new one.
- if (hook.baseState) {
- // Flip this back to false.
- hook.baseState = false;
- markWorkInProgressReceivedUpdate();
- }
- hook.memoizedState = value;
- return value;
- }
- }
- function startTransition(setPending, callback, options) {
- var previousPriority = getCurrentUpdatePriority();
- setCurrentUpdatePriority(higherEventPriority(previousPriority, ContinuousEventPriority));
- setPending(true);
- var prevTransition = ReactCurrentBatchConfig$2.transition;
- ReactCurrentBatchConfig$2.transition = {};
- var currentTransition = ReactCurrentBatchConfig$2.transition;
- {
- ReactCurrentBatchConfig$2.transition._updatedFibers = new Set();
- }
- try {
- setPending(false);
- callback();
- } finally {
- setCurrentUpdatePriority(previousPriority);
- ReactCurrentBatchConfig$2.transition = prevTransition;
- {
- if (prevTransition === null && currentTransition._updatedFibers) {
- var updatedFibersCount = currentTransition._updatedFibers.size;
- if (updatedFibersCount > 10) {
- warn('Detected a large number of updates inside startTransition. ' + 'If this is due to a subscription please re-write it to use React provided hooks. ' + 'Otherwise concurrent mode guarantees are off the table.');
- }
- currentTransition._updatedFibers.clear();
- }
- }
- }
- }
- function mountTransition() {
- var _mountState = mountState(false),
- isPending = _mountState[0],
- setPending = _mountState[1]; // The `start` method never changes.
- var start = startTransition.bind(null, setPending);
- var hook = mountWorkInProgressHook();
- hook.memoizedState = start;
- return [isPending, start];
- }
- function updateTransition() {
- var _updateState = updateState(),
- isPending = _updateState[0];
- var hook = updateWorkInProgressHook();
- var start = hook.memoizedState;
- return [isPending, start];
- }
- function rerenderTransition() {
- var _rerenderState = rerenderState(),
- isPending = _rerenderState[0];
- var hook = updateWorkInProgressHook();
- var start = hook.memoizedState;
- return [isPending, start];
- }
- var isUpdatingOpaqueValueInRenderPhase = false;
- function getIsUpdatingOpaqueValueInRenderPhaseInDEV() {
- {
- return isUpdatingOpaqueValueInRenderPhase;
- }
- }
- function mountId() {
- var hook = mountWorkInProgressHook();
- var root = getWorkInProgressRoot(); // TODO: In Fizz, id generation is specific to each server config. Maybe we
- // should do this in Fiber, too? Deferring this decision for now because
- // there's no other place to store the prefix except for an internal field on
- // the public createRoot object, which the fiber tree does not currently have
- // a reference to.
- var identifierPrefix = root.identifierPrefix;
- var id;
- if (getIsHydrating()) {
- var treeId = getTreeId(); // Use a captial R prefix for server-generated ids.
- id = ':' + identifierPrefix + 'R' + treeId; // Unless this is the first id at this level, append a number at the end
- // that represents the position of this useId hook among all the useId
- // hooks for this fiber.
- var localId = localIdCounter++;
- if (localId > 0) {
- id += 'H' + localId.toString(32);
- }
- id += ':';
- } else {
- // Use a lowercase r prefix for client-generated ids.
- var globalClientId = globalClientIdCounter++;
- id = ':' + identifierPrefix + 'r' + globalClientId.toString(32) + ':';
- }
- hook.memoizedState = id;
- return id;
- }
- function updateId() {
- var hook = updateWorkInProgressHook();
- var id = hook.memoizedState;
- return id;
- }
- function dispatchReducerAction(fiber, queue, action) {
- {
- if (typeof arguments[3] === 'function') {
- error("State updates from the useState() and useReducer() Hooks don't support the " + 'second callback argument. To execute a side effect after ' + 'rendering, declare it in the component body with useEffect().');
- }
- }
- var lane = requestUpdateLane(fiber);
- var update = {
- lane: lane,
- action: action,
- hasEagerState: false,
- eagerState: null,
- next: null
- };
- if (isRenderPhaseUpdate(fiber)) {
- enqueueRenderPhaseUpdate(queue, update);
- } else {
- var root = enqueueConcurrentHookUpdate(fiber, queue, update, lane);
- if (root !== null) {
- var eventTime = requestEventTime();
- scheduleUpdateOnFiber(root, fiber, lane, eventTime);
- entangleTransitionUpdate(root, queue, lane);
- }
- }
- markUpdateInDevTools(fiber, lane);
- }
- function dispatchSetState(fiber, queue, action) {
- {
- if (typeof arguments[3] === 'function') {
- error("State updates from the useState() and useReducer() Hooks don't support the " + 'second callback argument. To execute a side effect after ' + 'rendering, declare it in the component body with useEffect().');
- }
- }
- var lane = requestUpdateLane(fiber);
- var update = {
- lane: lane,
- action: action,
- hasEagerState: false,
- eagerState: null,
- next: null
- };
- if (isRenderPhaseUpdate(fiber)) {
- enqueueRenderPhaseUpdate(queue, update);
- } else {
- var alternate = fiber.alternate;
- if (fiber.lanes === NoLanes && (alternate === null || alternate.lanes === NoLanes)) {
- // The queue is currently empty, which means we can eagerly compute the
- // next state before entering the render phase. If the new state is the
- // same as the current state, we may be able to bail out entirely.
- var lastRenderedReducer = queue.lastRenderedReducer;
- if (lastRenderedReducer !== null) {
- var prevDispatcher;
- {
- prevDispatcher = ReactCurrentDispatcher$1.current;
- ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV;
- }
- try {
- var currentState = queue.lastRenderedState;
- var eagerState = lastRenderedReducer(currentState, action); // Stash the eagerly computed state, and the reducer used to compute
- // it, on the update object. If the reducer hasn't changed by the
- // time we enter the render phase, then the eager state can be used
- // without calling the reducer again.
- update.hasEagerState = true;
- update.eagerState = eagerState;
- if (objectIs(eagerState, currentState)) {
- // Fast path. We can bail out without scheduling React to re-render.
- // It's still possible that we'll need to rebase this update later,
- // if the component re-renders for a different reason and by that
- // time the reducer has changed.
- // TODO: Do we still need to entangle transitions in this case?
- enqueueConcurrentHookUpdateAndEagerlyBailout(fiber, queue, update, lane);
- return;
- }
- } catch (error) {// Suppress the error. It will throw again in the render phase.
- } finally {
- {
- ReactCurrentDispatcher$1.current = prevDispatcher;
- }
- }
- }
- }
- var root = enqueueConcurrentHookUpdate(fiber, queue, update, lane);
- if (root !== null) {
- var eventTime = requestEventTime();
- scheduleUpdateOnFiber(root, fiber, lane, eventTime);
- entangleTransitionUpdate(root, queue, lane);
- }
- }
- markUpdateInDevTools(fiber, lane);
- }
- function isRenderPhaseUpdate(fiber) {
- var alternate = fiber.alternate;
- return fiber === currentlyRenderingFiber$1 || alternate !== null && alternate === currentlyRenderingFiber$1;
- }
- function enqueueRenderPhaseUpdate(queue, update) {
- // This is a render phase update. Stash it in a lazily-created map of
- // queue -> linked list of updates. After this render pass, we'll restart
- // and apply the stashed updates on top of the work-in-progress hook.
- didScheduleRenderPhaseUpdateDuringThisPass = didScheduleRenderPhaseUpdate = true;
- var pending = queue.pending;
- if (pending === null) {
- // This is the first update. Create a circular list.
- update.next = update;
- } else {
- update.next = pending.next;
- pending.next = update;
- }
- queue.pending = update;
- } // TODO: Move to ReactFiberConcurrentUpdates?
- function entangleTransitionUpdate(root, queue, lane) {
- if (isTransitionLane(lane)) {
- var queueLanes = queue.lanes; // If any entangled lanes are no longer pending on the root, then they
- // must have finished. We can remove them from the shared queue, which
- // represents a superset of the actually pending lanes. In some cases we
- // may entangle more than we need to, but that's OK. In fact it's worse if
- // we *don't* entangle when we should.
- queueLanes = intersectLanes(queueLanes, root.pendingLanes); // Entangle the new transition lane with the other transition lanes.
- var newQueueLanes = mergeLanes(queueLanes, lane);
- queue.lanes = newQueueLanes; // Even if queue.lanes already include lane, we don't know for certain if
- // the lane finished since the last time we entangled it. So we need to
- // entangle it again, just to be sure.
- markRootEntangled(root, newQueueLanes);
- }
- }
- function markUpdateInDevTools(fiber, lane, action) {
- {
- markStateUpdateScheduled(fiber, lane);
- }
- }
- var ContextOnlyDispatcher = {
- readContext: readContext,
- useCallback: throwInvalidHookError,
- useContext: throwInvalidHookError,
- useEffect: throwInvalidHookError,
- useImperativeHandle: throwInvalidHookError,
- useInsertionEffect: throwInvalidHookError,
- useLayoutEffect: throwInvalidHookError,
- useMemo: throwInvalidHookError,
- useReducer: throwInvalidHookError,
- useRef: throwInvalidHookError,
- useState: throwInvalidHookError,
- useDebugValue: throwInvalidHookError,
- useDeferredValue: throwInvalidHookError,
- useTransition: throwInvalidHookError,
- useMutableSource: throwInvalidHookError,
- useSyncExternalStore: throwInvalidHookError,
- useId: throwInvalidHookError,
- unstable_isNewReconciler: enableNewReconciler
- };
- var HooksDispatcherOnMountInDEV = null;
- var HooksDispatcherOnMountWithHookTypesInDEV = null;
- var HooksDispatcherOnUpdateInDEV = null;
- var HooksDispatcherOnRerenderInDEV = null;
- var InvalidNestedHooksDispatcherOnMountInDEV = null;
- var InvalidNestedHooksDispatcherOnUpdateInDEV = null;
- var InvalidNestedHooksDispatcherOnRerenderInDEV = null;
- {
- var warnInvalidContextAccess = function () {
- error('Context can only be read while React is rendering. ' + 'In classes, you can read it in the render method or getDerivedStateFromProps. ' + 'In function components, you can read it directly in the function body, but not ' + 'inside Hooks like useReducer() or useMemo().');
- };
- var warnInvalidHookAccess = function () {
- error('Do not call Hooks inside useEffect(...), useMemo(...), or other built-in Hooks. ' + 'You can only call Hooks at the top level of your React function. ' + 'For more information, see ' + 'https://reactjs.org/link/rules-of-hooks');
- };
- HooksDispatcherOnMountInDEV = {
- readContext: function (context) {
- return readContext(context);
- },
- useCallback: function (callback, deps) {
- currentHookNameInDev = 'useCallback';
- mountHookTypesDev();
- checkDepsAreArrayDev(deps);
- return mountCallback(callback, deps);
- },
- useContext: function (context) {
- currentHookNameInDev = 'useContext';
- mountHookTypesDev();
- return readContext(context);
- },
- useEffect: function (create, deps) {
- currentHookNameInDev = 'useEffect';
- mountHookTypesDev();
- checkDepsAreArrayDev(deps);
- return mountEffect(create, deps);
- },
- useImperativeHandle: function (ref, create, deps) {
- currentHookNameInDev = 'useImperativeHandle';
- mountHookTypesDev();
- checkDepsAreArrayDev(deps);
- return mountImperativeHandle(ref, create, deps);
- },
- useInsertionEffect: function (create, deps) {
- currentHookNameInDev = 'useInsertionEffect';
- mountHookTypesDev();
- checkDepsAreArrayDev(deps);
- return mountInsertionEffect(create, deps);
- },
- useLayoutEffect: function (create, deps) {
- currentHookNameInDev = 'useLayoutEffect';
- mountHookTypesDev();
- checkDepsAreArrayDev(deps);
- return mountLayoutEffect(create, deps);
- },
- useMemo: function (create, deps) {
- currentHookNameInDev = 'useMemo';
- mountHookTypesDev();
- checkDepsAreArrayDev(deps);
- var prevDispatcher = ReactCurrentDispatcher$1.current;
- ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV;
- try {
- return mountMemo(create, deps);
- } finally {
- ReactCurrentDispatcher$1.current = prevDispatcher;
- }
- },
- useReducer: function (reducer, initialArg, init) {
- currentHookNameInDev = 'useReducer';
- mountHookTypesDev();
- var prevDispatcher = ReactCurrentDispatcher$1.current;
- ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV;
- try {
- return mountReducer(reducer, initialArg, init);
- } finally {
- ReactCurrentDispatcher$1.current = prevDispatcher;
- }
- },
- useRef: function (initialValue) {
- currentHookNameInDev = 'useRef';
- mountHookTypesDev();
- return mountRef(initialValue);
- },
- useState: function (initialState) {
- currentHookNameInDev = 'useState';
- mountHookTypesDev();
- var prevDispatcher = ReactCurrentDispatcher$1.current;
- ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV;
- try {
- return mountState(initialState);
- } finally {
- ReactCurrentDispatcher$1.current = prevDispatcher;
- }
- },
- useDebugValue: function (value, formatterFn) {
- currentHookNameInDev = 'useDebugValue';
- mountHookTypesDev();
- return mountDebugValue();
- },
- useDeferredValue: function (value) {
- currentHookNameInDev = 'useDeferredValue';
- mountHookTypesDev();
- return mountDeferredValue(value);
- },
- useTransition: function () {
- currentHookNameInDev = 'useTransition';
- mountHookTypesDev();
- return mountTransition();
- },
- useMutableSource: function (source, getSnapshot, subscribe) {
- currentHookNameInDev = 'useMutableSource';
- mountHookTypesDev();
- return mountMutableSource();
- },
- useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) {
- currentHookNameInDev = 'useSyncExternalStore';
- mountHookTypesDev();
- return mountSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
- },
- useId: function () {
- currentHookNameInDev = 'useId';
- mountHookTypesDev();
- return mountId();
- },
- unstable_isNewReconciler: enableNewReconciler
- };
- HooksDispatcherOnMountWithHookTypesInDEV = {
- readContext: function (context) {
- return readContext(context);
- },
- useCallback: function (callback, deps) {
- currentHookNameInDev = 'useCallback';
- updateHookTypesDev();
- return mountCallback(callback, deps);
- },
- useContext: function (context) {
- currentHookNameInDev = 'useContext';
- updateHookTypesDev();
- return readContext(context);
- },
- useEffect: function (create, deps) {
- currentHookNameInDev = 'useEffect';
- updateHookTypesDev();
- return mountEffect(create, deps);
- },
- useImperativeHandle: function (ref, create, deps) {
- currentHookNameInDev = 'useImperativeHandle';
- updateHookTypesDev();
- return mountImperativeHandle(ref, create, deps);
- },
- useInsertionEffect: function (create, deps) {
- currentHookNameInDev = 'useInsertionEffect';
- updateHookTypesDev();
- return mountInsertionEffect(create, deps);
- },
- useLayoutEffect: function (create, deps) {
- currentHookNameInDev = 'useLayoutEffect';
- updateHookTypesDev();
- return mountLayoutEffect(create, deps);
- },
- useMemo: function (create, deps) {
- currentHookNameInDev = 'useMemo';
- updateHookTypesDev();
- var prevDispatcher = ReactCurrentDispatcher$1.current;
- ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV;
- try {
- return mountMemo(create, deps);
- } finally {
- ReactCurrentDispatcher$1.current = prevDispatcher;
- }
- },
- useReducer: function (reducer, initialArg, init) {
- currentHookNameInDev = 'useReducer';
- updateHookTypesDev();
- var prevDispatcher = ReactCurrentDispatcher$1.current;
- ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV;
- try {
- return mountReducer(reducer, initialArg, init);
- } finally {
- ReactCurrentDispatcher$1.current = prevDispatcher;
- }
- },
- useRef: function (initialValue) {
- currentHookNameInDev = 'useRef';
- updateHookTypesDev();
- return mountRef(initialValue);
- },
- useState: function (initialState) {
- currentHookNameInDev = 'useState';
- updateHookTypesDev();
- var prevDispatcher = ReactCurrentDispatcher$1.current;
- ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV;
- try {
- return mountState(initialState);
- } finally {
- ReactCurrentDispatcher$1.current = prevDispatcher;
- }
- },
- useDebugValue: function (value, formatterFn) {
- currentHookNameInDev = 'useDebugValue';
- updateHookTypesDev();
- return mountDebugValue();
- },
- useDeferredValue: function (value) {
- currentHookNameInDev = 'useDeferredValue';
- updateHookTypesDev();
- return mountDeferredValue(value);
- },
- useTransition: function () {
- currentHookNameInDev = 'useTransition';
- updateHookTypesDev();
- return mountTransition();
- },
- useMutableSource: function (source, getSnapshot, subscribe) {
- currentHookNameInDev = 'useMutableSource';
- updateHookTypesDev();
- return mountMutableSource();
- },
- useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) {
- currentHookNameInDev = 'useSyncExternalStore';
- updateHookTypesDev();
- return mountSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
- },
- useId: function () {
- currentHookNameInDev = 'useId';
- updateHookTypesDev();
- return mountId();
- },
- unstable_isNewReconciler: enableNewReconciler
- };
- HooksDispatcherOnUpdateInDEV = {
- readContext: function (context) {
- return readContext(context);
- },
- useCallback: function (callback, deps) {
- currentHookNameInDev = 'useCallback';
- updateHookTypesDev();
- return updateCallback(callback, deps);
- },
- useContext: function (context) {
- currentHookNameInDev = 'useContext';
- updateHookTypesDev();
- return readContext(context);
- },
- useEffect: function (create, deps) {
- currentHookNameInDev = 'useEffect';
- updateHookTypesDev();
- return updateEffect(create, deps);
- },
- useImperativeHandle: function (ref, create, deps) {
- currentHookNameInDev = 'useImperativeHandle';
- updateHookTypesDev();
- return updateImperativeHandle(ref, create, deps);
- },
- useInsertionEffect: function (create, deps) {
- currentHookNameInDev = 'useInsertionEffect';
- updateHookTypesDev();
- return updateInsertionEffect(create, deps);
- },
- useLayoutEffect: function (create, deps) {
- currentHookNameInDev = 'useLayoutEffect';
- updateHookTypesDev();
- return updateLayoutEffect(create, deps);
- },
- useMemo: function (create, deps) {
- currentHookNameInDev = 'useMemo';
- updateHookTypesDev();
- var prevDispatcher = ReactCurrentDispatcher$1.current;
- ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV;
- try {
- return updateMemo(create, deps);
- } finally {
- ReactCurrentDispatcher$1.current = prevDispatcher;
- }
- },
- useReducer: function (reducer, initialArg, init) {
- currentHookNameInDev = 'useReducer';
- updateHookTypesDev();
- var prevDispatcher = ReactCurrentDispatcher$1.current;
- ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV;
- try {
- return updateReducer(reducer, initialArg, init);
- } finally {
- ReactCurrentDispatcher$1.current = prevDispatcher;
- }
- },
- useRef: function (initialValue) {
- currentHookNameInDev = 'useRef';
- updateHookTypesDev();
- return updateRef();
- },
- useState: function (initialState) {
- currentHookNameInDev = 'useState';
- updateHookTypesDev();
- var prevDispatcher = ReactCurrentDispatcher$1.current;
- ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV;
- try {
- return updateState(initialState);
- } finally {
- ReactCurrentDispatcher$1.current = prevDispatcher;
- }
- },
- useDebugValue: function (value, formatterFn) {
- currentHookNameInDev = 'useDebugValue';
- updateHookTypesDev();
- return updateDebugValue();
- },
- useDeferredValue: function (value) {
- currentHookNameInDev = 'useDeferredValue';
- updateHookTypesDev();
- return updateDeferredValue(value);
- },
- useTransition: function () {
- currentHookNameInDev = 'useTransition';
- updateHookTypesDev();
- return updateTransition();
- },
- useMutableSource: function (source, getSnapshot, subscribe) {
- currentHookNameInDev = 'useMutableSource';
- updateHookTypesDev();
- return updateMutableSource();
- },
- useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) {
- currentHookNameInDev = 'useSyncExternalStore';
- updateHookTypesDev();
- return updateSyncExternalStore(subscribe, getSnapshot);
- },
- useId: function () {
- currentHookNameInDev = 'useId';
- updateHookTypesDev();
- return updateId();
- },
- unstable_isNewReconciler: enableNewReconciler
- };
- HooksDispatcherOnRerenderInDEV = {
- readContext: function (context) {
- return readContext(context);
- },
- useCallback: function (callback, deps) {
- currentHookNameInDev = 'useCallback';
- updateHookTypesDev();
- return updateCallback(callback, deps);
- },
- useContext: function (context) {
- currentHookNameInDev = 'useContext';
- updateHookTypesDev();
- return readContext(context);
- },
- useEffect: function (create, deps) {
- currentHookNameInDev = 'useEffect';
- updateHookTypesDev();
- return updateEffect(create, deps);
- },
- useImperativeHandle: function (ref, create, deps) {
- currentHookNameInDev = 'useImperativeHandle';
- updateHookTypesDev();
- return updateImperativeHandle(ref, create, deps);
- },
- useInsertionEffect: function (create, deps) {
- currentHookNameInDev = 'useInsertionEffect';
- updateHookTypesDev();
- return updateInsertionEffect(create, deps);
- },
- useLayoutEffect: function (create, deps) {
- currentHookNameInDev = 'useLayoutEffect';
- updateHookTypesDev();
- return updateLayoutEffect(create, deps);
- },
- useMemo: function (create, deps) {
- currentHookNameInDev = 'useMemo';
- updateHookTypesDev();
- var prevDispatcher = ReactCurrentDispatcher$1.current;
- ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnRerenderInDEV;
- try {
- return updateMemo(create, deps);
- } finally {
- ReactCurrentDispatcher$1.current = prevDispatcher;
- }
- },
- useReducer: function (reducer, initialArg, init) {
- currentHookNameInDev = 'useReducer';
- updateHookTypesDev();
- var prevDispatcher = ReactCurrentDispatcher$1.current;
- ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnRerenderInDEV;
- try {
- return rerenderReducer(reducer, initialArg, init);
- } finally {
- ReactCurrentDispatcher$1.current = prevDispatcher;
- }
- },
- useRef: function (initialValue) {
- currentHookNameInDev = 'useRef';
- updateHookTypesDev();
- return updateRef();
- },
- useState: function (initialState) {
- currentHookNameInDev = 'useState';
- updateHookTypesDev();
- var prevDispatcher = ReactCurrentDispatcher$1.current;
- ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnRerenderInDEV;
- try {
- return rerenderState(initialState);
- } finally {
- ReactCurrentDispatcher$1.current = prevDispatcher;
- }
- },
- useDebugValue: function (value, formatterFn) {
- currentHookNameInDev = 'useDebugValue';
- updateHookTypesDev();
- return updateDebugValue();
- },
- useDeferredValue: function (value) {
- currentHookNameInDev = 'useDeferredValue';
- updateHookTypesDev();
- return rerenderDeferredValue(value);
- },
- useTransition: function () {
- currentHookNameInDev = 'useTransition';
- updateHookTypesDev();
- return rerenderTransition();
- },
- useMutableSource: function (source, getSnapshot, subscribe) {
- currentHookNameInDev = 'useMutableSource';
- updateHookTypesDev();
- return updateMutableSource();
- },
- useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) {
- currentHookNameInDev = 'useSyncExternalStore';
- updateHookTypesDev();
- return updateSyncExternalStore(subscribe, getSnapshot);
- },
- useId: function () {
- currentHookNameInDev = 'useId';
- updateHookTypesDev();
- return updateId();
- },
- unstable_isNewReconciler: enableNewReconciler
- };
- InvalidNestedHooksDispatcherOnMountInDEV = {
- readContext: function (context) {
- warnInvalidContextAccess();
- return readContext(context);
- },
- useCallback: function (callback, deps) {
- currentHookNameInDev = 'useCallback';
- warnInvalidHookAccess();
- mountHookTypesDev();
- return mountCallback(callback, deps);
- },
- useContext: function (context) {
- currentHookNameInDev = 'useContext';
- warnInvalidHookAccess();
- mountHookTypesDev();
- return readContext(context);
- },
- useEffect: function (create, deps) {
- currentHookNameInDev = 'useEffect';
- warnInvalidHookAccess();
- mountHookTypesDev();
- return mountEffect(create, deps);
- },
- useImperativeHandle: function (ref, create, deps) {
- currentHookNameInDev = 'useImperativeHandle';
- warnInvalidHookAccess();
- mountHookTypesDev();
- return mountImperativeHandle(ref, create, deps);
- },
- useInsertionEffect: function (create, deps) {
- currentHookNameInDev = 'useInsertionEffect';
- warnInvalidHookAccess();
- mountHookTypesDev();
- return mountInsertionEffect(create, deps);
- },
- useLayoutEffect: function (create, deps) {
- currentHookNameInDev = 'useLayoutEffect';
- warnInvalidHookAccess();
- mountHookTypesDev();
- return mountLayoutEffect(create, deps);
- },
- useMemo: function (create, deps) {
- currentHookNameInDev = 'useMemo';
- warnInvalidHookAccess();
- mountHookTypesDev();
- var prevDispatcher = ReactCurrentDispatcher$1.current;
- ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV;
- try {
- return mountMemo(create, deps);
- } finally {
- ReactCurrentDispatcher$1.current = prevDispatcher;
- }
- },
- useReducer: function (reducer, initialArg, init) {
- currentHookNameInDev = 'useReducer';
- warnInvalidHookAccess();
- mountHookTypesDev();
- var prevDispatcher = ReactCurrentDispatcher$1.current;
- ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV;
- try {
- return mountReducer(reducer, initialArg, init);
- } finally {
- ReactCurrentDispatcher$1.current = prevDispatcher;
- }
- },
- useRef: function (initialValue) {
- currentHookNameInDev = 'useRef';
- warnInvalidHookAccess();
- mountHookTypesDev();
- return mountRef(initialValue);
- },
- useState: function (initialState) {
- currentHookNameInDev = 'useState';
- warnInvalidHookAccess();
- mountHookTypesDev();
- var prevDispatcher = ReactCurrentDispatcher$1.current;
- ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV;
- try {
- return mountState(initialState);
- } finally {
- ReactCurrentDispatcher$1.current = prevDispatcher;
- }
- },
- useDebugValue: function (value, formatterFn) {
- currentHookNameInDev = 'useDebugValue';
- warnInvalidHookAccess();
- mountHookTypesDev();
- return mountDebugValue();
- },
- useDeferredValue: function (value) {
- currentHookNameInDev = 'useDeferredValue';
- warnInvalidHookAccess();
- mountHookTypesDev();
- return mountDeferredValue(value);
- },
- useTransition: function () {
- currentHookNameInDev = 'useTransition';
- warnInvalidHookAccess();
- mountHookTypesDev();
- return mountTransition();
- },
- useMutableSource: function (source, getSnapshot, subscribe) {
- currentHookNameInDev = 'useMutableSource';
- warnInvalidHookAccess();
- mountHookTypesDev();
- return mountMutableSource();
- },
- useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) {
- currentHookNameInDev = 'useSyncExternalStore';
- warnInvalidHookAccess();
- mountHookTypesDev();
- return mountSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
- },
- useId: function () {
- currentHookNameInDev = 'useId';
- warnInvalidHookAccess();
- mountHookTypesDev();
- return mountId();
- },
- unstable_isNewReconciler: enableNewReconciler
- };
- InvalidNestedHooksDispatcherOnUpdateInDEV = {
- readContext: function (context) {
- warnInvalidContextAccess();
- return readContext(context);
- },
- useCallback: function (callback, deps) {
- currentHookNameInDev = 'useCallback';
- warnInvalidHookAccess();
- updateHookTypesDev();
- return updateCallback(callback, deps);
- },
- useContext: function (context) {
- currentHookNameInDev = 'useContext';
- warnInvalidHookAccess();
- updateHookTypesDev();
- return readContext(context);
- },
- useEffect: function (create, deps) {
- currentHookNameInDev = 'useEffect';
- warnInvalidHookAccess();
- updateHookTypesDev();
- return updateEffect(create, deps);
- },
- useImperativeHandle: function (ref, create, deps) {
- currentHookNameInDev = 'useImperativeHandle';
- warnInvalidHookAccess();
- updateHookTypesDev();
- return updateImperativeHandle(ref, create, deps);
- },
- useInsertionEffect: function (create, deps) {
- currentHookNameInDev = 'useInsertionEffect';
- warnInvalidHookAccess();
- updateHookTypesDev();
- return updateInsertionEffect(create, deps);
- },
- useLayoutEffect: function (create, deps) {
- currentHookNameInDev = 'useLayoutEffect';
- warnInvalidHookAccess();
- updateHookTypesDev();
- return updateLayoutEffect(create, deps);
- },
- useMemo: function (create, deps) {
- currentHookNameInDev = 'useMemo';
- warnInvalidHookAccess();
- updateHookTypesDev();
- var prevDispatcher = ReactCurrentDispatcher$1.current;
- ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV;
- try {
- return updateMemo(create, deps);
- } finally {
- ReactCurrentDispatcher$1.current = prevDispatcher;
- }
- },
- useReducer: function (reducer, initialArg, init) {
- currentHookNameInDev = 'useReducer';
- warnInvalidHookAccess();
- updateHookTypesDev();
- var prevDispatcher = ReactCurrentDispatcher$1.current;
- ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV;
- try {
- return updateReducer(reducer, initialArg, init);
- } finally {
- ReactCurrentDispatcher$1.current = prevDispatcher;
- }
- },
- useRef: function (initialValue) {
- currentHookNameInDev = 'useRef';
- warnInvalidHookAccess();
- updateHookTypesDev();
- return updateRef();
- },
- useState: function (initialState) {
- currentHookNameInDev = 'useState';
- warnInvalidHookAccess();
- updateHookTypesDev();
- var prevDispatcher = ReactCurrentDispatcher$1.current;
- ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV;
- try {
- return updateState(initialState);
- } finally {
- ReactCurrentDispatcher$1.current = prevDispatcher;
- }
- },
- useDebugValue: function (value, formatterFn) {
- currentHookNameInDev = 'useDebugValue';
- warnInvalidHookAccess();
- updateHookTypesDev();
- return updateDebugValue();
- },
- useDeferredValue: function (value) {
- currentHookNameInDev = 'useDeferredValue';
- warnInvalidHookAccess();
- updateHookTypesDev();
- return updateDeferredValue(value);
- },
- useTransition: function () {
- currentHookNameInDev = 'useTransition';
- warnInvalidHookAccess();
- updateHookTypesDev();
- return updateTransition();
- },
- useMutableSource: function (source, getSnapshot, subscribe) {
- currentHookNameInDev = 'useMutableSource';
- warnInvalidHookAccess();
- updateHookTypesDev();
- return updateMutableSource();
- },
- useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) {
- currentHookNameInDev = 'useSyncExternalStore';
- warnInvalidHookAccess();
- updateHookTypesDev();
- return updateSyncExternalStore(subscribe, getSnapshot);
- },
- useId: function () {
- currentHookNameInDev = 'useId';
- warnInvalidHookAccess();
- updateHookTypesDev();
- return updateId();
- },
- unstable_isNewReconciler: enableNewReconciler
- };
- InvalidNestedHooksDispatcherOnRerenderInDEV = {
- readContext: function (context) {
- warnInvalidContextAccess();
- return readContext(context);
- },
- useCallback: function (callback, deps) {
- currentHookNameInDev = 'useCallback';
- warnInvalidHookAccess();
- updateHookTypesDev();
- return updateCallback(callback, deps);
- },
- useContext: function (context) {
- currentHookNameInDev = 'useContext';
- warnInvalidHookAccess();
- updateHookTypesDev();
- return readContext(context);
- },
- useEffect: function (create, deps) {
- currentHookNameInDev = 'useEffect';
- warnInvalidHookAccess();
- updateHookTypesDev();
- return updateEffect(create, deps);
- },
- useImperativeHandle: function (ref, create, deps) {
- currentHookNameInDev = 'useImperativeHandle';
- warnInvalidHookAccess();
- updateHookTypesDev();
- return updateImperativeHandle(ref, create, deps);
- },
- useInsertionEffect: function (create, deps) {
- currentHookNameInDev = 'useInsertionEffect';
- warnInvalidHookAccess();
- updateHookTypesDev();
- return updateInsertionEffect(create, deps);
- },
- useLayoutEffect: function (create, deps) {
- currentHookNameInDev = 'useLayoutEffect';
- warnInvalidHookAccess();
- updateHookTypesDev();
- return updateLayoutEffect(create, deps);
- },
- useMemo: function (create, deps) {
- currentHookNameInDev = 'useMemo';
- warnInvalidHookAccess();
- updateHookTypesDev();
- var prevDispatcher = ReactCurrentDispatcher$1.current;
- ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV;
- try {
- return updateMemo(create, deps);
- } finally {
- ReactCurrentDispatcher$1.current = prevDispatcher;
- }
- },
- useReducer: function (reducer, initialArg, init) {
- currentHookNameInDev = 'useReducer';
- warnInvalidHookAccess();
- updateHookTypesDev();
- var prevDispatcher = ReactCurrentDispatcher$1.current;
- ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV;
- try {
- return rerenderReducer(reducer, initialArg, init);
- } finally {
- ReactCurrentDispatcher$1.current = prevDispatcher;
- }
- },
- useRef: function (initialValue) {
- currentHookNameInDev = 'useRef';
- warnInvalidHookAccess();
- updateHookTypesDev();
- return updateRef();
- },
- useState: function (initialState) {
- currentHookNameInDev = 'useState';
- warnInvalidHookAccess();
- updateHookTypesDev();
- var prevDispatcher = ReactCurrentDispatcher$1.current;
- ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV;
- try {
- return rerenderState(initialState);
- } finally {
- ReactCurrentDispatcher$1.current = prevDispatcher;
- }
- },
- useDebugValue: function (value, formatterFn) {
- currentHookNameInDev = 'useDebugValue';
- warnInvalidHookAccess();
- updateHookTypesDev();
- return updateDebugValue();
- },
- useDeferredValue: function (value) {
- currentHookNameInDev = 'useDeferredValue';
- warnInvalidHookAccess();
- updateHookTypesDev();
- return rerenderDeferredValue(value);
- },
- useTransition: function () {
- currentHookNameInDev = 'useTransition';
- warnInvalidHookAccess();
- updateHookTypesDev();
- return rerenderTransition();
- },
- useMutableSource: function (source, getSnapshot, subscribe) {
- currentHookNameInDev = 'useMutableSource';
- warnInvalidHookAccess();
- updateHookTypesDev();
- return updateMutableSource();
- },
- useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) {
- currentHookNameInDev = 'useSyncExternalStore';
- warnInvalidHookAccess();
- updateHookTypesDev();
- return updateSyncExternalStore(subscribe, getSnapshot);
- },
- useId: function () {
- currentHookNameInDev = 'useId';
- warnInvalidHookAccess();
- updateHookTypesDev();
- return updateId();
- },
- unstable_isNewReconciler: enableNewReconciler
- };
- }
- var now$1 = unstable_now;
- var commitTime = 0;
- var layoutEffectStartTime = -1;
- var profilerStartTime = -1;
- var passiveEffectStartTime = -1;
- /**
- * Tracks whether the current update was a nested/cascading update (scheduled from a layout effect).
- *
- * The overall sequence is:
- * 1. render
- * 2. commit (and call `onRender`, `onCommit`)
- * 3. check for nested updates
- * 4. flush passive effects (and call `onPostCommit`)
- *
- * Nested updates are identified in step 3 above,
- * but step 4 still applies to the work that was just committed.
- * We use two flags to track nested updates then:
- * one tracks whether the upcoming update is a nested update,
- * and the other tracks whether the current update was a nested update.
- * The first value gets synced to the second at the start of the render phase.
- */
- var currentUpdateIsNested = false;
- var nestedUpdateScheduled = false;
- function isCurrentUpdateNested() {
- return currentUpdateIsNested;
- }
- function markNestedUpdateScheduled() {
- {
- nestedUpdateScheduled = true;
- }
- }
- function resetNestedUpdateFlag() {
- {
- currentUpdateIsNested = false;
- nestedUpdateScheduled = false;
- }
- }
- function syncNestedUpdateFlag() {
- {
- currentUpdateIsNested = nestedUpdateScheduled;
- nestedUpdateScheduled = false;
- }
- }
- function getCommitTime() {
- return commitTime;
- }
- function recordCommitTime() {
- commitTime = now$1();
- }
- function startProfilerTimer(fiber) {
- profilerStartTime = now$1();
- if (fiber.actualStartTime < 0) {
- fiber.actualStartTime = now$1();
- }
- }
- function stopProfilerTimerIfRunning(fiber) {
- profilerStartTime = -1;
- }
- function stopProfilerTimerIfRunningAndRecordDelta(fiber, overrideBaseTime) {
- if (profilerStartTime >= 0) {
- var elapsedTime = now$1() - profilerStartTime;
- fiber.actualDuration += elapsedTime;
- if (overrideBaseTime) {
- fiber.selfBaseDuration = elapsedTime;
- }
- profilerStartTime = -1;
- }
- }
- function recordLayoutEffectDuration(fiber) {
- if (layoutEffectStartTime >= 0) {
- var elapsedTime = now$1() - layoutEffectStartTime;
- layoutEffectStartTime = -1; // Store duration on the next nearest Profiler ancestor
- // Or the root (for the DevTools Profiler to read)
- var parentFiber = fiber.return;
- while (parentFiber !== null) {
- switch (parentFiber.tag) {
- case HostRoot:
- var root = parentFiber.stateNode;
- root.effectDuration += elapsedTime;
- return;
- case Profiler:
- var parentStateNode = parentFiber.stateNode;
- parentStateNode.effectDuration += elapsedTime;
- return;
- }
- parentFiber = parentFiber.return;
- }
- }
- }
- function recordPassiveEffectDuration(fiber) {
- if (passiveEffectStartTime >= 0) {
- var elapsedTime = now$1() - passiveEffectStartTime;
- passiveEffectStartTime = -1; // Store duration on the next nearest Profiler ancestor
- // Or the root (for the DevTools Profiler to read)
- var parentFiber = fiber.return;
- while (parentFiber !== null) {
- switch (parentFiber.tag) {
- case HostRoot:
- var root = parentFiber.stateNode;
- if (root !== null) {
- root.passiveEffectDuration += elapsedTime;
- }
- return;
- case Profiler:
- var parentStateNode = parentFiber.stateNode;
- if (parentStateNode !== null) {
- // Detached fibers have their state node cleared out.
- // In this case, the return pointer is also cleared out,
- // so we won't be able to report the time spent in this Profiler's subtree.
- parentStateNode.passiveEffectDuration += elapsedTime;
- }
- return;
- }
- parentFiber = parentFiber.return;
- }
- }
- }
- function startLayoutEffectTimer() {
- layoutEffectStartTime = now$1();
- }
- function startPassiveEffectTimer() {
- passiveEffectStartTime = now$1();
- }
- function transferActualDuration(fiber) {
- // Transfer time spent rendering these children so we don't lose it
- // after we rerender. This is used as a helper in special cases
- // where we should count the work of multiple passes.
- var child = fiber.child;
- while (child) {
- fiber.actualDuration += child.actualDuration;
- child = child.sibling;
- }
- }
- function createCapturedValueAtFiber(value, source) {
- // If the value is an error, call this function immediately after it is thrown
- // so the stack is accurate.
- return {
- value: value,
- source: source,
- stack: getStackByFiberInDevAndProd(source),
- digest: null
- };
- }
- function createCapturedValue(value, digest, stack) {
- return {
- value: value,
- source: null,
- stack: stack != null ? stack : null,
- digest: digest != null ? digest : null
- };
- }
- // This module is forked in different environments.
- // By default, return `true` to log errors to the console.
- // Forks can return `false` if this isn't desirable.
- function showErrorDialog(boundary, errorInfo) {
- return true;
- }
- function logCapturedError(boundary, errorInfo) {
- try {
- var logError = showErrorDialog(boundary, errorInfo); // Allow injected showErrorDialog() to prevent default console.error logging.
- // This enables renderers like ReactNative to better manage redbox behavior.
- if (logError === false) {
- return;
- }
- var error = errorInfo.value;
- if (true) {
- var source = errorInfo.source;
- var stack = errorInfo.stack;
- var componentStack = stack !== null ? stack : ''; // Browsers support silencing uncaught errors by calling
- // `preventDefault()` in window `error` handler.
- // We record this information as an expando on the error.
- if (error != null && error._suppressLogging) {
- if (boundary.tag === ClassComponent) {
- // The error is recoverable and was silenced.
- // Ignore it and don't print the stack addendum.
- // This is handy for testing error boundaries without noise.
- return;
- } // The error is fatal. Since the silencing might have
- // been accidental, we'll surface it anyway.
- // However, the browser would have silenced the original error
- // so we'll print it first, and then print the stack addendum.
- console['error'](error); // Don't transform to our wrapper
- // For a more detailed description of this block, see:
- // https://github.com/facebook/react/pull/13384
- }
- var componentName = source ? getComponentNameFromFiber(source) : null;
- var componentNameMessage = componentName ? "The above error occurred in the <" + componentName + "> component:" : 'The above error occurred in one of your React components:';
- var errorBoundaryMessage;
- if (boundary.tag === HostRoot) {
- errorBoundaryMessage = 'Consider adding an error boundary to your tree to customize error handling behavior.\n' + 'Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.';
- } else {
- var errorBoundaryName = getComponentNameFromFiber(boundary) || 'Anonymous';
- errorBoundaryMessage = "React will try to recreate this component tree from scratch " + ("using the error boundary you provided, " + errorBoundaryName + ".");
- }
- var combinedMessage = componentNameMessage + "\n" + componentStack + "\n\n" + ("" + errorBoundaryMessage); // In development, we provide our own message with just the component stack.
- // We don't include the original error message and JS stack because the browser
- // has already printed it. Even if the application swallows the error, it is still
- // displayed by the browser thanks to the DEV-only fake event trick in ReactErrorUtils.
- console['error'](combinedMessage); // Don't transform to our wrapper
- } else {
- // In production, we print the error directly.
- // This will include the message, the JS stack, and anything the browser wants to show.
- // We pass the error object instead of custom message so that the browser displays the error natively.
- console['error'](error); // Don't transform to our wrapper
- }
- } catch (e) {
- // This method must not throw, or React internal state will get messed up.
- // If console.error is overridden, or logCapturedError() shows a dialog that throws,
- // we want to report this error outside of the normal stack as a last resort.
- // https://github.com/facebook/react/issues/13188
- setTimeout(function () {
- throw e;
- });
- }
- }
- var PossiblyWeakMap$1 = typeof WeakMap === 'function' ? WeakMap : Map;
- function createRootErrorUpdate(fiber, errorInfo, lane) {
- var update = createUpdate(NoTimestamp, lane); // Unmount the root by rendering null.
- update.tag = CaptureUpdate; // Caution: React DevTools currently depends on this property
- // being called "element".
- update.payload = {
- element: null
- };
- var error = errorInfo.value;
- update.callback = function () {
- onUncaughtError(error);
- logCapturedError(fiber, errorInfo);
- };
- return update;
- }
- function createClassErrorUpdate(fiber, errorInfo, lane) {
- var update = createUpdate(NoTimestamp, lane);
- update.tag = CaptureUpdate;
- var getDerivedStateFromError = fiber.type.getDerivedStateFromError;
- if (typeof getDerivedStateFromError === 'function') {
- var error$1 = errorInfo.value;
- update.payload = function () {
- return getDerivedStateFromError(error$1);
- };
- update.callback = function () {
- {
- markFailedErrorBoundaryForHotReloading(fiber);
- }
- logCapturedError(fiber, errorInfo);
- };
- }
- var inst = fiber.stateNode;
- if (inst !== null && typeof inst.componentDidCatch === 'function') {
- update.callback = function callback() {
- {
- markFailedErrorBoundaryForHotReloading(fiber);
- }
- logCapturedError(fiber, errorInfo);
- if (typeof getDerivedStateFromError !== 'function') {
- // To preserve the preexisting retry behavior of error boundaries,
- // we keep track of which ones already failed during this batch.
- // This gets reset before we yield back to the browser.
- // TODO: Warn in strict mode if getDerivedStateFromError is
- // not defined.
- markLegacyErrorBoundaryAsFailed(this);
- }
- var error$1 = errorInfo.value;
- var stack = errorInfo.stack;
- this.componentDidCatch(error$1, {
- componentStack: stack !== null ? stack : ''
- });
- {
- if (typeof getDerivedStateFromError !== 'function') {
- // If componentDidCatch is the only error boundary method defined,
- // then it needs to call setState to recover from errors.
- // If no state update is scheduled then the boundary will swallow the error.
- if (!includesSomeLane(fiber.lanes, SyncLane)) {
- error('%s: Error boundaries should implement getDerivedStateFromError(). ' + 'In that method, return a state update to display an error message or fallback UI.', getComponentNameFromFiber(fiber) || 'Unknown');
- }
- }
- }
- };
- }
- return update;
- }
- function attachPingListener(root, wakeable, lanes) {
- // Attach a ping listener
- //
- // The data might resolve before we have a chance to commit the fallback. Or,
- // in the case of a refresh, we'll never commit a fallback. So we need to
- // attach a listener now. When it resolves ("pings"), we can decide whether to
- // try rendering the tree again.
- //
- // Only attach a listener if one does not already exist for the lanes
- // we're currently rendering (which acts like a "thread ID" here).
- //
- // We only need to do this in concurrent mode. Legacy Suspense always
- // commits fallbacks synchronously, so there are no pings.
- var pingCache = root.pingCache;
- var threadIDs;
- if (pingCache === null) {
- pingCache = root.pingCache = new PossiblyWeakMap$1();
- threadIDs = new Set();
- pingCache.set(wakeable, threadIDs);
- } else {
- threadIDs = pingCache.get(wakeable);
- if (threadIDs === undefined) {
- threadIDs = new Set();
- pingCache.set(wakeable, threadIDs);
- }
- }
- if (!threadIDs.has(lanes)) {
- // Memoize using the thread ID to prevent redundant listeners.
- threadIDs.add(lanes);
- var ping = pingSuspendedRoot.bind(null, root, wakeable, lanes);
- {
- if (isDevToolsPresent) {
- // If we have pending work still, restore the original updaters
- restorePendingUpdaters(root, lanes);
- }
- }
- wakeable.then(ping, ping);
- }
- }
- function attachRetryListener(suspenseBoundary, root, wakeable, lanes) {
- // Retry listener
- //
- // If the fallback does commit, we need to attach a different type of
- // listener. This one schedules an update on the Suspense boundary to turn
- // the fallback state off.
- //
- // Stash the wakeable on the boundary fiber so we can access it in the
- // commit phase.
- //
- // When the wakeable resolves, we'll attempt to render the boundary
- // again ("retry").
- var wakeables = suspenseBoundary.updateQueue;
- if (wakeables === null) {
- var updateQueue = new Set();
- updateQueue.add(wakeable);
- suspenseBoundary.updateQueue = updateQueue;
- } else {
- wakeables.add(wakeable);
- }
- }
- function resetSuspendedComponent(sourceFiber, rootRenderLanes) {
- // A legacy mode Suspense quirk, only relevant to hook components.
- var tag = sourceFiber.tag;
- if ((sourceFiber.mode & ConcurrentMode) === NoMode && (tag === FunctionComponent || tag === ForwardRef || tag === SimpleMemoComponent)) {
- var currentSource = sourceFiber.alternate;
- if (currentSource) {
- sourceFiber.updateQueue = currentSource.updateQueue;
- sourceFiber.memoizedState = currentSource.memoizedState;
- sourceFiber.lanes = currentSource.lanes;
- } else {
- sourceFiber.updateQueue = null;
- sourceFiber.memoizedState = null;
- }
- }
- }
- function getNearestSuspenseBoundaryToCapture(returnFiber) {
- var node = returnFiber;
- do {
- if (node.tag === SuspenseComponent && shouldCaptureSuspense(node)) {
- return node;
- } // This boundary already captured during this render. Continue to the next
- // boundary.
- node = node.return;
- } while (node !== null);
- return null;
- }
- function markSuspenseBoundaryShouldCapture(suspenseBoundary, returnFiber, sourceFiber, root, rootRenderLanes) {
- // This marks a Suspense boundary so that when we're unwinding the stack,
- // it captures the suspended "exception" and does a second (fallback) pass.
- if ((suspenseBoundary.mode & ConcurrentMode) === NoMode) {
- // Legacy Mode Suspense
- //
- // If the boundary is in legacy mode, we should *not*
- // suspend the commit. Pretend as if the suspended component rendered
- // null and keep rendering. When the Suspense boundary completes,
- // we'll do a second pass to render the fallback.
- if (suspenseBoundary === returnFiber) {
- // Special case where we suspended while reconciling the children of
- // a Suspense boundary's inner Offscreen wrapper fiber. This happens
- // when a React.lazy component is a direct child of a
- // Suspense boundary.
- //
- // Suspense boundaries are implemented as multiple fibers, but they
- // are a single conceptual unit. The legacy mode behavior where we
- // pretend the suspended fiber committed as `null` won't work,
- // because in this case the "suspended" fiber is the inner
- // Offscreen wrapper.
- //
- // Because the contents of the boundary haven't started rendering
- // yet (i.e. nothing in the tree has partially rendered) we can
- // switch to the regular, concurrent mode behavior: mark the
- // boundary with ShouldCapture and enter the unwind phase.
- suspenseBoundary.flags |= ShouldCapture;
- } else {
- suspenseBoundary.flags |= DidCapture;
- sourceFiber.flags |= ForceUpdateForLegacySuspense; // We're going to commit this fiber even though it didn't complete.
- // But we shouldn't call any lifecycle methods or callbacks. Remove
- // all lifecycle effect tags.
- sourceFiber.flags &= ~(LifecycleEffectMask | Incomplete);
- if (sourceFiber.tag === ClassComponent) {
- var currentSourceFiber = sourceFiber.alternate;
- if (currentSourceFiber === null) {
- // This is a new mount. Change the tag so it's not mistaken for a
- // completed class component. For example, we should not call
- // componentWillUnmount if it is deleted.
- sourceFiber.tag = IncompleteClassComponent;
- } else {
- // When we try rendering again, we should not reuse the current fiber,
- // since it's known to be in an inconsistent state. Use a force update to
- // prevent a bail out.
- var update = createUpdate(NoTimestamp, SyncLane);
- update.tag = ForceUpdate;
- enqueueUpdate(sourceFiber, update, SyncLane);
- }
- } // The source fiber did not complete. Mark it with Sync priority to
- // indicate that it still has pending work.
- sourceFiber.lanes = mergeLanes(sourceFiber.lanes, SyncLane);
- }
- return suspenseBoundary;
- } // Confirmed that the boundary is in a concurrent mode tree. Continue
- // with the normal suspend path.
- //
- // After this we'll use a set of heuristics to determine whether this
- // render pass will run to completion or restart or "suspend" the commit.
- // The actual logic for this is spread out in different places.
- //
- // This first principle is that if we're going to suspend when we complete
- // a root, then we should also restart if we get an update or ping that
- // might unsuspend it, and vice versa. The only reason to suspend is
- // because you think you might want to restart before committing. However,
- // it doesn't make sense to restart only while in the period we're suspended.
- //
- // Restarting too aggressively is also not good because it starves out any
- // intermediate loading state. So we use heuristics to determine when.
- // Suspense Heuristics
- //
- // If nothing threw a Promise or all the same fallbacks are already showing,
- // then don't suspend/restart.
- //
- // If this is an initial render of a new tree of Suspense boundaries and
- // those trigger a fallback, then don't suspend/restart. We want to ensure
- // that we can show the initial loading state as quickly as possible.
- //
- // If we hit a "Delayed" case, such as when we'd switch from content back into
- // a fallback, then we should always suspend/restart. Transitions apply
- // to this case. If none is defined, JND is used instead.
- //
- // If we're already showing a fallback and it gets "retried", allowing us to show
- // another level, but there's still an inner boundary that would show a fallback,
- // then we suspend/restart for 500ms since the last time we showed a fallback
- // anywhere in the tree. This effectively throttles progressive loading into a
- // consistent train of commits. This also gives us an opportunity to restart to
- // get to the completed state slightly earlier.
- //
- // If there's ambiguity due to batching it's resolved in preference of:
- // 1) "delayed", 2) "initial render", 3) "retry".
- //
- // We want to ensure that a "busy" state doesn't get force committed. We want to
- // ensure that new initial loading states can commit as soon as possible.
- suspenseBoundary.flags |= ShouldCapture; // TODO: I think we can remove this, since we now use `DidCapture` in
- // the begin phase to prevent an early bailout.
- suspenseBoundary.lanes = rootRenderLanes;
- return suspenseBoundary;
- }
- function throwException(root, returnFiber, sourceFiber, value, rootRenderLanes) {
- // The source fiber did not complete.
- sourceFiber.flags |= Incomplete;
- {
- if (isDevToolsPresent) {
- // If we have pending work still, restore the original updaters
- restorePendingUpdaters(root, rootRenderLanes);
- }
- }
- if (value !== null && typeof value === 'object' && typeof value.then === 'function') {
- // This is a wakeable. The component suspended.
- var wakeable = value;
- resetSuspendedComponent(sourceFiber);
- {
- if (getIsHydrating() && sourceFiber.mode & ConcurrentMode) {
- markDidThrowWhileHydratingDEV();
- }
- }
- var suspenseBoundary = getNearestSuspenseBoundaryToCapture(returnFiber);
- if (suspenseBoundary !== null) {
- suspenseBoundary.flags &= ~ForceClientRender;
- markSuspenseBoundaryShouldCapture(suspenseBoundary, returnFiber, sourceFiber, root, rootRenderLanes); // We only attach ping listeners in concurrent mode. Legacy Suspense always
- // commits fallbacks synchronously, so there are no pings.
- if (suspenseBoundary.mode & ConcurrentMode) {
- attachPingListener(root, wakeable, rootRenderLanes);
- }
- attachRetryListener(suspenseBoundary, root, wakeable);
- return;
- } else {
- // No boundary was found. Unless this is a sync update, this is OK.
- // We can suspend and wait for more data to arrive.
- if (!includesSyncLane(rootRenderLanes)) {
- // This is not a sync update. Suspend. Since we're not activating a
- // Suspense boundary, this will unwind all the way to the root without
- // performing a second pass to render a fallback. (This is arguably how
- // refresh transitions should work, too, since we're not going to commit
- // the fallbacks anyway.)
- //
- // This case also applies to initial hydration.
- attachPingListener(root, wakeable, rootRenderLanes);
- renderDidSuspendDelayIfPossible();
- return;
- } // This is a sync/discrete update. We treat this case like an error
- // because discrete renders are expected to produce a complete tree
- // synchronously to maintain consistency with external state.
- var uncaughtSuspenseError = new Error('A component suspended while responding to synchronous input. This ' + 'will cause the UI to be replaced with a loading indicator. To ' + 'fix, updates that suspend should be wrapped ' + 'with startTransition.'); // If we're outside a transition, fall through to the regular error path.
- // The error will be caught by the nearest suspense boundary.
- value = uncaughtSuspenseError;
- }
- } else {
- // This is a regular error, not a Suspense wakeable.
- if (getIsHydrating() && sourceFiber.mode & ConcurrentMode) {
- markDidThrowWhileHydratingDEV();
- var _suspenseBoundary = getNearestSuspenseBoundaryToCapture(returnFiber); // If the error was thrown during hydration, we may be able to recover by
- // discarding the dehydrated content and switching to a client render.
- // Instead of surfacing the error, find the nearest Suspense boundary
- // and render it again without hydration.
- if (_suspenseBoundary !== null) {
- if ((_suspenseBoundary.flags & ShouldCapture) === NoFlags) {
- // Set a flag to indicate that we should try rendering the normal
- // children again, not the fallback.
- _suspenseBoundary.flags |= ForceClientRender;
- }
- markSuspenseBoundaryShouldCapture(_suspenseBoundary, returnFiber, sourceFiber, root, rootRenderLanes); // Even though the user may not be affected by this error, we should
- // still log it so it can be fixed.
- queueHydrationError(createCapturedValueAtFiber(value, sourceFiber));
- return;
- }
- }
- }
- value = createCapturedValueAtFiber(value, sourceFiber);
- renderDidError(value); // We didn't find a boundary that could handle this type of exception. Start
- // over and traverse parent path again, this time treating the exception
- // as an error.
- var workInProgress = returnFiber;
- do {
- switch (workInProgress.tag) {
- case HostRoot:
- {
- var _errorInfo = value;
- workInProgress.flags |= ShouldCapture;
- var lane = pickArbitraryLane(rootRenderLanes);
- workInProgress.lanes = mergeLanes(workInProgress.lanes, lane);
- var update = createRootErrorUpdate(workInProgress, _errorInfo, lane);
- enqueueCapturedUpdate(workInProgress, update);
- return;
- }
- case ClassComponent:
- // Capture and retry
- var errorInfo = value;
- var ctor = workInProgress.type;
- var instance = workInProgress.stateNode;
- if ((workInProgress.flags & DidCapture) === NoFlags && (typeof ctor.getDerivedStateFromError === 'function' || instance !== null && typeof instance.componentDidCatch === 'function' && !isAlreadyFailedLegacyErrorBoundary(instance))) {
- workInProgress.flags |= ShouldCapture;
- var _lane = pickArbitraryLane(rootRenderLanes);
- workInProgress.lanes = mergeLanes(workInProgress.lanes, _lane); // Schedule the error boundary to re-render using updated state
- var _update = createClassErrorUpdate(workInProgress, errorInfo, _lane);
- enqueueCapturedUpdate(workInProgress, _update);
- return;
- }
- break;
- }
- workInProgress = workInProgress.return;
- } while (workInProgress !== null);
- }
- function getSuspendedCache() {
- {
- return null;
- } // This function is called when a Suspense boundary suspends. It returns the
- }
- var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner;
- var didReceiveUpdate = false;
- var didWarnAboutBadClass;
- var didWarnAboutModulePatternComponent;
- var didWarnAboutContextTypeOnFunctionComponent;
- var didWarnAboutGetDerivedStateOnFunctionComponent;
- var didWarnAboutFunctionRefs;
- var didWarnAboutReassigningProps;
- var didWarnAboutRevealOrder;
- var didWarnAboutTailOptions;
- {
- didWarnAboutBadClass = {};
- didWarnAboutModulePatternComponent = {};
- didWarnAboutContextTypeOnFunctionComponent = {};
- didWarnAboutGetDerivedStateOnFunctionComponent = {};
- didWarnAboutFunctionRefs = {};
- didWarnAboutReassigningProps = false;
- didWarnAboutRevealOrder = {};
- didWarnAboutTailOptions = {};
- }
- function reconcileChildren(current, workInProgress, nextChildren, renderLanes) {
- if (current === null) {
- // If this is a fresh new component that hasn't been rendered yet, we
- // won't update its child set by applying minimal side-effects. Instead,
- // we will add them all to the child before it gets rendered. That means
- // we can optimize this reconciliation pass by not tracking side-effects.
- workInProgress.child = mountChildFibers(workInProgress, null, nextChildren, renderLanes);
- } else {
- // If the current child is the same as the work in progress, it means that
- // we haven't yet started any work on these children. Therefore, we use
- // the clone algorithm to create a copy of all the current children.
- // If we had any progressed work already, that is invalid at this point so
- // let's throw it out.
- workInProgress.child = reconcileChildFibers(workInProgress, current.child, nextChildren, renderLanes);
- }
- }
- function forceUnmountCurrentAndReconcile(current, workInProgress, nextChildren, renderLanes) {
- // This function is fork of reconcileChildren. It's used in cases where we
- // want to reconcile without matching against the existing set. This has the
- // effect of all current children being unmounted; even if the type and key
- // are the same, the old child is unmounted and a new child is created.
- //
- // To do this, we're going to go through the reconcile algorithm twice. In
- // the first pass, we schedule a deletion for all the current children by
- // passing null.
- workInProgress.child = reconcileChildFibers(workInProgress, current.child, null, renderLanes); // In the second pass, we mount the new children. The trick here is that we
- // pass null in place of where we usually pass the current child set. This has
- // the effect of remounting all children regardless of whether their
- // identities match.
- workInProgress.child = reconcileChildFibers(workInProgress, null, nextChildren, renderLanes);
- }
- function updateForwardRef(current, workInProgress, Component, nextProps, renderLanes) {
- // TODO: current can be non-null here even if the component
- // hasn't yet mounted. This happens after the first render suspends.
- // We'll need to figure out if this is fine or can cause issues.
- {
- if (workInProgress.type !== workInProgress.elementType) {
- // Lazy component props can't be validated in createElement
- // because they're only guaranteed to be resolved here.
- var innerPropTypes = Component.propTypes;
- if (innerPropTypes) {
- checkPropTypes(innerPropTypes, nextProps, // Resolved props
- 'prop', getComponentNameFromType(Component));
- }
- }
- }
- var render = Component.render;
- var ref = workInProgress.ref; // The rest is a fork of updateFunctionComponent
- var nextChildren;
- var hasId;
- prepareToReadContext(workInProgress, renderLanes);
- {
- markComponentRenderStarted(workInProgress);
- }
- {
- ReactCurrentOwner$1.current = workInProgress;
- setIsRendering(true);
- nextChildren = renderWithHooks(current, workInProgress, render, nextProps, ref, renderLanes);
- hasId = checkDidRenderIdHook();
- if (workInProgress.mode & StrictLegacyMode) {
- setIsStrictModeForDevtools(true);
- try {
- nextChildren = renderWithHooks(current, workInProgress, render, nextProps, ref, renderLanes);
- hasId = checkDidRenderIdHook();
- } finally {
- setIsStrictModeForDevtools(false);
- }
- }
- setIsRendering(false);
- }
- {
- markComponentRenderStopped();
- }
- if (current !== null && !didReceiveUpdate) {
- bailoutHooks(current, workInProgress, renderLanes);
- return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);
- }
- if (getIsHydrating() && hasId) {
- pushMaterializedTreeId(workInProgress);
- } // React DevTools reads this flag.
- workInProgress.flags |= PerformedWork;
- reconcileChildren(current, workInProgress, nextChildren, renderLanes);
- return workInProgress.child;
- }
- function updateMemoComponent(current, workInProgress, Component, nextProps, renderLanes) {
- if (current === null) {
- var type = Component.type;
- if (isSimpleFunctionComponent(type) && Component.compare === null && // SimpleMemoComponent codepath doesn't resolve outer props either.
- Component.defaultProps === undefined) {
- var resolvedType = type;
- {
- resolvedType = resolveFunctionForHotReloading(type);
- } // If this is a plain function component without default props,
- // and with only the default shallow comparison, we upgrade it
- // to a SimpleMemoComponent to allow fast path updates.
- workInProgress.tag = SimpleMemoComponent;
- workInProgress.type = resolvedType;
- {
- validateFunctionComponentInDev(workInProgress, type);
- }
- return updateSimpleMemoComponent(current, workInProgress, resolvedType, nextProps, renderLanes);
- }
- {
- var innerPropTypes = type.propTypes;
- if (innerPropTypes) {
- // Inner memo component props aren't currently validated in createElement.
- // We could move it there, but we'd still need this for lazy code path.
- checkPropTypes(innerPropTypes, nextProps, // Resolved props
- 'prop', getComponentNameFromType(type));
- }
- }
- var child = createFiberFromTypeAndProps(Component.type, null, nextProps, workInProgress, workInProgress.mode, renderLanes);
- child.ref = workInProgress.ref;
- child.return = workInProgress;
- workInProgress.child = child;
- return child;
- }
- {
- var _type = Component.type;
- var _innerPropTypes = _type.propTypes;
- if (_innerPropTypes) {
- // Inner memo component props aren't currently validated in createElement.
- // We could move it there, but we'd still need this for lazy code path.
- checkPropTypes(_innerPropTypes, nextProps, // Resolved props
- 'prop', getComponentNameFromType(_type));
- }
- }
- var currentChild = current.child; // This is always exactly one child
- var hasScheduledUpdateOrContext = checkScheduledUpdateOrContext(current, renderLanes);
- if (!hasScheduledUpdateOrContext) {
- // This will be the props with resolved defaultProps,
- // unlike current.memoizedProps which will be the unresolved ones.
- var prevProps = currentChild.memoizedProps; // Default to shallow comparison
- var compare = Component.compare;
- compare = compare !== null ? compare : shallowEqual;
- if (compare(prevProps, nextProps) && current.ref === workInProgress.ref) {
- return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);
- }
- } // React DevTools reads this flag.
- workInProgress.flags |= PerformedWork;
- var newChild = createWorkInProgress(currentChild, nextProps);
- newChild.ref = workInProgress.ref;
- newChild.return = workInProgress;
- workInProgress.child = newChild;
- return newChild;
- }
- function updateSimpleMemoComponent(current, workInProgress, Component, nextProps, renderLanes) {
- // TODO: current can be non-null here even if the component
- // hasn't yet mounted. This happens when the inner render suspends.
- // We'll need to figure out if this is fine or can cause issues.
- {
- if (workInProgress.type !== workInProgress.elementType) {
- // Lazy component props can't be validated in createElement
- // because they're only guaranteed to be resolved here.
- var outerMemoType = workInProgress.elementType;
- if (outerMemoType.$$typeof === REACT_LAZY_TYPE) {
- // We warn when you define propTypes on lazy()
- // so let's just skip over it to find memo() outer wrapper.
- // Inner props for memo are validated later.
- var lazyComponent = outerMemoType;
- var payload = lazyComponent._payload;
- var init = lazyComponent._init;
- try {
- outerMemoType = init(payload);
- } catch (x) {
- outerMemoType = null;
- } // Inner propTypes will be validated in the function component path.
- var outerPropTypes = outerMemoType && outerMemoType.propTypes;
- if (outerPropTypes) {
- checkPropTypes(outerPropTypes, nextProps, // Resolved (SimpleMemoComponent has no defaultProps)
- 'prop', getComponentNameFromType(outerMemoType));
- }
- }
- }
- }
- if (current !== null) {
- var prevProps = current.memoizedProps;
- if (shallowEqual(prevProps, nextProps) && current.ref === workInProgress.ref && ( // Prevent bailout if the implementation changed due to hot reload.
- workInProgress.type === current.type)) {
- didReceiveUpdate = false; // The props are shallowly equal. Reuse the previous props object, like we
- // would during a normal fiber bailout.
- //
- // We don't have strong guarantees that the props object is referentially
- // equal during updates where we can't bail out anyway — like if the props
- // are shallowly equal, but there's a local state or context update in the
- // same batch.
- //
- // However, as a principle, we should aim to make the behavior consistent
- // across different ways of memoizing a component. For example, React.memo
- // has a different internal Fiber layout if you pass a normal function
- // component (SimpleMemoComponent) versus if you pass a different type
- // like forwardRef (MemoComponent). But this is an implementation detail.
- // Wrapping a component in forwardRef (or React.lazy, etc) shouldn't
- // affect whether the props object is reused during a bailout.
- workInProgress.pendingProps = nextProps = prevProps;
- if (!checkScheduledUpdateOrContext(current, renderLanes)) {
- // The pending lanes were cleared at the beginning of beginWork. We're
- // about to bail out, but there might be other lanes that weren't
- // included in the current render. Usually, the priority level of the
- // remaining updates is accumulated during the evaluation of the
- // component (i.e. when processing the update queue). But since since
- // we're bailing out early *without* evaluating the component, we need
- // to account for it here, too. Reset to the value of the current fiber.
- // NOTE: This only applies to SimpleMemoComponent, not MemoComponent,
- // because a MemoComponent fiber does not have hooks or an update queue;
- // rather, it wraps around an inner component, which may or may not
- // contains hooks.
- // TODO: Move the reset at in beginWork out of the common path so that
- // this is no longer necessary.
- workInProgress.lanes = current.lanes;
- return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);
- } else if ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags) {
- // This is a special case that only exists for legacy mode.
- // See https://github.com/facebook/react/pull/19216.
- didReceiveUpdate = true;
- }
- }
- }
- return updateFunctionComponent(current, workInProgress, Component, nextProps, renderLanes);
- }
- function updateOffscreenComponent(current, workInProgress, renderLanes) {
- var nextProps = workInProgress.pendingProps;
- var nextChildren = nextProps.children;
- var prevState = current !== null ? current.memoizedState : null;
- if (nextProps.mode === 'hidden' || enableLegacyHidden) {
- // Rendering a hidden tree.
- if ((workInProgress.mode & ConcurrentMode) === NoMode) {
- // In legacy sync mode, don't defer the subtree. Render it now.
- // TODO: Consider how Offscreen should work with transitions in the future
- var nextState = {
- baseLanes: NoLanes,
- cachePool: null,
- transitions: null
- };
- workInProgress.memoizedState = nextState;
- pushRenderLanes(workInProgress, renderLanes);
- } else if (!includesSomeLane(renderLanes, OffscreenLane)) {
- var spawnedCachePool = null; // We're hidden, and we're not rendering at Offscreen. We will bail out
- // and resume this tree later.
- var nextBaseLanes;
- if (prevState !== null) {
- var prevBaseLanes = prevState.baseLanes;
- nextBaseLanes = mergeLanes(prevBaseLanes, renderLanes);
- } else {
- nextBaseLanes = renderLanes;
- } // Schedule this fiber to re-render at offscreen priority. Then bailout.
- workInProgress.lanes = workInProgress.childLanes = laneToLanes(OffscreenLane);
- var _nextState = {
- baseLanes: nextBaseLanes,
- cachePool: spawnedCachePool,
- transitions: null
- };
- workInProgress.memoizedState = _nextState;
- workInProgress.updateQueue = null;
- // to avoid a push/pop misalignment.
- pushRenderLanes(workInProgress, nextBaseLanes);
- return null;
- } else {
- // This is the second render. The surrounding visible content has already
- // committed. Now we resume rendering the hidden tree.
- // Rendering at offscreen, so we can clear the base lanes.
- var _nextState2 = {
- baseLanes: NoLanes,
- cachePool: null,
- transitions: null
- };
- workInProgress.memoizedState = _nextState2; // Push the lanes that were skipped when we bailed out.
- var subtreeRenderLanes = prevState !== null ? prevState.baseLanes : renderLanes;
- pushRenderLanes(workInProgress, subtreeRenderLanes);
- }
- } else {
- // Rendering a visible tree.
- var _subtreeRenderLanes;
- if (prevState !== null) {
- // We're going from hidden -> visible.
- _subtreeRenderLanes = mergeLanes(prevState.baseLanes, renderLanes);
- workInProgress.memoizedState = null;
- } else {
- // We weren't previously hidden, and we still aren't, so there's nothing
- // special to do. Need to push to the stack regardless, though, to avoid
- // a push/pop misalignment.
- _subtreeRenderLanes = renderLanes;
- }
- pushRenderLanes(workInProgress, _subtreeRenderLanes);
- }
- reconcileChildren(current, workInProgress, nextChildren, renderLanes);
- return workInProgress.child;
- } // Note: These happen to have identical begin phases, for now. We shouldn't hold
- function updateFragment(current, workInProgress, renderLanes) {
- var nextChildren = workInProgress.pendingProps;
- reconcileChildren(current, workInProgress, nextChildren, renderLanes);
- return workInProgress.child;
- }
- function updateMode(current, workInProgress, renderLanes) {
- var nextChildren = workInProgress.pendingProps.children;
- reconcileChildren(current, workInProgress, nextChildren, renderLanes);
- return workInProgress.child;
- }
- function updateProfiler(current, workInProgress, renderLanes) {
- {
- workInProgress.flags |= Update;
- {
- // Reset effect durations for the next eventual effect phase.
- // These are reset during render to allow the DevTools commit hook a chance to read them,
- var stateNode = workInProgress.stateNode;
- stateNode.effectDuration = 0;
- stateNode.passiveEffectDuration = 0;
- }
- }
- var nextProps = workInProgress.pendingProps;
- var nextChildren = nextProps.children;
- reconcileChildren(current, workInProgress, nextChildren, renderLanes);
- return workInProgress.child;
- }
- function markRef(current, workInProgress) {
- var ref = workInProgress.ref;
- if (current === null && ref !== null || current !== null && current.ref !== ref) {
- // Schedule a Ref effect
- workInProgress.flags |= Ref;
- {
- workInProgress.flags |= RefStatic;
- }
- }
- }
- function updateFunctionComponent(current, workInProgress, Component, nextProps, renderLanes) {
- {
- if (workInProgress.type !== workInProgress.elementType) {
- // Lazy component props can't be validated in createElement
- // because they're only guaranteed to be resolved here.
- var innerPropTypes = Component.propTypes;
- if (innerPropTypes) {
- checkPropTypes(innerPropTypes, nextProps, // Resolved props
- 'prop', getComponentNameFromType(Component));
- }
- }
- }
- var context;
- {
- var unmaskedContext = getUnmaskedContext(workInProgress, Component, true);
- context = getMaskedContext(workInProgress, unmaskedContext);
- }
- var nextChildren;
- var hasId;
- prepareToReadContext(workInProgress, renderLanes);
- {
- markComponentRenderStarted(workInProgress);
- }
- {
- ReactCurrentOwner$1.current = workInProgress;
- setIsRendering(true);
- nextChildren = renderWithHooks(current, workInProgress, Component, nextProps, context, renderLanes);
- hasId = checkDidRenderIdHook();
- if (workInProgress.mode & StrictLegacyMode) {
- setIsStrictModeForDevtools(true);
- try {
- nextChildren = renderWithHooks(current, workInProgress, Component, nextProps, context, renderLanes);
- hasId = checkDidRenderIdHook();
- } finally {
- setIsStrictModeForDevtools(false);
- }
- }
- setIsRendering(false);
- }
- {
- markComponentRenderStopped();
- }
- if (current !== null && !didReceiveUpdate) {
- bailoutHooks(current, workInProgress, renderLanes);
- return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);
- }
- if (getIsHydrating() && hasId) {
- pushMaterializedTreeId(workInProgress);
- } // React DevTools reads this flag.
- workInProgress.flags |= PerformedWork;
- reconcileChildren(current, workInProgress, nextChildren, renderLanes);
- return workInProgress.child;
- }
- function updateClassComponent(current, workInProgress, Component, nextProps, renderLanes) {
- {
- // This is used by DevTools to force a boundary to error.
- switch (shouldError(workInProgress)) {
- case false:
- {
- var _instance = workInProgress.stateNode;
- var ctor = workInProgress.type; // TODO This way of resetting the error boundary state is a hack.
- // Is there a better way to do this?
- var tempInstance = new ctor(workInProgress.memoizedProps, _instance.context);
- var state = tempInstance.state;
- _instance.updater.enqueueSetState(_instance, state, null);
- break;
- }
- case true:
- {
- workInProgress.flags |= DidCapture;
- workInProgress.flags |= ShouldCapture; // eslint-disable-next-line react-internal/prod-error-codes
- var error$1 = new Error('Simulated error coming from DevTools');
- var lane = pickArbitraryLane(renderLanes);
- workInProgress.lanes = mergeLanes(workInProgress.lanes, lane); // Schedule the error boundary to re-render using updated state
- var update = createClassErrorUpdate(workInProgress, createCapturedValueAtFiber(error$1, workInProgress), lane);
- enqueueCapturedUpdate(workInProgress, update);
- break;
- }
- }
- if (workInProgress.type !== workInProgress.elementType) {
- // Lazy component props can't be validated in createElement
- // because they're only guaranteed to be resolved here.
- var innerPropTypes = Component.propTypes;
- if (innerPropTypes) {
- checkPropTypes(innerPropTypes, nextProps, // Resolved props
- 'prop', getComponentNameFromType(Component));
- }
- }
- } // Push context providers early to prevent context stack mismatches.
- // During mounting we don't know the child context yet as the instance doesn't exist.
- // We will invalidate the child context in finishClassComponent() right after rendering.
- var hasContext;
- if (isContextProvider(Component)) {
- hasContext = true;
- pushContextProvider(workInProgress);
- } else {
- hasContext = false;
- }
- prepareToReadContext(workInProgress, renderLanes);
- var instance = workInProgress.stateNode;
- var shouldUpdate;
- if (instance === null) {
- resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress); // In the initial pass we might need to construct the instance.
- constructClassInstance(workInProgress, Component, nextProps);
- mountClassInstance(workInProgress, Component, nextProps, renderLanes);
- shouldUpdate = true;
- } else if (current === null) {
- // In a resume, we'll already have an instance we can reuse.
- shouldUpdate = resumeMountClassInstance(workInProgress, Component, nextProps, renderLanes);
- } else {
- shouldUpdate = updateClassInstance(current, workInProgress, Component, nextProps, renderLanes);
- }
- var nextUnitOfWork = finishClassComponent(current, workInProgress, Component, shouldUpdate, hasContext, renderLanes);
- {
- var inst = workInProgress.stateNode;
- if (shouldUpdate && inst.props !== nextProps) {
- if (!didWarnAboutReassigningProps) {
- error('It looks like %s is reassigning its own `this.props` while rendering. ' + 'This is not supported and can lead to confusing bugs.', getComponentNameFromFiber(workInProgress) || 'a component');
- }
- didWarnAboutReassigningProps = true;
- }
- }
- return nextUnitOfWork;
- }
- function finishClassComponent(current, workInProgress, Component, shouldUpdate, hasContext, renderLanes) {
- // Refs should update even if shouldComponentUpdate returns false
- markRef(current, workInProgress);
- var didCaptureError = (workInProgress.flags & DidCapture) !== NoFlags;
- if (!shouldUpdate && !didCaptureError) {
- // Context providers should defer to sCU for rendering
- if (hasContext) {
- invalidateContextProvider(workInProgress, Component, false);
- }
- return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);
- }
- var instance = workInProgress.stateNode; // Rerender
- ReactCurrentOwner$1.current = workInProgress;
- var nextChildren;
- if (didCaptureError && typeof Component.getDerivedStateFromError !== 'function') {
- // If we captured an error, but getDerivedStateFromError is not defined,
- // unmount all the children. componentDidCatch will schedule an update to
- // re-render a fallback. This is temporary until we migrate everyone to
- // the new API.
- // TODO: Warn in a future release.
- nextChildren = null;
- {
- stopProfilerTimerIfRunning();
- }
- } else {
- {
- markComponentRenderStarted(workInProgress);
- }
- {
- setIsRendering(true);
- nextChildren = instance.render();
- if (workInProgress.mode & StrictLegacyMode) {
- setIsStrictModeForDevtools(true);
- try {
- instance.render();
- } finally {
- setIsStrictModeForDevtools(false);
- }
- }
- setIsRendering(false);
- }
- {
- markComponentRenderStopped();
- }
- } // React DevTools reads this flag.
- workInProgress.flags |= PerformedWork;
- if (current !== null && didCaptureError) {
- // If we're recovering from an error, reconcile without reusing any of
- // the existing children. Conceptually, the normal children and the children
- // that are shown on error are two different sets, so we shouldn't reuse
- // normal children even if their identities match.
- forceUnmountCurrentAndReconcile(current, workInProgress, nextChildren, renderLanes);
- } else {
- reconcileChildren(current, workInProgress, nextChildren, renderLanes);
- } // Memoize state using the values we just used to render.
- // TODO: Restructure so we never read values from the instance.
- workInProgress.memoizedState = instance.state; // The context might have changed so we need to recalculate it.
- if (hasContext) {
- invalidateContextProvider(workInProgress, Component, true);
- }
- return workInProgress.child;
- }
- function pushHostRootContext(workInProgress) {
- var root = workInProgress.stateNode;
- if (root.pendingContext) {
- pushTopLevelContextObject(workInProgress, root.pendingContext, root.pendingContext !== root.context);
- } else if (root.context) {
- // Should always be set
- pushTopLevelContextObject(workInProgress, root.context, false);
- }
- pushHostContainer(workInProgress, root.containerInfo);
- }
- function updateHostRoot(current, workInProgress, renderLanes) {
- pushHostRootContext(workInProgress);
- if (current === null) {
- throw new Error('Should have a current fiber. This is a bug in React.');
- }
- var nextProps = workInProgress.pendingProps;
- var prevState = workInProgress.memoizedState;
- var prevChildren = prevState.element;
- cloneUpdateQueue(current, workInProgress);
- processUpdateQueue(workInProgress, nextProps, null, renderLanes);
- var nextState = workInProgress.memoizedState;
- var root = workInProgress.stateNode;
- // being called "element".
- var nextChildren = nextState.element;
- if (prevState.isDehydrated) {
- // This is a hydration root whose shell has not yet hydrated. We should
- // attempt to hydrate.
- // Flip isDehydrated to false to indicate that when this render
- // finishes, the root will no longer be dehydrated.
- var overrideState = {
- element: nextChildren,
- isDehydrated: false,
- cache: nextState.cache,
- pendingSuspenseBoundaries: nextState.pendingSuspenseBoundaries,
- transitions: nextState.transitions
- };
- var updateQueue = workInProgress.updateQueue; // `baseState` can always be the last state because the root doesn't
- // have reducer functions so it doesn't need rebasing.
- updateQueue.baseState = overrideState;
- workInProgress.memoizedState = overrideState;
- if (workInProgress.flags & ForceClientRender) {
- // Something errored during a previous attempt to hydrate the shell, so we
- // forced a client render.
- var recoverableError = createCapturedValueAtFiber(new Error('There was an error while hydrating. Because the error happened outside ' + 'of a Suspense boundary, the entire root will switch to ' + 'client rendering.'), workInProgress);
- return mountHostRootWithoutHydrating(current, workInProgress, nextChildren, renderLanes, recoverableError);
- } else if (nextChildren !== prevChildren) {
- var _recoverableError = createCapturedValueAtFiber(new Error('This root received an early update, before anything was able ' + 'hydrate. Switched the entire root to client rendering.'), workInProgress);
- return mountHostRootWithoutHydrating(current, workInProgress, nextChildren, renderLanes, _recoverableError);
- } else {
- // The outermost shell has not hydrated yet. Start hydrating.
- enterHydrationState(workInProgress);
- var child = mountChildFibers(workInProgress, null, nextChildren, renderLanes);
- workInProgress.child = child;
- var node = child;
- while (node) {
- // Mark each child as hydrating. This is a fast path to know whether this
- // tree is part of a hydrating tree. This is used to determine if a child
- // node has fully mounted yet, and for scheduling event replaying.
- // Conceptually this is similar to Placement in that a new subtree is
- // inserted into the React tree here. It just happens to not need DOM
- // mutations because it already exists.
- node.flags = node.flags & ~Placement | Hydrating;
- node = node.sibling;
- }
- }
- } else {
- // Root is not dehydrated. Either this is a client-only root, or it
- // already hydrated.
- resetHydrationState();
- if (nextChildren === prevChildren) {
- return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);
- }
- reconcileChildren(current, workInProgress, nextChildren, renderLanes);
- }
- return workInProgress.child;
- }
- function mountHostRootWithoutHydrating(current, workInProgress, nextChildren, renderLanes, recoverableError) {
- // Revert to client rendering.
- resetHydrationState();
- queueHydrationError(recoverableError);
- workInProgress.flags |= ForceClientRender;
- reconcileChildren(current, workInProgress, nextChildren, renderLanes);
- return workInProgress.child;
- }
- function updateHostComponent(current, workInProgress, renderLanes) {
- pushHostContext(workInProgress);
- if (current === null) {
- tryToClaimNextHydratableInstance(workInProgress);
- }
- var type = workInProgress.type;
- var nextProps = workInProgress.pendingProps;
- var prevProps = current !== null ? current.memoizedProps : null;
- var nextChildren = nextProps.children;
- var isDirectTextChild = shouldSetTextContent(type, nextProps);
- if (isDirectTextChild) {
- // We special case a direct text child of a host node. This is a common
- // case. We won't handle it as a reified child. We will instead handle
- // this in the host environment that also has access to this prop. That
- // avoids allocating another HostText fiber and traversing it.
- nextChildren = null;
- } else if (prevProps !== null && shouldSetTextContent(type, prevProps)) {
- // If we're switching from a direct text child to a normal child, or to
- // empty, we need to schedule the text content to be reset.
- workInProgress.flags |= ContentReset;
- }
- markRef(current, workInProgress);
- reconcileChildren(current, workInProgress, nextChildren, renderLanes);
- return workInProgress.child;
- }
- function updateHostText(current, workInProgress) {
- if (current === null) {
- tryToClaimNextHydratableInstance(workInProgress);
- } // Nothing to do here. This is terminal. We'll do the completion step
- // immediately after.
- return null;
- }
- function mountLazyComponent(_current, workInProgress, elementType, renderLanes) {
- resetSuspendedCurrentOnMountInLegacyMode(_current, workInProgress);
- var props = workInProgress.pendingProps;
- var lazyComponent = elementType;
- var payload = lazyComponent._payload;
- var init = lazyComponent._init;
- var Component = init(payload); // Store the unwrapped component in the type.
- workInProgress.type = Component;
- var resolvedTag = workInProgress.tag = resolveLazyComponentTag(Component);
- var resolvedProps = resolveDefaultProps(Component, props);
- var child;
- switch (resolvedTag) {
- case FunctionComponent:
- {
- {
- validateFunctionComponentInDev(workInProgress, Component);
- workInProgress.type = Component = resolveFunctionForHotReloading(Component);
- }
- child = updateFunctionComponent(null, workInProgress, Component, resolvedProps, renderLanes);
- return child;
- }
- case ClassComponent:
- {
- {
- workInProgress.type = Component = resolveClassForHotReloading(Component);
- }
- child = updateClassComponent(null, workInProgress, Component, resolvedProps, renderLanes);
- return child;
- }
- case ForwardRef:
- {
- {
- workInProgress.type = Component = resolveForwardRefForHotReloading(Component);
- }
- child = updateForwardRef(null, workInProgress, Component, resolvedProps, renderLanes);
- return child;
- }
- case MemoComponent:
- {
- {
- if (workInProgress.type !== workInProgress.elementType) {
- var outerPropTypes = Component.propTypes;
- if (outerPropTypes) {
- checkPropTypes(outerPropTypes, resolvedProps, // Resolved for outer only
- 'prop', getComponentNameFromType(Component));
- }
- }
- }
- child = updateMemoComponent(null, workInProgress, Component, resolveDefaultProps(Component.type, resolvedProps), // The inner type can have defaults too
- renderLanes);
- return child;
- }
- }
- var hint = '';
- {
- if (Component !== null && typeof Component === 'object' && Component.$$typeof === REACT_LAZY_TYPE) {
- hint = ' Did you wrap a component in React.lazy() more than once?';
- }
- } // This message intentionally doesn't mention ForwardRef or MemoComponent
- // because the fact that it's a separate type of work is an
- // implementation detail.
- throw new Error("Element type is invalid. Received a promise that resolves to: " + Component + ". " + ("Lazy element type must resolve to a class or function." + hint));
- }
- function mountIncompleteClassComponent(_current, workInProgress, Component, nextProps, renderLanes) {
- resetSuspendedCurrentOnMountInLegacyMode(_current, workInProgress); // Promote the fiber to a class and try rendering again.
- workInProgress.tag = ClassComponent; // The rest of this function is a fork of `updateClassComponent`
- // Push context providers early to prevent context stack mismatches.
- // During mounting we don't know the child context yet as the instance doesn't exist.
- // We will invalidate the child context in finishClassComponent() right after rendering.
- var hasContext;
- if (isContextProvider(Component)) {
- hasContext = true;
- pushContextProvider(workInProgress);
- } else {
- hasContext = false;
- }
- prepareToReadContext(workInProgress, renderLanes);
- constructClassInstance(workInProgress, Component, nextProps);
- mountClassInstance(workInProgress, Component, nextProps, renderLanes);
- return finishClassComponent(null, workInProgress, Component, true, hasContext, renderLanes);
- }
- function mountIndeterminateComponent(_current, workInProgress, Component, renderLanes) {
- resetSuspendedCurrentOnMountInLegacyMode(_current, workInProgress);
- var props = workInProgress.pendingProps;
- var context;
- {
- var unmaskedContext = getUnmaskedContext(workInProgress, Component, false);
- context = getMaskedContext(workInProgress, unmaskedContext);
- }
- prepareToReadContext(workInProgress, renderLanes);
- var value;
- var hasId;
- {
- markComponentRenderStarted(workInProgress);
- }
- {
- if (Component.prototype && typeof Component.prototype.render === 'function') {
- var componentName = getComponentNameFromType(Component) || 'Unknown';
- if (!didWarnAboutBadClass[componentName]) {
- error("The <%s /> component appears to have a render method, but doesn't extend React.Component. " + 'This is likely to cause errors. Change %s to extend React.Component instead.', componentName, componentName);
- didWarnAboutBadClass[componentName] = true;
- }
- }
- if (workInProgress.mode & StrictLegacyMode) {
- ReactStrictModeWarnings.recordLegacyContextWarning(workInProgress, null);
- }
- setIsRendering(true);
- ReactCurrentOwner$1.current = workInProgress;
- value = renderWithHooks(null, workInProgress, Component, props, context, renderLanes);
- hasId = checkDidRenderIdHook();
- setIsRendering(false);
- }
- {
- markComponentRenderStopped();
- } // React DevTools reads this flag.
- workInProgress.flags |= PerformedWork;
- {
- // Support for module components is deprecated and is removed behind a flag.
- // Whether or not it would crash later, we want to show a good message in DEV first.
- if (typeof value === 'object' && value !== null && typeof value.render === 'function' && value.$$typeof === undefined) {
- var _componentName = getComponentNameFromType(Component) || 'Unknown';
- if (!didWarnAboutModulePatternComponent[_componentName]) {
- error('The <%s /> component appears to be a function component that returns a class instance. ' + 'Change %s to a class that extends React.Component instead. ' + "If you can't use a class try assigning the prototype on the function as a workaround. " + "`%s.prototype = React.Component.prototype`. Don't use an arrow function since it " + 'cannot be called with `new` by React.', _componentName, _componentName, _componentName);
- didWarnAboutModulePatternComponent[_componentName] = true;
- }
- }
- }
- if ( // Run these checks in production only if the flag is off.
- // Eventually we'll delete this branch altogether.
- typeof value === 'object' && value !== null && typeof value.render === 'function' && value.$$typeof === undefined) {
- {
- var _componentName2 = getComponentNameFromType(Component) || 'Unknown';
- if (!didWarnAboutModulePatternComponent[_componentName2]) {
- error('The <%s /> component appears to be a function component that returns a class instance. ' + 'Change %s to a class that extends React.Component instead. ' + "If you can't use a class try assigning the prototype on the function as a workaround. " + "`%s.prototype = React.Component.prototype`. Don't use an arrow function since it " + 'cannot be called with `new` by React.', _componentName2, _componentName2, _componentName2);
- didWarnAboutModulePatternComponent[_componentName2] = true;
- }
- } // Proceed under the assumption that this is a class instance
- workInProgress.tag = ClassComponent; // Throw out any hooks that were used.
- workInProgress.memoizedState = null;
- workInProgress.updateQueue = null; // Push context providers early to prevent context stack mismatches.
- // During mounting we don't know the child context yet as the instance doesn't exist.
- // We will invalidate the child context in finishClassComponent() right after rendering.
- var hasContext = false;
- if (isContextProvider(Component)) {
- hasContext = true;
- pushContextProvider(workInProgress);
- } else {
- hasContext = false;
- }
- workInProgress.memoizedState = value.state !== null && value.state !== undefined ? value.state : null;
- initializeUpdateQueue(workInProgress);
- adoptClassInstance(workInProgress, value);
- mountClassInstance(workInProgress, Component, props, renderLanes);
- return finishClassComponent(null, workInProgress, Component, true, hasContext, renderLanes);
- } else {
- // Proceed under the assumption that this is a function component
- workInProgress.tag = FunctionComponent;
- {
- if (workInProgress.mode & StrictLegacyMode) {
- setIsStrictModeForDevtools(true);
- try {
- value = renderWithHooks(null, workInProgress, Component, props, context, renderLanes);
- hasId = checkDidRenderIdHook();
- } finally {
- setIsStrictModeForDevtools(false);
- }
- }
- }
- if (getIsHydrating() && hasId) {
- pushMaterializedTreeId(workInProgress);
- }
- reconcileChildren(null, workInProgress, value, renderLanes);
- {
- validateFunctionComponentInDev(workInProgress, Component);
- }
- return workInProgress.child;
- }
- }
- function validateFunctionComponentInDev(workInProgress, Component) {
- {
- if (Component) {
- if (Component.childContextTypes) {
- error('%s(...): childContextTypes cannot be defined on a function component.', Component.displayName || Component.name || 'Component');
- }
- }
- if (workInProgress.ref !== null) {
- var info = '';
- var ownerName = getCurrentFiberOwnerNameInDevOrNull();
- if (ownerName) {
- info += '\n\nCheck the render method of `' + ownerName + '`.';
- }
- var warningKey = ownerName || '';
- var debugSource = workInProgress._debugSource;
- if (debugSource) {
- warningKey = debugSource.fileName + ':' + debugSource.lineNumber;
- }
- if (!didWarnAboutFunctionRefs[warningKey]) {
- didWarnAboutFunctionRefs[warningKey] = true;
- error('Function components cannot be given refs. ' + 'Attempts to access this ref will fail. ' + 'Did you mean to use React.forwardRef()?%s', info);
- }
- }
- if (typeof Component.getDerivedStateFromProps === 'function') {
- var _componentName3 = getComponentNameFromType(Component) || 'Unknown';
- if (!didWarnAboutGetDerivedStateOnFunctionComponent[_componentName3]) {
- error('%s: Function components do not support getDerivedStateFromProps.', _componentName3);
- didWarnAboutGetDerivedStateOnFunctionComponent[_componentName3] = true;
- }
- }
- if (typeof Component.contextType === 'object' && Component.contextType !== null) {
- var _componentName4 = getComponentNameFromType(Component) || 'Unknown';
- if (!didWarnAboutContextTypeOnFunctionComponent[_componentName4]) {
- error('%s: Function components do not support contextType.', _componentName4);
- didWarnAboutContextTypeOnFunctionComponent[_componentName4] = true;
- }
- }
- }
- }
- var SUSPENDED_MARKER = {
- dehydrated: null,
- treeContext: null,
- retryLane: NoLane
- };
- function mountSuspenseOffscreenState(renderLanes) {
- return {
- baseLanes: renderLanes,
- cachePool: getSuspendedCache(),
- transitions: null
- };
- }
- function updateSuspenseOffscreenState(prevOffscreenState, renderLanes) {
- var cachePool = null;
- return {
- baseLanes: mergeLanes(prevOffscreenState.baseLanes, renderLanes),
- cachePool: cachePool,
- transitions: prevOffscreenState.transitions
- };
- } // TODO: Probably should inline this back
- function shouldRemainOnFallback(suspenseContext, current, workInProgress, renderLanes) {
- // If we're already showing a fallback, there are cases where we need to
- // remain on that fallback regardless of whether the content has resolved.
- // For example, SuspenseList coordinates when nested content appears.
- if (current !== null) {
- var suspenseState = current.memoizedState;
- if (suspenseState === null) {
- // Currently showing content. Don't hide it, even if ForceSuspenseFallback
- // is true. More precise name might be "ForceRemainSuspenseFallback".
- // Note: This is a factoring smell. Can't remain on a fallback if there's
- // no fallback to remain on.
- return false;
- }
- } // Not currently showing content. Consult the Suspense context.
- return hasSuspenseContext(suspenseContext, ForceSuspenseFallback);
- }
- function getRemainingWorkInPrimaryTree(current, renderLanes) {
- // TODO: Should not remove render lanes that were pinged during this render
- return removeLanes(current.childLanes, renderLanes);
- }
- function updateSuspenseComponent(current, workInProgress, renderLanes) {
- var nextProps = workInProgress.pendingProps; // This is used by DevTools to force a boundary to suspend.
- {
- if (shouldSuspend(workInProgress)) {
- workInProgress.flags |= DidCapture;
- }
- }
- var suspenseContext = suspenseStackCursor.current;
- var showFallback = false;
- var didSuspend = (workInProgress.flags & DidCapture) !== NoFlags;
- if (didSuspend || shouldRemainOnFallback(suspenseContext, current)) {
- // Something in this boundary's subtree already suspended. Switch to
- // rendering the fallback children.
- showFallback = true;
- workInProgress.flags &= ~DidCapture;
- } else {
- // Attempting the main content
- if (current === null || current.memoizedState !== null) {
- // This is a new mount or this boundary is already showing a fallback state.
- // Mark this subtree context as having at least one invisible parent that could
- // handle the fallback state.
- // Avoided boundaries are not considered since they cannot handle preferred fallback states.
- {
- suspenseContext = addSubtreeSuspenseContext(suspenseContext, InvisibleParentSuspenseContext);
- }
- }
- }
- suspenseContext = setDefaultShallowSuspenseContext(suspenseContext);
- pushSuspenseContext(workInProgress, suspenseContext); // OK, the next part is confusing. We're about to reconcile the Suspense
- // boundary's children. This involves some custom reconciliation logic. Two
- // main reasons this is so complicated.
- //
- // First, Legacy Mode has different semantics for backwards compatibility. The
- // primary tree will commit in an inconsistent state, so when we do the
- // second pass to render the fallback, we do some exceedingly, uh, clever
- // hacks to make that not totally break. Like transferring effects and
- // deletions from hidden tree. In Concurrent Mode, it's much simpler,
- // because we bailout on the primary tree completely and leave it in its old
- // state, no effects. Same as what we do for Offscreen (except that
- // Offscreen doesn't have the first render pass).
- //
- // Second is hydration. During hydration, the Suspense fiber has a slightly
- // different layout, where the child points to a dehydrated fragment, which
- // contains the DOM rendered by the server.
- //
- // Third, even if you set all that aside, Suspense is like error boundaries in
- // that we first we try to render one tree, and if that fails, we render again
- // and switch to a different tree. Like a try/catch block. So we have to track
- // which branch we're currently rendering. Ideally we would model this using
- // a stack.
- if (current === null) {
- // Initial mount
- // Special path for hydration
- // If we're currently hydrating, try to hydrate this boundary.
- tryToClaimNextHydratableInstance(workInProgress); // This could've been a dehydrated suspense component.
- var suspenseState = workInProgress.memoizedState;
- if (suspenseState !== null) {
- var dehydrated = suspenseState.dehydrated;
- if (dehydrated !== null) {
- return mountDehydratedSuspenseComponent(workInProgress, dehydrated);
- }
- }
- var nextPrimaryChildren = nextProps.children;
- var nextFallbackChildren = nextProps.fallback;
- if (showFallback) {
- var fallbackFragment = mountSuspenseFallbackChildren(workInProgress, nextPrimaryChildren, nextFallbackChildren, renderLanes);
- var primaryChildFragment = workInProgress.child;
- primaryChildFragment.memoizedState = mountSuspenseOffscreenState(renderLanes);
- workInProgress.memoizedState = SUSPENDED_MARKER;
- return fallbackFragment;
- } else {
- return mountSuspensePrimaryChildren(workInProgress, nextPrimaryChildren);
- }
- } else {
- // This is an update.
- // Special path for hydration
- var prevState = current.memoizedState;
- if (prevState !== null) {
- var _dehydrated = prevState.dehydrated;
- if (_dehydrated !== null) {
- return updateDehydratedSuspenseComponent(current, workInProgress, didSuspend, nextProps, _dehydrated, prevState, renderLanes);
- }
- }
- if (showFallback) {
- var _nextFallbackChildren = nextProps.fallback;
- var _nextPrimaryChildren = nextProps.children;
- var fallbackChildFragment = updateSuspenseFallbackChildren(current, workInProgress, _nextPrimaryChildren, _nextFallbackChildren, renderLanes);
- var _primaryChildFragment2 = workInProgress.child;
- var prevOffscreenState = current.child.memoizedState;
- _primaryChildFragment2.memoizedState = prevOffscreenState === null ? mountSuspenseOffscreenState(renderLanes) : updateSuspenseOffscreenState(prevOffscreenState, renderLanes);
- _primaryChildFragment2.childLanes = getRemainingWorkInPrimaryTree(current, renderLanes);
- workInProgress.memoizedState = SUSPENDED_MARKER;
- return fallbackChildFragment;
- } else {
- var _nextPrimaryChildren2 = nextProps.children;
- var _primaryChildFragment3 = updateSuspensePrimaryChildren(current, workInProgress, _nextPrimaryChildren2, renderLanes);
- workInProgress.memoizedState = null;
- return _primaryChildFragment3;
- }
- }
- }
- function mountSuspensePrimaryChildren(workInProgress, primaryChildren, renderLanes) {
- var mode = workInProgress.mode;
- var primaryChildProps = {
- mode: 'visible',
- children: primaryChildren
- };
- var primaryChildFragment = mountWorkInProgressOffscreenFiber(primaryChildProps, mode);
- primaryChildFragment.return = workInProgress;
- workInProgress.child = primaryChildFragment;
- return primaryChildFragment;
- }
- function mountSuspenseFallbackChildren(workInProgress, primaryChildren, fallbackChildren, renderLanes) {
- var mode = workInProgress.mode;
- var progressedPrimaryFragment = workInProgress.child;
- var primaryChildProps = {
- mode: 'hidden',
- children: primaryChildren
- };
- var primaryChildFragment;
- var fallbackChildFragment;
- if ((mode & ConcurrentMode) === NoMode && progressedPrimaryFragment !== null) {
- // In legacy mode, we commit the primary tree as if it successfully
- // completed, even though it's in an inconsistent state.
- primaryChildFragment = progressedPrimaryFragment;
- primaryChildFragment.childLanes = NoLanes;
- primaryChildFragment.pendingProps = primaryChildProps;
- if (workInProgress.mode & ProfileMode) {
- // Reset the durations from the first pass so they aren't included in the
- // final amounts. This seems counterintuitive, since we're intentionally
- // not measuring part of the render phase, but this makes it match what we
- // do in Concurrent Mode.
- primaryChildFragment.actualDuration = 0;
- primaryChildFragment.actualStartTime = -1;
- primaryChildFragment.selfBaseDuration = 0;
- primaryChildFragment.treeBaseDuration = 0;
- }
- fallbackChildFragment = createFiberFromFragment(fallbackChildren, mode, renderLanes, null);
- } else {
- primaryChildFragment = mountWorkInProgressOffscreenFiber(primaryChildProps, mode);
- fallbackChildFragment = createFiberFromFragment(fallbackChildren, mode, renderLanes, null);
- }
- primaryChildFragment.return = workInProgress;
- fallbackChildFragment.return = workInProgress;
- primaryChildFragment.sibling = fallbackChildFragment;
- workInProgress.child = primaryChildFragment;
- return fallbackChildFragment;
- }
- function mountWorkInProgressOffscreenFiber(offscreenProps, mode, renderLanes) {
- // The props argument to `createFiberFromOffscreen` is `any` typed, so we use
- // this wrapper function to constrain it.
- return createFiberFromOffscreen(offscreenProps, mode, NoLanes, null);
- }
- function updateWorkInProgressOffscreenFiber(current, offscreenProps) {
- // The props argument to `createWorkInProgress` is `any` typed, so we use this
- // wrapper function to constrain it.
- return createWorkInProgress(current, offscreenProps);
- }
- function updateSuspensePrimaryChildren(current, workInProgress, primaryChildren, renderLanes) {
- var currentPrimaryChildFragment = current.child;
- var currentFallbackChildFragment = currentPrimaryChildFragment.sibling;
- var primaryChildFragment = updateWorkInProgressOffscreenFiber(currentPrimaryChildFragment, {
- mode: 'visible',
- children: primaryChildren
- });
- if ((workInProgress.mode & ConcurrentMode) === NoMode) {
- primaryChildFragment.lanes = renderLanes;
- }
- primaryChildFragment.return = workInProgress;
- primaryChildFragment.sibling = null;
- if (currentFallbackChildFragment !== null) {
- // Delete the fallback child fragment
- var deletions = workInProgress.deletions;
- if (deletions === null) {
- workInProgress.deletions = [currentFallbackChildFragment];
- workInProgress.flags |= ChildDeletion;
- } else {
- deletions.push(currentFallbackChildFragment);
- }
- }
- workInProgress.child = primaryChildFragment;
- return primaryChildFragment;
- }
- function updateSuspenseFallbackChildren(current, workInProgress, primaryChildren, fallbackChildren, renderLanes) {
- var mode = workInProgress.mode;
- var currentPrimaryChildFragment = current.child;
- var currentFallbackChildFragment = currentPrimaryChildFragment.sibling;
- var primaryChildProps = {
- mode: 'hidden',
- children: primaryChildren
- };
- var primaryChildFragment;
- if ( // In legacy mode, we commit the primary tree as if it successfully
- // completed, even though it's in an inconsistent state.
- (mode & ConcurrentMode) === NoMode && // Make sure we're on the second pass, i.e. the primary child fragment was
- // already cloned. In legacy mode, the only case where this isn't true is
- // when DevTools forces us to display a fallback; we skip the first render
- // pass entirely and go straight to rendering the fallback. (In Concurrent
- // Mode, SuspenseList can also trigger this scenario, but this is a legacy-
- // only codepath.)
- workInProgress.child !== currentPrimaryChildFragment) {
- var progressedPrimaryFragment = workInProgress.child;
- primaryChildFragment = progressedPrimaryFragment;
- primaryChildFragment.childLanes = NoLanes;
- primaryChildFragment.pendingProps = primaryChildProps;
- if (workInProgress.mode & ProfileMode) {
- // Reset the durations from the first pass so they aren't included in the
- // final amounts. This seems counterintuitive, since we're intentionally
- // not measuring part of the render phase, but this makes it match what we
- // do in Concurrent Mode.
- primaryChildFragment.actualDuration = 0;
- primaryChildFragment.actualStartTime = -1;
- primaryChildFragment.selfBaseDuration = currentPrimaryChildFragment.selfBaseDuration;
- primaryChildFragment.treeBaseDuration = currentPrimaryChildFragment.treeBaseDuration;
- } // The fallback fiber was added as a deletion during the first pass.
- // However, since we're going to remain on the fallback, we no longer want
- // to delete it.
- workInProgress.deletions = null;
- } else {
- primaryChildFragment = updateWorkInProgressOffscreenFiber(currentPrimaryChildFragment, primaryChildProps); // Since we're reusing a current tree, we need to reuse the flags, too.
- // (We don't do this in legacy mode, because in legacy mode we don't re-use
- // the current tree; see previous branch.)
- primaryChildFragment.subtreeFlags = currentPrimaryChildFragment.subtreeFlags & StaticMask;
- }
- var fallbackChildFragment;
- if (currentFallbackChildFragment !== null) {
- fallbackChildFragment = createWorkInProgress(currentFallbackChildFragment, fallbackChildren);
- } else {
- fallbackChildFragment = createFiberFromFragment(fallbackChildren, mode, renderLanes, null); // Needs a placement effect because the parent (the Suspense boundary) already
- // mounted but this is a new fiber.
- fallbackChildFragment.flags |= Placement;
- }
- fallbackChildFragment.return = workInProgress;
- primaryChildFragment.return = workInProgress;
- primaryChildFragment.sibling = fallbackChildFragment;
- workInProgress.child = primaryChildFragment;
- return fallbackChildFragment;
- }
- function retrySuspenseComponentWithoutHydrating(current, workInProgress, renderLanes, recoverableError) {
- // Falling back to client rendering. Because this has performance
- // implications, it's considered a recoverable error, even though the user
- // likely won't observe anything wrong with the UI.
- //
- // The error is passed in as an argument to enforce that every caller provide
- // a custom message, or explicitly opt out (currently the only path that opts
- // out is legacy mode; every concurrent path provides an error).
- if (recoverableError !== null) {
- queueHydrationError(recoverableError);
- } // This will add the old fiber to the deletion list
- reconcileChildFibers(workInProgress, current.child, null, renderLanes); // We're now not suspended nor dehydrated.
- var nextProps = workInProgress.pendingProps;
- var primaryChildren = nextProps.children;
- var primaryChildFragment = mountSuspensePrimaryChildren(workInProgress, primaryChildren); // Needs a placement effect because the parent (the Suspense boundary) already
- // mounted but this is a new fiber.
- primaryChildFragment.flags |= Placement;
- workInProgress.memoizedState = null;
- return primaryChildFragment;
- }
- function mountSuspenseFallbackAfterRetryWithoutHydrating(current, workInProgress, primaryChildren, fallbackChildren, renderLanes) {
- var fiberMode = workInProgress.mode;
- var primaryChildProps = {
- mode: 'visible',
- children: primaryChildren
- };
- var primaryChildFragment = mountWorkInProgressOffscreenFiber(primaryChildProps, fiberMode);
- var fallbackChildFragment = createFiberFromFragment(fallbackChildren, fiberMode, renderLanes, null); // Needs a placement effect because the parent (the Suspense
- // boundary) already mounted but this is a new fiber.
- fallbackChildFragment.flags |= Placement;
- primaryChildFragment.return = workInProgress;
- fallbackChildFragment.return = workInProgress;
- primaryChildFragment.sibling = fallbackChildFragment;
- workInProgress.child = primaryChildFragment;
- if ((workInProgress.mode & ConcurrentMode) !== NoMode) {
- // We will have dropped the effect list which contains the
- // deletion. We need to reconcile to delete the current child.
- reconcileChildFibers(workInProgress, current.child, null, renderLanes);
- }
- return fallbackChildFragment;
- }
- function mountDehydratedSuspenseComponent(workInProgress, suspenseInstance, renderLanes) {
- // During the first pass, we'll bail out and not drill into the children.
- // Instead, we'll leave the content in place and try to hydrate it later.
- if ((workInProgress.mode & ConcurrentMode) === NoMode) {
- {
- error('Cannot hydrate Suspense in legacy mode. Switch from ' + 'ReactDOM.hydrate(element, container) to ' + 'ReactDOMClient.hydrateRoot(container, <App />)' + '.render(element) or remove the Suspense components from ' + 'the server rendered components.');
- }
- workInProgress.lanes = laneToLanes(SyncLane);
- } else if (isSuspenseInstanceFallback(suspenseInstance)) {
- // This is a client-only boundary. Since we won't get any content from the server
- // for this, we need to schedule that at a higher priority based on when it would
- // have timed out. In theory we could render it in this pass but it would have the
- // wrong priority associated with it and will prevent hydration of parent path.
- // Instead, we'll leave work left on it to render it in a separate commit.
- // TODO This time should be the time at which the server rendered response that is
- // a parent to this boundary was displayed. However, since we currently don't have
- // a protocol to transfer that time, we'll just estimate it by using the current
- // time. This will mean that Suspense timeouts are slightly shifted to later than
- // they should be.
- // Schedule a normal pri update to render this content.
- workInProgress.lanes = laneToLanes(DefaultHydrationLane);
- } else {
- // We'll continue hydrating the rest at offscreen priority since we'll already
- // be showing the right content coming from the server, it is no rush.
- workInProgress.lanes = laneToLanes(OffscreenLane);
- }
- return null;
- }
- function updateDehydratedSuspenseComponent(current, workInProgress, didSuspend, nextProps, suspenseInstance, suspenseState, renderLanes) {
- if (!didSuspend) {
- // This is the first render pass. Attempt to hydrate.
- // We should never be hydrating at this point because it is the first pass,
- // but after we've already committed once.
- warnIfHydrating();
- if ((workInProgress.mode & ConcurrentMode) === NoMode) {
- return retrySuspenseComponentWithoutHydrating(current, workInProgress, renderLanes, // TODO: When we delete legacy mode, we should make this error argument
- // required — every concurrent mode path that causes hydration to
- // de-opt to client rendering should have an error message.
- null);
- }
- if (isSuspenseInstanceFallback(suspenseInstance)) {
- // This boundary is in a permanent fallback state. In this case, we'll never
- // get an update and we'll never be able to hydrate the final content. Let's just try the
- // client side render instead.
- var digest, message, stack;
- {
- var _getSuspenseInstanceF = getSuspenseInstanceFallbackErrorDetails(suspenseInstance);
- digest = _getSuspenseInstanceF.digest;
- message = _getSuspenseInstanceF.message;
- stack = _getSuspenseInstanceF.stack;
- }
- var error;
- if (message) {
- // eslint-disable-next-line react-internal/prod-error-codes
- error = new Error(message);
- } else {
- error = new Error('The server could not finish this Suspense boundary, likely ' + 'due to an error during server rendering. Switched to ' + 'client rendering.');
- }
- var capturedValue = createCapturedValue(error, digest, stack);
- return retrySuspenseComponentWithoutHydrating(current, workInProgress, renderLanes, capturedValue);
- }
- // any context has changed, we need to treat is as if the input might have changed.
- var hasContextChanged = includesSomeLane(renderLanes, current.childLanes);
- if (didReceiveUpdate || hasContextChanged) {
- // This boundary has changed since the first render. This means that we are now unable to
- // hydrate it. We might still be able to hydrate it using a higher priority lane.
- var root = getWorkInProgressRoot();
- if (root !== null) {
- var attemptHydrationAtLane = getBumpedLaneForHydration(root, renderLanes);
- if (attemptHydrationAtLane !== NoLane && attemptHydrationAtLane !== suspenseState.retryLane) {
- // Intentionally mutating since this render will get interrupted. This
- // is one of the very rare times where we mutate the current tree
- // during the render phase.
- suspenseState.retryLane = attemptHydrationAtLane; // TODO: Ideally this would inherit the event time of the current render
- var eventTime = NoTimestamp;
- enqueueConcurrentRenderForLane(current, attemptHydrationAtLane);
- scheduleUpdateOnFiber(root, current, attemptHydrationAtLane, eventTime);
- }
- } // If we have scheduled higher pri work above, this will probably just abort the render
- // since we now have higher priority work, but in case it doesn't, we need to prepare to
- // render something, if we time out. Even if that requires us to delete everything and
- // skip hydration.
- // Delay having to do this as long as the suspense timeout allows us.
- renderDidSuspendDelayIfPossible();
- var _capturedValue = createCapturedValue(new Error('This Suspense boundary received an update before it finished ' + 'hydrating. This caused the boundary to switch to client rendering. ' + 'The usual way to fix this is to wrap the original update ' + 'in startTransition.'));
- return retrySuspenseComponentWithoutHydrating(current, workInProgress, renderLanes, _capturedValue);
- } else if (isSuspenseInstancePending(suspenseInstance)) {
- // This component is still pending more data from the server, so we can't hydrate its
- // content. We treat it as if this component suspended itself. It might seem as if
- // we could just try to render it client-side instead. However, this will perform a
- // lot of unnecessary work and is unlikely to complete since it often will suspend
- // on missing data anyway. Additionally, the server might be able to render more
- // than we can on the client yet. In that case we'd end up with more fallback states
- // on the client than if we just leave it alone. If the server times out or errors
- // these should update this boundary to the permanent Fallback state instead.
- // Mark it as having captured (i.e. suspended).
- workInProgress.flags |= DidCapture; // Leave the child in place. I.e. the dehydrated fragment.
- workInProgress.child = current.child; // Register a callback to retry this boundary once the server has sent the result.
- var retry = retryDehydratedSuspenseBoundary.bind(null, current);
- registerSuspenseInstanceRetry(suspenseInstance, retry);
- return null;
- } else {
- // This is the first attempt.
- reenterHydrationStateFromDehydratedSuspenseInstance(workInProgress, suspenseInstance, suspenseState.treeContext);
- var primaryChildren = nextProps.children;
- var primaryChildFragment = mountSuspensePrimaryChildren(workInProgress, primaryChildren); // Mark the children as hydrating. This is a fast path to know whether this
- // tree is part of a hydrating tree. This is used to determine if a child
- // node has fully mounted yet, and for scheduling event replaying.
- // Conceptually this is similar to Placement in that a new subtree is
- // inserted into the React tree here. It just happens to not need DOM
- // mutations because it already exists.
- primaryChildFragment.flags |= Hydrating;
- return primaryChildFragment;
- }
- } else {
- // This is the second render pass. We already attempted to hydrated, but
- // something either suspended or errored.
- if (workInProgress.flags & ForceClientRender) {
- // Something errored during hydration. Try again without hydrating.
- workInProgress.flags &= ~ForceClientRender;
- var _capturedValue2 = createCapturedValue(new Error('There was an error while hydrating this Suspense boundary. ' + 'Switched to client rendering.'));
- return retrySuspenseComponentWithoutHydrating(current, workInProgress, renderLanes, _capturedValue2);
- } else if (workInProgress.memoizedState !== null) {
- // Something suspended and we should still be in dehydrated mode.
- // Leave the existing child in place.
- workInProgress.child = current.child; // The dehydrated completion pass expects this flag to be there
- // but the normal suspense pass doesn't.
- workInProgress.flags |= DidCapture;
- return null;
- } else {
- // Suspended but we should no longer be in dehydrated mode.
- // Therefore we now have to render the fallback.
- var nextPrimaryChildren = nextProps.children;
- var nextFallbackChildren = nextProps.fallback;
- var fallbackChildFragment = mountSuspenseFallbackAfterRetryWithoutHydrating(current, workInProgress, nextPrimaryChildren, nextFallbackChildren, renderLanes);
- var _primaryChildFragment4 = workInProgress.child;
- _primaryChildFragment4.memoizedState = mountSuspenseOffscreenState(renderLanes);
- workInProgress.memoizedState = SUSPENDED_MARKER;
- return fallbackChildFragment;
- }
- }
- }
- function scheduleSuspenseWorkOnFiber(fiber, renderLanes, propagationRoot) {
- fiber.lanes = mergeLanes(fiber.lanes, renderLanes);
- var alternate = fiber.alternate;
- if (alternate !== null) {
- alternate.lanes = mergeLanes(alternate.lanes, renderLanes);
- }
- scheduleContextWorkOnParentPath(fiber.return, renderLanes, propagationRoot);
- }
- function propagateSuspenseContextChange(workInProgress, firstChild, renderLanes) {
- // Mark any Suspense boundaries with fallbacks as having work to do.
- // If they were previously forced into fallbacks, they may now be able
- // to unblock.
- var node = firstChild;
- while (node !== null) {
- if (node.tag === SuspenseComponent) {
- var state = node.memoizedState;
- if (state !== null) {
- scheduleSuspenseWorkOnFiber(node, renderLanes, workInProgress);
- }
- } else if (node.tag === SuspenseListComponent) {
- // If the tail is hidden there might not be an Suspense boundaries
- // to schedule work on. In this case we have to schedule it on the
- // list itself.
- // We don't have to traverse to the children of the list since
- // the list will propagate the change when it rerenders.
- scheduleSuspenseWorkOnFiber(node, renderLanes, workInProgress);
- } else if (node.child !== null) {
- node.child.return = node;
- node = node.child;
- continue;
- }
- if (node === workInProgress) {
- return;
- }
- while (node.sibling === null) {
- if (node.return === null || node.return === workInProgress) {
- return;
- }
- node = node.return;
- }
- node.sibling.return = node.return;
- node = node.sibling;
- }
- }
- function findLastContentRow(firstChild) {
- // This is going to find the last row among these children that is already
- // showing content on the screen, as opposed to being in fallback state or
- // new. If a row has multiple Suspense boundaries, any of them being in the
- // fallback state, counts as the whole row being in a fallback state.
- // Note that the "rows" will be workInProgress, but any nested children
- // will still be current since we haven't rendered them yet. The mounted
- // order may not be the same as the new order. We use the new order.
- var row = firstChild;
- var lastContentRow = null;
- while (row !== null) {
- var currentRow = row.alternate; // New rows can't be content rows.
- if (currentRow !== null && findFirstSuspended(currentRow) === null) {
- lastContentRow = row;
- }
- row = row.sibling;
- }
- return lastContentRow;
- }
- function validateRevealOrder(revealOrder) {
- {
- if (revealOrder !== undefined && revealOrder !== 'forwards' && revealOrder !== 'backwards' && revealOrder !== 'together' && !didWarnAboutRevealOrder[revealOrder]) {
- didWarnAboutRevealOrder[revealOrder] = true;
- if (typeof revealOrder === 'string') {
- switch (revealOrder.toLowerCase()) {
- case 'together':
- case 'forwards':
- case 'backwards':
- {
- error('"%s" is not a valid value for revealOrder on <SuspenseList />. ' + 'Use lowercase "%s" instead.', revealOrder, revealOrder.toLowerCase());
- break;
- }
- case 'forward':
- case 'backward':
- {
- error('"%s" is not a valid value for revealOrder on <SuspenseList />. ' + 'React uses the -s suffix in the spelling. Use "%ss" instead.', revealOrder, revealOrder.toLowerCase());
- break;
- }
- default:
- error('"%s" is not a supported revealOrder on <SuspenseList />. ' + 'Did you mean "together", "forwards" or "backwards"?', revealOrder);
- break;
- }
- } else {
- error('%s is not a supported value for revealOrder on <SuspenseList />. ' + 'Did you mean "together", "forwards" or "backwards"?', revealOrder);
- }
- }
- }
- }
- function validateTailOptions(tailMode, revealOrder) {
- {
- if (tailMode !== undefined && !didWarnAboutTailOptions[tailMode]) {
- if (tailMode !== 'collapsed' && tailMode !== 'hidden') {
- didWarnAboutTailOptions[tailMode] = true;
- error('"%s" is not a supported value for tail on <SuspenseList />. ' + 'Did you mean "collapsed" or "hidden"?', tailMode);
- } else if (revealOrder !== 'forwards' && revealOrder !== 'backwards') {
- didWarnAboutTailOptions[tailMode] = true;
- error('<SuspenseList tail="%s" /> is only valid if revealOrder is ' + '"forwards" or "backwards". ' + 'Did you mean to specify revealOrder="forwards"?', tailMode);
- }
- }
- }
- }
- function validateSuspenseListNestedChild(childSlot, index) {
- {
- var isAnArray = isArray(childSlot);
- var isIterable = !isAnArray && typeof getIteratorFn(childSlot) === 'function';
- if (isAnArray || isIterable) {
- var type = isAnArray ? 'array' : 'iterable';
- error('A nested %s was passed to row #%s in <SuspenseList />. Wrap it in ' + 'an additional SuspenseList to configure its revealOrder: ' + '<SuspenseList revealOrder=...> ... ' + '<SuspenseList revealOrder=...>{%s}</SuspenseList> ... ' + '</SuspenseList>', type, index, type);
- return false;
- }
- }
- return true;
- }
- function validateSuspenseListChildren(children, revealOrder) {
- {
- if ((revealOrder === 'forwards' || revealOrder === 'backwards') && children !== undefined && children !== null && children !== false) {
- if (isArray(children)) {
- for (var i = 0; i < children.length; i++) {
- if (!validateSuspenseListNestedChild(children[i], i)) {
- return;
- }
- }
- } else {
- var iteratorFn = getIteratorFn(children);
- if (typeof iteratorFn === 'function') {
- var childrenIterator = iteratorFn.call(children);
- if (childrenIterator) {
- var step = childrenIterator.next();
- var _i = 0;
- for (; !step.done; step = childrenIterator.next()) {
- if (!validateSuspenseListNestedChild(step.value, _i)) {
- return;
- }
- _i++;
- }
- }
- } else {
- error('A single row was passed to a <SuspenseList revealOrder="%s" />. ' + 'This is not useful since it needs multiple rows. ' + 'Did you mean to pass multiple children or an array?', revealOrder);
- }
- }
- }
- }
- }
- function initSuspenseListRenderState(workInProgress, isBackwards, tail, lastContentRow, tailMode) {
- var renderState = workInProgress.memoizedState;
- if (renderState === null) {
- workInProgress.memoizedState = {
- isBackwards: isBackwards,
- rendering: null,
- renderingStartTime: 0,
- last: lastContentRow,
- tail: tail,
- tailMode: tailMode
- };
- } else {
- // We can reuse the existing object from previous renders.
- renderState.isBackwards = isBackwards;
- renderState.rendering = null;
- renderState.renderingStartTime = 0;
- renderState.last = lastContentRow;
- renderState.tail = tail;
- renderState.tailMode = tailMode;
- }
- } // This can end up rendering this component multiple passes.
- // The first pass splits the children fibers into two sets. A head and tail.
- // We first render the head. If anything is in fallback state, we do another
- // pass through beginWork to rerender all children (including the tail) with
- // the force suspend context. If the first render didn't have anything in
- // in fallback state. Then we render each row in the tail one-by-one.
- // That happens in the completeWork phase without going back to beginWork.
- function updateSuspenseListComponent(current, workInProgress, renderLanes) {
- var nextProps = workInProgress.pendingProps;
- var revealOrder = nextProps.revealOrder;
- var tailMode = nextProps.tail;
- var newChildren = nextProps.children;
- validateRevealOrder(revealOrder);
- validateTailOptions(tailMode, revealOrder);
- validateSuspenseListChildren(newChildren, revealOrder);
- reconcileChildren(current, workInProgress, newChildren, renderLanes);
- var suspenseContext = suspenseStackCursor.current;
- var shouldForceFallback = hasSuspenseContext(suspenseContext, ForceSuspenseFallback);
- if (shouldForceFallback) {
- suspenseContext = setShallowSuspenseContext(suspenseContext, ForceSuspenseFallback);
- workInProgress.flags |= DidCapture;
- } else {
- var didSuspendBefore = current !== null && (current.flags & DidCapture) !== NoFlags;
- if (didSuspendBefore) {
- // If we previously forced a fallback, we need to schedule work
- // on any nested boundaries to let them know to try to render
- // again. This is the same as context updating.
- propagateSuspenseContextChange(workInProgress, workInProgress.child, renderLanes);
- }
- suspenseContext = setDefaultShallowSuspenseContext(suspenseContext);
- }
- pushSuspenseContext(workInProgress, suspenseContext);
- if ((workInProgress.mode & ConcurrentMode) === NoMode) {
- // In legacy mode, SuspenseList doesn't work so we just
- // use make it a noop by treating it as the default revealOrder.
- workInProgress.memoizedState = null;
- } else {
- switch (revealOrder) {
- case 'forwards':
- {
- var lastContentRow = findLastContentRow(workInProgress.child);
- var tail;
- if (lastContentRow === null) {
- // The whole list is part of the tail.
- // TODO: We could fast path by just rendering the tail now.
- tail = workInProgress.child;
- workInProgress.child = null;
- } else {
- // Disconnect the tail rows after the content row.
- // We're going to render them separately later.
- tail = lastContentRow.sibling;
- lastContentRow.sibling = null;
- }
- initSuspenseListRenderState(workInProgress, false, // isBackwards
- tail, lastContentRow, tailMode);
- break;
- }
- case 'backwards':
- {
- // We're going to find the first row that has existing content.
- // At the same time we're going to reverse the list of everything
- // we pass in the meantime. That's going to be our tail in reverse
- // order.
- var _tail = null;
- var row = workInProgress.child;
- workInProgress.child = null;
- while (row !== null) {
- var currentRow = row.alternate; // New rows can't be content rows.
- if (currentRow !== null && findFirstSuspended(currentRow) === null) {
- // This is the beginning of the main content.
- workInProgress.child = row;
- break;
- }
- var nextRow = row.sibling;
- row.sibling = _tail;
- _tail = row;
- row = nextRow;
- } // TODO: If workInProgress.child is null, we can continue on the tail immediately.
- initSuspenseListRenderState(workInProgress, true, // isBackwards
- _tail, null, // last
- tailMode);
- break;
- }
- case 'together':
- {
- initSuspenseListRenderState(workInProgress, false, // isBackwards
- null, // tail
- null, // last
- undefined);
- break;
- }
- default:
- {
- // The default reveal order is the same as not having
- // a boundary.
- workInProgress.memoizedState = null;
- }
- }
- }
- return workInProgress.child;
- }
- function updatePortalComponent(current, workInProgress, renderLanes) {
- pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo);
- var nextChildren = workInProgress.pendingProps;
- if (current === null) {
- // Portals are special because we don't append the children during mount
- // but at commit. Therefore we need to track insertions which the normal
- // flow doesn't do during mount. This doesn't happen at the root because
- // the root always starts with a "current" with a null child.
- // TODO: Consider unifying this with how the root works.
- workInProgress.child = reconcileChildFibers(workInProgress, null, nextChildren, renderLanes);
- } else {
- reconcileChildren(current, workInProgress, nextChildren, renderLanes);
- }
- return workInProgress.child;
- }
- var hasWarnedAboutUsingNoValuePropOnContextProvider = false;
- function updateContextProvider(current, workInProgress, renderLanes) {
- var providerType = workInProgress.type;
- var context = providerType._context;
- var newProps = workInProgress.pendingProps;
- var oldProps = workInProgress.memoizedProps;
- var newValue = newProps.value;
- {
- if (!('value' in newProps)) {
- if (!hasWarnedAboutUsingNoValuePropOnContextProvider) {
- hasWarnedAboutUsingNoValuePropOnContextProvider = true;
- error('The `value` prop is required for the `<Context.Provider>`. Did you misspell it or forget to pass it?');
- }
- }
- var providerPropTypes = workInProgress.type.propTypes;
- if (providerPropTypes) {
- checkPropTypes(providerPropTypes, newProps, 'prop', 'Context.Provider');
- }
- }
- pushProvider(workInProgress, context, newValue);
- {
- if (oldProps !== null) {
- var oldValue = oldProps.value;
- if (objectIs(oldValue, newValue)) {
- // No change. Bailout early if children are the same.
- if (oldProps.children === newProps.children && !hasContextChanged()) {
- return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);
- }
- } else {
- // The context value changed. Search for matching consumers and schedule
- // them to update.
- propagateContextChange(workInProgress, context, renderLanes);
- }
- }
- }
- var newChildren = newProps.children;
- reconcileChildren(current, workInProgress, newChildren, renderLanes);
- return workInProgress.child;
- }
- var hasWarnedAboutUsingContextAsConsumer = false;
- function updateContextConsumer(current, workInProgress, renderLanes) {
- var context = workInProgress.type; // The logic below for Context differs depending on PROD or DEV mode. In
- // DEV mode, we create a separate object for Context.Consumer that acts
- // like a proxy to Context. This proxy object adds unnecessary code in PROD
- // so we use the old behaviour (Context.Consumer references Context) to
- // reduce size and overhead. The separate object references context via
- // a property called "_context", which also gives us the ability to check
- // in DEV mode if this property exists or not and warn if it does not.
- {
- if (context._context === undefined) {
- // This may be because it's a Context (rather than a Consumer).
- // Or it may be because it's older React where they're the same thing.
- // We only want to warn if we're sure it's a new React.
- if (context !== context.Consumer) {
- if (!hasWarnedAboutUsingContextAsConsumer) {
- hasWarnedAboutUsingContextAsConsumer = true;
- error('Rendering <Context> directly is not supported and will be removed in ' + 'a future major release. Did you mean to render <Context.Consumer> instead?');
- }
- }
- } else {
- context = context._context;
- }
- }
- var newProps = workInProgress.pendingProps;
- var render = newProps.children;
- {
- if (typeof render !== 'function') {
- error('A context consumer was rendered with multiple children, or a child ' + "that isn't a function. A context consumer expects a single child " + 'that is a function. If you did pass a function, make sure there ' + 'is no trailing or leading whitespace around it.');
- }
- }
- prepareToReadContext(workInProgress, renderLanes);
- var newValue = readContext(context);
- {
- markComponentRenderStarted(workInProgress);
- }
- var newChildren;
- {
- ReactCurrentOwner$1.current = workInProgress;
- setIsRendering(true);
- newChildren = render(newValue);
- setIsRendering(false);
- }
- {
- markComponentRenderStopped();
- } // React DevTools reads this flag.
- workInProgress.flags |= PerformedWork;
- reconcileChildren(current, workInProgress, newChildren, renderLanes);
- return workInProgress.child;
- }
- function markWorkInProgressReceivedUpdate() {
- didReceiveUpdate = true;
- }
- function resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress) {
- if ((workInProgress.mode & ConcurrentMode) === NoMode) {
- if (current !== null) {
- // A lazy component only mounts if it suspended inside a non-
- // concurrent tree, in an inconsistent state. We want to treat it like
- // a new mount, even though an empty version of it already committed.
- // Disconnect the alternate pointers.
- current.alternate = null;
- workInProgress.alternate = null; // Since this is conceptually a new fiber, schedule a Placement effect
- workInProgress.flags |= Placement;
- }
- }
- }
- function bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) {
- if (current !== null) {
- // Reuse previous dependencies
- workInProgress.dependencies = current.dependencies;
- }
- {
- // Don't update "base" render times for bailouts.
- stopProfilerTimerIfRunning();
- }
- markSkippedUpdateLanes(workInProgress.lanes); // Check if the children have any pending work.
- if (!includesSomeLane(renderLanes, workInProgress.childLanes)) {
- // The children don't have any work either. We can skip them.
- // TODO: Once we add back resuming, we should check if the children are
- // a work-in-progress set. If so, we need to transfer their effects.
- {
- return null;
- }
- } // This fiber doesn't have work, but its subtree does. Clone the child
- // fibers and continue.
- cloneChildFibers(current, workInProgress);
- return workInProgress.child;
- }
- function remountFiber(current, oldWorkInProgress, newWorkInProgress) {
- {
- var returnFiber = oldWorkInProgress.return;
- if (returnFiber === null) {
- // eslint-disable-next-line react-internal/prod-error-codes
- throw new Error('Cannot swap the root fiber.');
- } // Disconnect from the old current.
- // It will get deleted.
- current.alternate = null;
- oldWorkInProgress.alternate = null; // Connect to the new tree.
- newWorkInProgress.index = oldWorkInProgress.index;
- newWorkInProgress.sibling = oldWorkInProgress.sibling;
- newWorkInProgress.return = oldWorkInProgress.return;
- newWorkInProgress.ref = oldWorkInProgress.ref; // Replace the child/sibling pointers above it.
- if (oldWorkInProgress === returnFiber.child) {
- returnFiber.child = newWorkInProgress;
- } else {
- var prevSibling = returnFiber.child;
- if (prevSibling === null) {
- // eslint-disable-next-line react-internal/prod-error-codes
- throw new Error('Expected parent to have a child.');
- }
- while (prevSibling.sibling !== oldWorkInProgress) {
- prevSibling = prevSibling.sibling;
- if (prevSibling === null) {
- // eslint-disable-next-line react-internal/prod-error-codes
- throw new Error('Expected to find the previous sibling.');
- }
- }
- prevSibling.sibling = newWorkInProgress;
- } // Delete the old fiber and place the new one.
- // Since the old fiber is disconnected, we have to schedule it manually.
- var deletions = returnFiber.deletions;
- if (deletions === null) {
- returnFiber.deletions = [current];
- returnFiber.flags |= ChildDeletion;
- } else {
- deletions.push(current);
- }
- newWorkInProgress.flags |= Placement; // Restart work from the new fiber.
- return newWorkInProgress;
- }
- }
- function checkScheduledUpdateOrContext(current, renderLanes) {
- // Before performing an early bailout, we must check if there are pending
- // updates or context.
- var updateLanes = current.lanes;
- if (includesSomeLane(updateLanes, renderLanes)) {
- return true;
- } // No pending update, but because context is propagated lazily, we need
- return false;
- }
- function attemptEarlyBailoutIfNoScheduledUpdate(current, workInProgress, renderLanes) {
- // This fiber does not have any pending work. Bailout without entering
- // the begin phase. There's still some bookkeeping we that needs to be done
- // in this optimized path, mostly pushing stuff onto the stack.
- switch (workInProgress.tag) {
- case HostRoot:
- pushHostRootContext(workInProgress);
- var root = workInProgress.stateNode;
- resetHydrationState();
- break;
- case HostComponent:
- pushHostContext(workInProgress);
- break;
- case ClassComponent:
- {
- var Component = workInProgress.type;
- if (isContextProvider(Component)) {
- pushContextProvider(workInProgress);
- }
- break;
- }
- case HostPortal:
- pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo);
- break;
- case ContextProvider:
- {
- var newValue = workInProgress.memoizedProps.value;
- var context = workInProgress.type._context;
- pushProvider(workInProgress, context, newValue);
- break;
- }
- case Profiler:
- {
- // Profiler should only call onRender when one of its descendants actually rendered.
- var hasChildWork = includesSomeLane(renderLanes, workInProgress.childLanes);
- if (hasChildWork) {
- workInProgress.flags |= Update;
- }
- {
- // Reset effect durations for the next eventual effect phase.
- // These are reset during render to allow the DevTools commit hook a chance to read them,
- var stateNode = workInProgress.stateNode;
- stateNode.effectDuration = 0;
- stateNode.passiveEffectDuration = 0;
- }
- }
- break;
- case SuspenseComponent:
- {
- var state = workInProgress.memoizedState;
- if (state !== null) {
- if (state.dehydrated !== null) {
- pushSuspenseContext(workInProgress, setDefaultShallowSuspenseContext(suspenseStackCursor.current)); // We know that this component will suspend again because if it has
- // been unsuspended it has committed as a resolved Suspense component.
- // If it needs to be retried, it should have work scheduled on it.
- workInProgress.flags |= DidCapture; // We should never render the children of a dehydrated boundary until we
- // upgrade it. We return null instead of bailoutOnAlreadyFinishedWork.
- return null;
- } // If this boundary is currently timed out, we need to decide
- // whether to retry the primary children, or to skip over it and
- // go straight to the fallback. Check the priority of the primary
- // child fragment.
- var primaryChildFragment = workInProgress.child;
- var primaryChildLanes = primaryChildFragment.childLanes;
- if (includesSomeLane(renderLanes, primaryChildLanes)) {
- // The primary children have pending work. Use the normal path
- // to attempt to render the primary children again.
- return updateSuspenseComponent(current, workInProgress, renderLanes);
- } else {
- // The primary child fragment does not have pending work marked
- // on it
- pushSuspenseContext(workInProgress, setDefaultShallowSuspenseContext(suspenseStackCursor.current)); // The primary children do not have pending work with sufficient
- // priority. Bailout.
- var child = bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);
- if (child !== null) {
- // The fallback children have pending work. Skip over the
- // primary children and work on the fallback.
- return child.sibling;
- } else {
- // Note: We can return `null` here because we already checked
- // whether there were nested context consumers, via the call to
- // `bailoutOnAlreadyFinishedWork` above.
- return null;
- }
- }
- } else {
- pushSuspenseContext(workInProgress, setDefaultShallowSuspenseContext(suspenseStackCursor.current));
- }
- break;
- }
- case SuspenseListComponent:
- {
- var didSuspendBefore = (current.flags & DidCapture) !== NoFlags;
- var _hasChildWork = includesSomeLane(renderLanes, workInProgress.childLanes);
- if (didSuspendBefore) {
- if (_hasChildWork) {
- // If something was in fallback state last time, and we have all the
- // same children then we're still in progressive loading state.
- // Something might get unblocked by state updates or retries in the
- // tree which will affect the tail. So we need to use the normal
- // path to compute the correct tail.
- return updateSuspenseListComponent(current, workInProgress, renderLanes);
- } // If none of the children had any work, that means that none of
- // them got retried so they'll still be blocked in the same way
- // as before. We can fast bail out.
- workInProgress.flags |= DidCapture;
- } // If nothing suspended before and we're rendering the same children,
- // then the tail doesn't matter. Anything new that suspends will work
- // in the "together" mode, so we can continue from the state we had.
- var renderState = workInProgress.memoizedState;
- if (renderState !== null) {
- // Reset to the "together" mode in case we've started a different
- // update in the past but didn't complete it.
- renderState.rendering = null;
- renderState.tail = null;
- renderState.lastEffect = null;
- }
- pushSuspenseContext(workInProgress, suspenseStackCursor.current);
- if (_hasChildWork) {
- break;
- } else {
- // If none of the children had any work, that means that none of
- // them got retried so they'll still be blocked in the same way
- // as before. We can fast bail out.
- return null;
- }
- }
- case OffscreenComponent:
- case LegacyHiddenComponent:
- {
- // Need to check if the tree still needs to be deferred. This is
- // almost identical to the logic used in the normal update path,
- // so we'll just enter that. The only difference is we'll bail out
- // at the next level instead of this one, because the child props
- // have not changed. Which is fine.
- // TODO: Probably should refactor `beginWork` to split the bailout
- // path from the normal path. I'm tempted to do a labeled break here
- // but I won't :)
- workInProgress.lanes = NoLanes;
- return updateOffscreenComponent(current, workInProgress, renderLanes);
- }
- }
- return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);
- }
- function beginWork(current, workInProgress, renderLanes) {
- {
- if (workInProgress._debugNeedsRemount && current !== null) {
- // This will restart the begin phase with a new fiber.
- return remountFiber(current, workInProgress, createFiberFromTypeAndProps(workInProgress.type, workInProgress.key, workInProgress.pendingProps, workInProgress._debugOwner || null, workInProgress.mode, workInProgress.lanes));
- }
- }
- if (current !== null) {
- var oldProps = current.memoizedProps;
- var newProps = workInProgress.pendingProps;
- if (oldProps !== newProps || hasContextChanged() || ( // Force a re-render if the implementation changed due to hot reload:
- workInProgress.type !== current.type)) {
- // If props or context changed, mark the fiber as having performed work.
- // This may be unset if the props are determined to be equal later (memo).
- didReceiveUpdate = true;
- } else {
- // Neither props nor legacy context changes. Check if there's a pending
- // update or context change.
- var hasScheduledUpdateOrContext = checkScheduledUpdateOrContext(current, renderLanes);
- if (!hasScheduledUpdateOrContext && // If this is the second pass of an error or suspense boundary, there
- // may not be work scheduled on `current`, so we check for this flag.
- (workInProgress.flags & DidCapture) === NoFlags) {
- // No pending updates or context. Bail out now.
- didReceiveUpdate = false;
- return attemptEarlyBailoutIfNoScheduledUpdate(current, workInProgress, renderLanes);
- }
- if ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags) {
- // This is a special case that only exists for legacy mode.
- // See https://github.com/facebook/react/pull/19216.
- didReceiveUpdate = true;
- } else {
- // An update was scheduled on this fiber, but there are no new props
- // nor legacy context. Set this to false. If an update queue or context
- // consumer produces a changed value, it will set this to true. Otherwise,
- // the component will assume the children have not changed and bail out.
- didReceiveUpdate = false;
- }
- }
- } else {
- didReceiveUpdate = false;
- if (getIsHydrating() && isForkedChild(workInProgress)) {
- // Check if this child belongs to a list of muliple children in
- // its parent.
- //
- // In a true multi-threaded implementation, we would render children on
- // parallel threads. This would represent the beginning of a new render
- // thread for this subtree.
- //
- // We only use this for id generation during hydration, which is why the
- // logic is located in this special branch.
- var slotIndex = workInProgress.index;
- var numberOfForks = getForksAtLevel();
- pushTreeId(workInProgress, numberOfForks, slotIndex);
- }
- } // Before entering the begin phase, clear pending update priority.
- // TODO: This assumes that we're about to evaluate the component and process
- // the update queue. However, there's an exception: SimpleMemoComponent
- // sometimes bails out later in the begin phase. This indicates that we should
- // move this assignment out of the common path and into each branch.
- workInProgress.lanes = NoLanes;
- switch (workInProgress.tag) {
- case IndeterminateComponent:
- {
- return mountIndeterminateComponent(current, workInProgress, workInProgress.type, renderLanes);
- }
- case LazyComponent:
- {
- var elementType = workInProgress.elementType;
- return mountLazyComponent(current, workInProgress, elementType, renderLanes);
- }
- case FunctionComponent:
- {
- var Component = workInProgress.type;
- var unresolvedProps = workInProgress.pendingProps;
- var resolvedProps = workInProgress.elementType === Component ? unresolvedProps : resolveDefaultProps(Component, unresolvedProps);
- return updateFunctionComponent(current, workInProgress, Component, resolvedProps, renderLanes);
- }
- case ClassComponent:
- {
- var _Component = workInProgress.type;
- var _unresolvedProps = workInProgress.pendingProps;
- var _resolvedProps = workInProgress.elementType === _Component ? _unresolvedProps : resolveDefaultProps(_Component, _unresolvedProps);
- return updateClassComponent(current, workInProgress, _Component, _resolvedProps, renderLanes);
- }
- case HostRoot:
- return updateHostRoot(current, workInProgress, renderLanes);
- case HostComponent:
- return updateHostComponent(current, workInProgress, renderLanes);
- case HostText:
- return updateHostText(current, workInProgress);
- case SuspenseComponent:
- return updateSuspenseComponent(current, workInProgress, renderLanes);
- case HostPortal:
- return updatePortalComponent(current, workInProgress, renderLanes);
- case ForwardRef:
- {
- var type = workInProgress.type;
- var _unresolvedProps2 = workInProgress.pendingProps;
- var _resolvedProps2 = workInProgress.elementType === type ? _unresolvedProps2 : resolveDefaultProps(type, _unresolvedProps2);
- return updateForwardRef(current, workInProgress, type, _resolvedProps2, renderLanes);
- }
- case Fragment:
- return updateFragment(current, workInProgress, renderLanes);
- case Mode:
- return updateMode(current, workInProgress, renderLanes);
- case Profiler:
- return updateProfiler(current, workInProgress, renderLanes);
- case ContextProvider:
- return updateContextProvider(current, workInProgress, renderLanes);
- case ContextConsumer:
- return updateContextConsumer(current, workInProgress, renderLanes);
- case MemoComponent:
- {
- var _type2 = workInProgress.type;
- var _unresolvedProps3 = workInProgress.pendingProps; // Resolve outer props first, then resolve inner props.
- var _resolvedProps3 = resolveDefaultProps(_type2, _unresolvedProps3);
- {
- if (workInProgress.type !== workInProgress.elementType) {
- var outerPropTypes = _type2.propTypes;
- if (outerPropTypes) {
- checkPropTypes(outerPropTypes, _resolvedProps3, // Resolved for outer only
- 'prop', getComponentNameFromType(_type2));
- }
- }
- }
- _resolvedProps3 = resolveDefaultProps(_type2.type, _resolvedProps3);
- return updateMemoComponent(current, workInProgress, _type2, _resolvedProps3, renderLanes);
- }
- case SimpleMemoComponent:
- {
- return updateSimpleMemoComponent(current, workInProgress, workInProgress.type, workInProgress.pendingProps, renderLanes);
- }
- case IncompleteClassComponent:
- {
- var _Component2 = workInProgress.type;
- var _unresolvedProps4 = workInProgress.pendingProps;
- var _resolvedProps4 = workInProgress.elementType === _Component2 ? _unresolvedProps4 : resolveDefaultProps(_Component2, _unresolvedProps4);
- return mountIncompleteClassComponent(current, workInProgress, _Component2, _resolvedProps4, renderLanes);
- }
- case SuspenseListComponent:
- {
- return updateSuspenseListComponent(current, workInProgress, renderLanes);
- }
- case ScopeComponent:
- {
- break;
- }
- case OffscreenComponent:
- {
- return updateOffscreenComponent(current, workInProgress, renderLanes);
- }
- }
- throw new Error("Unknown unit of work tag (" + workInProgress.tag + "). This error is likely caused by a bug in " + 'React. Please file an issue.');
- }
- function markUpdate(workInProgress) {
- // Tag the fiber with an update effect. This turns a Placement into
- // a PlacementAndUpdate.
- workInProgress.flags |= Update;
- }
- function markRef$1(workInProgress) {
- workInProgress.flags |= Ref;
- {
- workInProgress.flags |= RefStatic;
- }
- }
- var appendAllChildren;
- var updateHostContainer;
- var updateHostComponent$1;
- var updateHostText$1;
- {
- // Mutation mode
- appendAllChildren = function (parent, workInProgress, needsVisibilityToggle, isHidden) {
- // We only have the top Fiber that was created but we need recurse down its
- // children to find all the terminal nodes.
- var node = workInProgress.child;
- while (node !== null) {
- if (node.tag === HostComponent || node.tag === HostText) {
- appendInitialChild(parent, node.stateNode);
- } else if (node.tag === HostPortal); else if (node.child !== null) {
- node.child.return = node;
- node = node.child;
- continue;
- }
- if (node === workInProgress) {
- return;
- }
- while (node.sibling === null) {
- if (node.return === null || node.return === workInProgress) {
- return;
- }
- node = node.return;
- }
- node.sibling.return = node.return;
- node = node.sibling;
- }
- };
- updateHostContainer = function (current, workInProgress) {// Noop
- };
- updateHostComponent$1 = function (current, workInProgress, type, newProps, rootContainerInstance) {
- // If we have an alternate, that means this is an update and we need to
- // schedule a side-effect to do the updates.
- var oldProps = current.memoizedProps;
- if (oldProps === newProps) {
- // In mutation mode, this is sufficient for a bailout because
- // we won't touch this node even if children changed.
- return;
- } // If we get updated because one of our children updated, we don't
- // have newProps so we'll have to reuse them.
- // TODO: Split the update API as separate for the props vs. children.
- // Even better would be if children weren't special cased at all tho.
- var instance = workInProgress.stateNode;
- var currentHostContext = getHostContext(); // TODO: Experiencing an error where oldProps is null. Suggests a host
- // component is hitting the resume path. Figure out why. Possibly
- // related to `hidden`.
- var updatePayload = prepareUpdate(instance, type, oldProps, newProps, rootContainerInstance, currentHostContext); // TODO: Type this specific to this type of component.
- workInProgress.updateQueue = updatePayload; // If the update payload indicates that there is a change or if there
- // is a new ref we mark this as an update. All the work is done in commitWork.
- if (updatePayload) {
- markUpdate(workInProgress);
- }
- };
- updateHostText$1 = function (current, workInProgress, oldText, newText) {
- // If the text differs, mark it as an update. All the work in done in commitWork.
- if (oldText !== newText) {
- markUpdate(workInProgress);
- }
- };
- }
- function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) {
- if (getIsHydrating()) {
- // If we're hydrating, we should consume as many items as we can
- // so we don't leave any behind.
- return;
- }
- switch (renderState.tailMode) {
- case 'hidden':
- {
- // Any insertions at the end of the tail list after this point
- // should be invisible. If there are already mounted boundaries
- // anything before them are not considered for collapsing.
- // Therefore we need to go through the whole tail to find if
- // there are any.
- var tailNode = renderState.tail;
- var lastTailNode = null;
- while (tailNode !== null) {
- if (tailNode.alternate !== null) {
- lastTailNode = tailNode;
- }
- tailNode = tailNode.sibling;
- } // Next we're simply going to delete all insertions after the
- // last rendered item.
- if (lastTailNode === null) {
- // All remaining items in the tail are insertions.
- renderState.tail = null;
- } else {
- // Detach the insertion after the last node that was already
- // inserted.
- lastTailNode.sibling = null;
- }
- break;
- }
- case 'collapsed':
- {
- // Any insertions at the end of the tail list after this point
- // should be invisible. If there are already mounted boundaries
- // anything before them are not considered for collapsing.
- // Therefore we need to go through the whole tail to find if
- // there are any.
- var _tailNode = renderState.tail;
- var _lastTailNode = null;
- while (_tailNode !== null) {
- if (_tailNode.alternate !== null) {
- _lastTailNode = _tailNode;
- }
- _tailNode = _tailNode.sibling;
- } // Next we're simply going to delete all insertions after the
- // last rendered item.
- if (_lastTailNode === null) {
- // All remaining items in the tail are insertions.
- if (!hasRenderedATailFallback && renderState.tail !== null) {
- // We suspended during the head. We want to show at least one
- // row at the tail. So we'll keep on and cut off the rest.
- renderState.tail.sibling = null;
- } else {
- renderState.tail = null;
- }
- } else {
- // Detach the insertion after the last node that was already
- // inserted.
- _lastTailNode.sibling = null;
- }
- break;
- }
- }
- }
- function bubbleProperties(completedWork) {
- var didBailout = completedWork.alternate !== null && completedWork.alternate.child === completedWork.child;
- var newChildLanes = NoLanes;
- var subtreeFlags = NoFlags;
- if (!didBailout) {
- // Bubble up the earliest expiration time.
- if ((completedWork.mode & ProfileMode) !== NoMode) {
- // In profiling mode, resetChildExpirationTime is also used to reset
- // profiler durations.
- var actualDuration = completedWork.actualDuration;
- var treeBaseDuration = completedWork.selfBaseDuration;
- var child = completedWork.child;
- while (child !== null) {
- newChildLanes = mergeLanes(newChildLanes, mergeLanes(child.lanes, child.childLanes));
- subtreeFlags |= child.subtreeFlags;
- subtreeFlags |= child.flags; // When a fiber is cloned, its actualDuration is reset to 0. This value will
- // only be updated if work is done on the fiber (i.e. it doesn't bailout).
- // When work is done, it should bubble to the parent's actualDuration. If
- // the fiber has not been cloned though, (meaning no work was done), then
- // this value will reflect the amount of time spent working on a previous
- // render. In that case it should not bubble. We determine whether it was
- // cloned by comparing the child pointer.
- actualDuration += child.actualDuration;
- treeBaseDuration += child.treeBaseDuration;
- child = child.sibling;
- }
- completedWork.actualDuration = actualDuration;
- completedWork.treeBaseDuration = treeBaseDuration;
- } else {
- var _child = completedWork.child;
- while (_child !== null) {
- newChildLanes = mergeLanes(newChildLanes, mergeLanes(_child.lanes, _child.childLanes));
- subtreeFlags |= _child.subtreeFlags;
- subtreeFlags |= _child.flags; // Update the return pointer so the tree is consistent. This is a code
- // smell because it assumes the commit phase is never concurrent with
- // the render phase. Will address during refactor to alternate model.
- _child.return = completedWork;
- _child = _child.sibling;
- }
- }
- completedWork.subtreeFlags |= subtreeFlags;
- } else {
- // Bubble up the earliest expiration time.
- if ((completedWork.mode & ProfileMode) !== NoMode) {
- // In profiling mode, resetChildExpirationTime is also used to reset
- // profiler durations.
- var _treeBaseDuration = completedWork.selfBaseDuration;
- var _child2 = completedWork.child;
- while (_child2 !== null) {
- newChildLanes = mergeLanes(newChildLanes, mergeLanes(_child2.lanes, _child2.childLanes)); // "Static" flags share the lifetime of the fiber/hook they belong to,
- // so we should bubble those up even during a bailout. All the other
- // flags have a lifetime only of a single render + commit, so we should
- // ignore them.
- subtreeFlags |= _child2.subtreeFlags & StaticMask;
- subtreeFlags |= _child2.flags & StaticMask;
- _treeBaseDuration += _child2.treeBaseDuration;
- _child2 = _child2.sibling;
- }
- completedWork.treeBaseDuration = _treeBaseDuration;
- } else {
- var _child3 = completedWork.child;
- while (_child3 !== null) {
- newChildLanes = mergeLanes(newChildLanes, mergeLanes(_child3.lanes, _child3.childLanes)); // "Static" flags share the lifetime of the fiber/hook they belong to,
- // so we should bubble those up even during a bailout. All the other
- // flags have a lifetime only of a single render + commit, so we should
- // ignore them.
- subtreeFlags |= _child3.subtreeFlags & StaticMask;
- subtreeFlags |= _child3.flags & StaticMask; // Update the return pointer so the tree is consistent. This is a code
- // smell because it assumes the commit phase is never concurrent with
- // the render phase. Will address during refactor to alternate model.
- _child3.return = completedWork;
- _child3 = _child3.sibling;
- }
- }
- completedWork.subtreeFlags |= subtreeFlags;
- }
- completedWork.childLanes = newChildLanes;
- return didBailout;
- }
- function completeDehydratedSuspenseBoundary(current, workInProgress, nextState) {
- if (hasUnhydratedTailNodes() && (workInProgress.mode & ConcurrentMode) !== NoMode && (workInProgress.flags & DidCapture) === NoFlags) {
- warnIfUnhydratedTailNodes(workInProgress);
- resetHydrationState();
- workInProgress.flags |= ForceClientRender | Incomplete | ShouldCapture;
- return false;
- }
- var wasHydrated = popHydrationState(workInProgress);
- if (nextState !== null && nextState.dehydrated !== null) {
- // We might be inside a hydration state the first time we're picking up this
- // Suspense boundary, and also after we've reentered it for further hydration.
- if (current === null) {
- if (!wasHydrated) {
- throw new Error('A dehydrated suspense component was completed without a hydrated node. ' + 'This is probably a bug in React.');
- }
- prepareToHydrateHostSuspenseInstance(workInProgress);
- bubbleProperties(workInProgress);
- {
- if ((workInProgress.mode & ProfileMode) !== NoMode) {
- var isTimedOutSuspense = nextState !== null;
- if (isTimedOutSuspense) {
- // Don't count time spent in a timed out Suspense subtree as part of the base duration.
- var primaryChildFragment = workInProgress.child;
- if (primaryChildFragment !== null) {
- // $FlowFixMe Flow doesn't support type casting in combination with the -= operator
- workInProgress.treeBaseDuration -= primaryChildFragment.treeBaseDuration;
- }
- }
- }
- }
- return false;
- } else {
- // We might have reentered this boundary to hydrate it. If so, we need to reset the hydration
- // state since we're now exiting out of it. popHydrationState doesn't do that for us.
- resetHydrationState();
- if ((workInProgress.flags & DidCapture) === NoFlags) {
- // This boundary did not suspend so it's now hydrated and unsuspended.
- workInProgress.memoizedState = null;
- } // If nothing suspended, we need to schedule an effect to mark this boundary
- // as having hydrated so events know that they're free to be invoked.
- // It's also a signal to replay events and the suspense callback.
- // If something suspended, schedule an effect to attach retry listeners.
- // So we might as well always mark this.
- workInProgress.flags |= Update;
- bubbleProperties(workInProgress);
- {
- if ((workInProgress.mode & ProfileMode) !== NoMode) {
- var _isTimedOutSuspense = nextState !== null;
- if (_isTimedOutSuspense) {
- // Don't count time spent in a timed out Suspense subtree as part of the base duration.
- var _primaryChildFragment = workInProgress.child;
- if (_primaryChildFragment !== null) {
- // $FlowFixMe Flow doesn't support type casting in combination with the -= operator
- workInProgress.treeBaseDuration -= _primaryChildFragment.treeBaseDuration;
- }
- }
- }
- }
- return false;
- }
- } else {
- // Successfully completed this tree. If this was a forced client render,
- // there may have been recoverable errors during first hydration
- // attempt. If so, add them to a queue so we can log them in the
- // commit phase.
- upgradeHydrationErrorsToRecoverable(); // Fall through to normal Suspense path
- return true;
- }
- }
- function completeWork(current, workInProgress, renderLanes) {
- var newProps = workInProgress.pendingProps; // Note: This intentionally doesn't check if we're hydrating because comparing
- // to the current tree provider fiber is just as fast and less error-prone.
- // Ideally we would have a special version of the work loop only
- // for hydration.
- popTreeContext(workInProgress);
- switch (workInProgress.tag) {
- case IndeterminateComponent:
- case LazyComponent:
- case SimpleMemoComponent:
- case FunctionComponent:
- case ForwardRef:
- case Fragment:
- case Mode:
- case Profiler:
- case ContextConsumer:
- case MemoComponent:
- bubbleProperties(workInProgress);
- return null;
- case ClassComponent:
- {
- var Component = workInProgress.type;
- if (isContextProvider(Component)) {
- popContext(workInProgress);
- }
- bubbleProperties(workInProgress);
- return null;
- }
- case HostRoot:
- {
- var fiberRoot = workInProgress.stateNode;
- popHostContainer(workInProgress);
- popTopLevelContextObject(workInProgress);
- resetWorkInProgressVersions();
- if (fiberRoot.pendingContext) {
- fiberRoot.context = fiberRoot.pendingContext;
- fiberRoot.pendingContext = null;
- }
- if (current === null || current.child === null) {
- // If we hydrated, pop so that we can delete any remaining children
- // that weren't hydrated.
- var wasHydrated = popHydrationState(workInProgress);
- if (wasHydrated) {
- // If we hydrated, then we'll need to schedule an update for
- // the commit side-effects on the root.
- markUpdate(workInProgress);
- } else {
- if (current !== null) {
- var prevState = current.memoizedState;
- if ( // Check if this is a client root
- !prevState.isDehydrated || // Check if we reverted to client rendering (e.g. due to an error)
- (workInProgress.flags & ForceClientRender) !== NoFlags) {
- // Schedule an effect to clear this container at the start of the
- // next commit. This handles the case of React rendering into a
- // container with previous children. It's also safe to do for
- // updates too, because current.child would only be null if the
- // previous render was null (so the container would already
- // be empty).
- workInProgress.flags |= Snapshot; // If this was a forced client render, there may have been
- // recoverable errors during first hydration attempt. If so, add
- // them to a queue so we can log them in the commit phase.
- upgradeHydrationErrorsToRecoverable();
- }
- }
- }
- }
- updateHostContainer(current, workInProgress);
- bubbleProperties(workInProgress);
- return null;
- }
- case HostComponent:
- {
- popHostContext(workInProgress);
- var rootContainerInstance = getRootHostContainer();
- var type = workInProgress.type;
- if (current !== null && workInProgress.stateNode != null) {
- updateHostComponent$1(current, workInProgress, type, newProps, rootContainerInstance);
- if (current.ref !== workInProgress.ref) {
- markRef$1(workInProgress);
- }
- } else {
- if (!newProps) {
- if (workInProgress.stateNode === null) {
- throw new Error('We must have new props for new mounts. This error is likely ' + 'caused by a bug in React. Please file an issue.');
- } // This can happen when we abort work.
- bubbleProperties(workInProgress);
- return null;
- }
- var currentHostContext = getHostContext(); // TODO: Move createInstance to beginWork and keep it on a context
- // "stack" as the parent. Then append children as we go in beginWork
- // or completeWork depending on whether we want to add them top->down or
- // bottom->up. Top->down is faster in IE11.
- var _wasHydrated = popHydrationState(workInProgress);
- if (_wasHydrated) {
- // TODO: Move this and createInstance step into the beginPhase
- // to consolidate.
- if (prepareToHydrateHostInstance(workInProgress, rootContainerInstance, currentHostContext)) {
- // If changes to the hydrated node need to be applied at the
- // commit-phase we mark this as such.
- markUpdate(workInProgress);
- }
- } else {
- var instance = createInstance(type, newProps, rootContainerInstance, currentHostContext, workInProgress);
- appendAllChildren(instance, workInProgress, false, false);
- workInProgress.stateNode = instance; // Certain renderers require commit-time effects for initial mount.
- // (eg DOM renderer supports auto-focus for certain elements).
- // Make sure such renderers get scheduled for later work.
- if (finalizeInitialChildren(instance, type, newProps, rootContainerInstance)) {
- markUpdate(workInProgress);
- }
- }
- if (workInProgress.ref !== null) {
- // If there is a ref on a host node we need to schedule a callback
- markRef$1(workInProgress);
- }
- }
- bubbleProperties(workInProgress);
- return null;
- }
- case HostText:
- {
- var newText = newProps;
- if (current && workInProgress.stateNode != null) {
- var oldText = current.memoizedProps; // If we have an alternate, that means this is an update and we need
- // to schedule a side-effect to do the updates.
- updateHostText$1(current, workInProgress, oldText, newText);
- } else {
- if (typeof newText !== 'string') {
- if (workInProgress.stateNode === null) {
- throw new Error('We must have new props for new mounts. This error is likely ' + 'caused by a bug in React. Please file an issue.');
- } // This can happen when we abort work.
- }
- var _rootContainerInstance = getRootHostContainer();
- var _currentHostContext = getHostContext();
- var _wasHydrated2 = popHydrationState(workInProgress);
- if (_wasHydrated2) {
- if (prepareToHydrateHostTextInstance(workInProgress)) {
- markUpdate(workInProgress);
- }
- } else {
- workInProgress.stateNode = createTextInstance(newText, _rootContainerInstance, _currentHostContext, workInProgress);
- }
- }
- bubbleProperties(workInProgress);
- return null;
- }
- case SuspenseComponent:
- {
- popSuspenseContext(workInProgress);
- var nextState = workInProgress.memoizedState; // Special path for dehydrated boundaries. We may eventually move this
- // to its own fiber type so that we can add other kinds of hydration
- // boundaries that aren't associated with a Suspense tree. In anticipation
- // of such a refactor, all the hydration logic is contained in
- // this branch.
- if (current === null || current.memoizedState !== null && current.memoizedState.dehydrated !== null) {
- var fallthroughToNormalSuspensePath = completeDehydratedSuspenseBoundary(current, workInProgress, nextState);
- if (!fallthroughToNormalSuspensePath) {
- if (workInProgress.flags & ShouldCapture) {
- // Special case. There were remaining unhydrated nodes. We treat
- // this as a mismatch. Revert to client rendering.
- return workInProgress;
- } else {
- // Did not finish hydrating, either because this is the initial
- // render or because something suspended.
- return null;
- }
- } // Continue with the normal Suspense path.
- }
- if ((workInProgress.flags & DidCapture) !== NoFlags) {
- // Something suspended. Re-render with the fallback children.
- workInProgress.lanes = renderLanes; // Do not reset the effect list.
- if ((workInProgress.mode & ProfileMode) !== NoMode) {
- transferActualDuration(workInProgress);
- } // Don't bubble properties in this case.
- return workInProgress;
- }
- var nextDidTimeout = nextState !== null;
- var prevDidTimeout = current !== null && current.memoizedState !== null;
- // a passive effect, which is when we process the transitions
- if (nextDidTimeout !== prevDidTimeout) {
- // an effect to toggle the subtree's visibility. When we switch from
- // fallback -> primary, the inner Offscreen fiber schedules this effect
- // as part of its normal complete phase. But when we switch from
- // primary -> fallback, the inner Offscreen fiber does not have a complete
- // phase. So we need to schedule its effect here.
- //
- // We also use this flag to connect/disconnect the effects, but the same
- // logic applies: when re-connecting, the Offscreen fiber's complete
- // phase will handle scheduling the effect. It's only when the fallback
- // is active that we have to do anything special.
- if (nextDidTimeout) {
- var _offscreenFiber2 = workInProgress.child;
- _offscreenFiber2.flags |= Visibility; // TODO: This will still suspend a synchronous tree if anything
- // in the concurrent tree already suspended during this render.
- // This is a known bug.
- if ((workInProgress.mode & ConcurrentMode) !== NoMode) {
- // TODO: Move this back to throwException because this is too late
- // if this is a large tree which is common for initial loads. We
- // don't know if we should restart a render or not until we get
- // this marker, and this is too late.
- // If this render already had a ping or lower pri updates,
- // and this is the first time we know we're going to suspend we
- // should be able to immediately restart from within throwException.
- var hasInvisibleChildContext = current === null && (workInProgress.memoizedProps.unstable_avoidThisFallback !== true || !enableSuspenseAvoidThisFallback);
- if (hasInvisibleChildContext || hasSuspenseContext(suspenseStackCursor.current, InvisibleParentSuspenseContext)) {
- // If this was in an invisible tree or a new render, then showing
- // this boundary is ok.
- renderDidSuspend();
- } else {
- // Otherwise, we're going to have to hide content so we should
- // suspend for longer if possible.
- renderDidSuspendDelayIfPossible();
- }
- }
- }
- }
- var wakeables = workInProgress.updateQueue;
- if (wakeables !== null) {
- // Schedule an effect to attach a retry listener to the promise.
- // TODO: Move to passive phase
- workInProgress.flags |= Update;
- }
- bubbleProperties(workInProgress);
- {
- if ((workInProgress.mode & ProfileMode) !== NoMode) {
- if (nextDidTimeout) {
- // Don't count time spent in a timed out Suspense subtree as part of the base duration.
- var primaryChildFragment = workInProgress.child;
- if (primaryChildFragment !== null) {
- // $FlowFixMe Flow doesn't support type casting in combination with the -= operator
- workInProgress.treeBaseDuration -= primaryChildFragment.treeBaseDuration;
- }
- }
- }
- }
- return null;
- }
- case HostPortal:
- popHostContainer(workInProgress);
- updateHostContainer(current, workInProgress);
- if (current === null) {
- preparePortalMount(workInProgress.stateNode.containerInfo);
- }
- bubbleProperties(workInProgress);
- return null;
- case ContextProvider:
- // Pop provider fiber
- var context = workInProgress.type._context;
- popProvider(context, workInProgress);
- bubbleProperties(workInProgress);
- return null;
- case IncompleteClassComponent:
- {
- // Same as class component case. I put it down here so that the tags are
- // sequential to ensure this switch is compiled to a jump table.
- var _Component = workInProgress.type;
- if (isContextProvider(_Component)) {
- popContext(workInProgress);
- }
- bubbleProperties(workInProgress);
- return null;
- }
- case SuspenseListComponent:
- {
- popSuspenseContext(workInProgress);
- var renderState = workInProgress.memoizedState;
- if (renderState === null) {
- // We're running in the default, "independent" mode.
- // We don't do anything in this mode.
- bubbleProperties(workInProgress);
- return null;
- }
- var didSuspendAlready = (workInProgress.flags & DidCapture) !== NoFlags;
- var renderedTail = renderState.rendering;
- if (renderedTail === null) {
- // We just rendered the head.
- if (!didSuspendAlready) {
- // This is the first pass. We need to figure out if anything is still
- // suspended in the rendered set.
- // If new content unsuspended, but there's still some content that
- // didn't. Then we need to do a second pass that forces everything
- // to keep showing their fallbacks.
- // We might be suspended if something in this render pass suspended, or
- // something in the previous committed pass suspended. Otherwise,
- // there's no chance so we can skip the expensive call to
- // findFirstSuspended.
- var cannotBeSuspended = renderHasNotSuspendedYet() && (current === null || (current.flags & DidCapture) === NoFlags);
- if (!cannotBeSuspended) {
- var row = workInProgress.child;
- while (row !== null) {
- var suspended = findFirstSuspended(row);
- if (suspended !== null) {
- didSuspendAlready = true;
- workInProgress.flags |= DidCapture;
- cutOffTailIfNeeded(renderState, false); // If this is a newly suspended tree, it might not get committed as
- // part of the second pass. In that case nothing will subscribe to
- // its thenables. Instead, we'll transfer its thenables to the
- // SuspenseList so that it can retry if they resolve.
- // There might be multiple of these in the list but since we're
- // going to wait for all of them anyway, it doesn't really matter
- // which ones gets to ping. In theory we could get clever and keep
- // track of how many dependencies remain but it gets tricky because
- // in the meantime, we can add/remove/change items and dependencies.
- // We might bail out of the loop before finding any but that
- // doesn't matter since that means that the other boundaries that
- // we did find already has their listeners attached.
- var newThenables = suspended.updateQueue;
- if (newThenables !== null) {
- workInProgress.updateQueue = newThenables;
- workInProgress.flags |= Update;
- } // Rerender the whole list, but this time, we'll force fallbacks
- // to stay in place.
- // Reset the effect flags before doing the second pass since that's now invalid.
- // Reset the child fibers to their original state.
- workInProgress.subtreeFlags = NoFlags;
- resetChildFibers(workInProgress, renderLanes); // Set up the Suspense Context to force suspense and immediately
- // rerender the children.
- pushSuspenseContext(workInProgress, setShallowSuspenseContext(suspenseStackCursor.current, ForceSuspenseFallback)); // Don't bubble properties in this case.
- return workInProgress.child;
- }
- row = row.sibling;
- }
- }
- if (renderState.tail !== null && now() > getRenderTargetTime()) {
- // We have already passed our CPU deadline but we still have rows
- // left in the tail. We'll just give up further attempts to render
- // the main content and only render fallbacks.
- workInProgress.flags |= DidCapture;
- didSuspendAlready = true;
- cutOffTailIfNeeded(renderState, false); // Since nothing actually suspended, there will nothing to ping this
- // to get it started back up to attempt the next item. While in terms
- // of priority this work has the same priority as this current render,
- // it's not part of the same transition once the transition has
- // committed. If it's sync, we still want to yield so that it can be
- // painted. Conceptually, this is really the same as pinging.
- // We can use any RetryLane even if it's the one currently rendering
- // since we're leaving it behind on this node.
- workInProgress.lanes = SomeRetryLane;
- }
- } else {
- cutOffTailIfNeeded(renderState, false);
- } // Next we're going to render the tail.
- } else {
- // Append the rendered row to the child list.
- if (!didSuspendAlready) {
- var _suspended = findFirstSuspended(renderedTail);
- if (_suspended !== null) {
- workInProgress.flags |= DidCapture;
- didSuspendAlready = true; // Ensure we transfer the update queue to the parent so that it doesn't
- // get lost if this row ends up dropped during a second pass.
- var _newThenables = _suspended.updateQueue;
- if (_newThenables !== null) {
- workInProgress.updateQueue = _newThenables;
- workInProgress.flags |= Update;
- }
- cutOffTailIfNeeded(renderState, true); // This might have been modified.
- if (renderState.tail === null && renderState.tailMode === 'hidden' && !renderedTail.alternate && !getIsHydrating() // We don't cut it if we're hydrating.
- ) {
- // We're done.
- bubbleProperties(workInProgress);
- return null;
- }
- } else if ( // The time it took to render last row is greater than the remaining
- // time we have to render. So rendering one more row would likely
- // exceed it.
- now() * 2 - renderState.renderingStartTime > getRenderTargetTime() && renderLanes !== OffscreenLane) {
- // We have now passed our CPU deadline and we'll just give up further
- // attempts to render the main content and only render fallbacks.
- // The assumption is that this is usually faster.
- workInProgress.flags |= DidCapture;
- didSuspendAlready = true;
- cutOffTailIfNeeded(renderState, false); // Since nothing actually suspended, there will nothing to ping this
- // to get it started back up to attempt the next item. While in terms
- // of priority this work has the same priority as this current render,
- // it's not part of the same transition once the transition has
- // committed. If it's sync, we still want to yield so that it can be
- // painted. Conceptually, this is really the same as pinging.
- // We can use any RetryLane even if it's the one currently rendering
- // since we're leaving it behind on this node.
- workInProgress.lanes = SomeRetryLane;
- }
- }
- if (renderState.isBackwards) {
- // The effect list of the backwards tail will have been added
- // to the end. This breaks the guarantee that life-cycles fire in
- // sibling order but that isn't a strong guarantee promised by React.
- // Especially since these might also just pop in during future commits.
- // Append to the beginning of the list.
- renderedTail.sibling = workInProgress.child;
- workInProgress.child = renderedTail;
- } else {
- var previousSibling = renderState.last;
- if (previousSibling !== null) {
- previousSibling.sibling = renderedTail;
- } else {
- workInProgress.child = renderedTail;
- }
- renderState.last = renderedTail;
- }
- }
- if (renderState.tail !== null) {
- // We still have tail rows to render.
- // Pop a row.
- var next = renderState.tail;
- renderState.rendering = next;
- renderState.tail = next.sibling;
- renderState.renderingStartTime = now();
- next.sibling = null; // Restore the context.
- // TODO: We can probably just avoid popping it instead and only
- // setting it the first time we go from not suspended to suspended.
- var suspenseContext = suspenseStackCursor.current;
- if (didSuspendAlready) {
- suspenseContext = setShallowSuspenseContext(suspenseContext, ForceSuspenseFallback);
- } else {
- suspenseContext = setDefaultShallowSuspenseContext(suspenseContext);
- }
- pushSuspenseContext(workInProgress, suspenseContext); // Do a pass over the next row.
- // Don't bubble properties in this case.
- return next;
- }
- bubbleProperties(workInProgress);
- return null;
- }
- case ScopeComponent:
- {
- break;
- }
- case OffscreenComponent:
- case LegacyHiddenComponent:
- {
- popRenderLanes(workInProgress);
- var _nextState = workInProgress.memoizedState;
- var nextIsHidden = _nextState !== null;
- if (current !== null) {
- var _prevState = current.memoizedState;
- var prevIsHidden = _prevState !== null;
- if (prevIsHidden !== nextIsHidden && ( // LegacyHidden doesn't do any hiding — it only pre-renders.
- !enableLegacyHidden)) {
- workInProgress.flags |= Visibility;
- }
- }
- if (!nextIsHidden || (workInProgress.mode & ConcurrentMode) === NoMode) {
- bubbleProperties(workInProgress);
- } else {
- // Don't bubble properties for hidden children unless we're rendering
- // at offscreen priority.
- if (includesSomeLane(subtreeRenderLanes, OffscreenLane)) {
- bubbleProperties(workInProgress);
- {
- // Check if there was an insertion or update in the hidden subtree.
- // If so, we need to hide those nodes in the commit phase, so
- // schedule a visibility effect.
- if (workInProgress.subtreeFlags & (Placement | Update)) {
- workInProgress.flags |= Visibility;
- }
- }
- }
- }
- return null;
- }
- case CacheComponent:
- {
- return null;
- }
- case TracingMarkerComponent:
- {
- return null;
- }
- }
- throw new Error("Unknown unit of work tag (" + workInProgress.tag + "). This error is likely caused by a bug in " + 'React. Please file an issue.');
- }
- function unwindWork(current, workInProgress, renderLanes) {
- // Note: This intentionally doesn't check if we're hydrating because comparing
- // to the current tree provider fiber is just as fast and less error-prone.
- // Ideally we would have a special version of the work loop only
- // for hydration.
- popTreeContext(workInProgress);
- switch (workInProgress.tag) {
- case ClassComponent:
- {
- var Component = workInProgress.type;
- if (isContextProvider(Component)) {
- popContext(workInProgress);
- }
- var flags = workInProgress.flags;
- if (flags & ShouldCapture) {
- workInProgress.flags = flags & ~ShouldCapture | DidCapture;
- if ((workInProgress.mode & ProfileMode) !== NoMode) {
- transferActualDuration(workInProgress);
- }
- return workInProgress;
- }
- return null;
- }
- case HostRoot:
- {
- var root = workInProgress.stateNode;
- popHostContainer(workInProgress);
- popTopLevelContextObject(workInProgress);
- resetWorkInProgressVersions();
- var _flags = workInProgress.flags;
- if ((_flags & ShouldCapture) !== NoFlags && (_flags & DidCapture) === NoFlags) {
- // There was an error during render that wasn't captured by a suspense
- // boundary. Do a second pass on the root to unmount the children.
- workInProgress.flags = _flags & ~ShouldCapture | DidCapture;
- return workInProgress;
- } // We unwound to the root without completing it. Exit.
- return null;
- }
- case HostComponent:
- {
- // TODO: popHydrationState
- popHostContext(workInProgress);
- return null;
- }
- case SuspenseComponent:
- {
- popSuspenseContext(workInProgress);
- var suspenseState = workInProgress.memoizedState;
- if (suspenseState !== null && suspenseState.dehydrated !== null) {
- if (workInProgress.alternate === null) {
- throw new Error('Threw in newly mounted dehydrated component. This is likely a bug in ' + 'React. Please file an issue.');
- }
- resetHydrationState();
- }
- var _flags2 = workInProgress.flags;
- if (_flags2 & ShouldCapture) {
- workInProgress.flags = _flags2 & ~ShouldCapture | DidCapture; // Captured a suspense effect. Re-render the boundary.
- if ((workInProgress.mode & ProfileMode) !== NoMode) {
- transferActualDuration(workInProgress);
- }
- return workInProgress;
- }
- return null;
- }
- case SuspenseListComponent:
- {
- popSuspenseContext(workInProgress); // SuspenseList doesn't actually catch anything. It should've been
- // caught by a nested boundary. If not, it should bubble through.
- return null;
- }
- case HostPortal:
- popHostContainer(workInProgress);
- return null;
- case ContextProvider:
- var context = workInProgress.type._context;
- popProvider(context, workInProgress);
- return null;
- case OffscreenComponent:
- case LegacyHiddenComponent:
- popRenderLanes(workInProgress);
- return null;
- case CacheComponent:
- return null;
- default:
- return null;
- }
- }
- function unwindInterruptedWork(current, interruptedWork, renderLanes) {
- // Note: This intentionally doesn't check if we're hydrating because comparing
- // to the current tree provider fiber is just as fast and less error-prone.
- // Ideally we would have a special version of the work loop only
- // for hydration.
- popTreeContext(interruptedWork);
- switch (interruptedWork.tag) {
- case ClassComponent:
- {
- var childContextTypes = interruptedWork.type.childContextTypes;
- if (childContextTypes !== null && childContextTypes !== undefined) {
- popContext(interruptedWork);
- }
- break;
- }
- case HostRoot:
- {
- var root = interruptedWork.stateNode;
- popHostContainer(interruptedWork);
- popTopLevelContextObject(interruptedWork);
- resetWorkInProgressVersions();
- break;
- }
- case HostComponent:
- {
- popHostContext(interruptedWork);
- break;
- }
- case HostPortal:
- popHostContainer(interruptedWork);
- break;
- case SuspenseComponent:
- popSuspenseContext(interruptedWork);
- break;
- case SuspenseListComponent:
- popSuspenseContext(interruptedWork);
- break;
- case ContextProvider:
- var context = interruptedWork.type._context;
- popProvider(context, interruptedWork);
- break;
- case OffscreenComponent:
- case LegacyHiddenComponent:
- popRenderLanes(interruptedWork);
- break;
- }
- }
- var didWarnAboutUndefinedSnapshotBeforeUpdate = null;
- {
- didWarnAboutUndefinedSnapshotBeforeUpdate = new Set();
- } // Used during the commit phase to track the state of the Offscreen component stack.
- // Allows us to avoid traversing the return path to find the nearest Offscreen ancestor.
- // Only used when enableSuspenseLayoutEffectSemantics is enabled.
- var offscreenSubtreeIsHidden = false;
- var offscreenSubtreeWasHidden = false;
- var PossiblyWeakSet = typeof WeakSet === 'function' ? WeakSet : Set;
- var nextEffect = null; // Used for Profiling builds to track updaters.
- var inProgressLanes = null;
- var inProgressRoot = null;
- function reportUncaughtErrorInDEV(error) {
- // Wrapping each small part of the commit phase into a guarded
- // callback is a bit too slow (https://github.com/facebook/react/pull/21666).
- // But we rely on it to surface errors to DEV tools like overlays
- // (https://github.com/facebook/react/issues/21712).
- // As a compromise, rethrow only caught errors in a guard.
- {
- invokeGuardedCallback(null, function () {
- throw error;
- });
- clearCaughtError();
- }
- }
- var callComponentWillUnmountWithTimer = function (current, instance) {
- instance.props = current.memoizedProps;
- instance.state = current.memoizedState;
- if (current.mode & ProfileMode) {
- try {
- startLayoutEffectTimer();
- instance.componentWillUnmount();
- } finally {
- recordLayoutEffectDuration(current);
- }
- } else {
- instance.componentWillUnmount();
- }
- }; // Capture errors so they don't interrupt mounting.
- function safelyCallCommitHookLayoutEffectListMount(current, nearestMountedAncestor) {
- try {
- commitHookEffectListMount(Layout, current);
- } catch (error) {
- captureCommitPhaseError(current, nearestMountedAncestor, error);
- }
- } // Capture errors so they don't interrupt unmounting.
- function safelyCallComponentWillUnmount(current, nearestMountedAncestor, instance) {
- try {
- callComponentWillUnmountWithTimer(current, instance);
- } catch (error) {
- captureCommitPhaseError(current, nearestMountedAncestor, error);
- }
- } // Capture errors so they don't interrupt mounting.
- function safelyCallComponentDidMount(current, nearestMountedAncestor, instance) {
- try {
- instance.componentDidMount();
- } catch (error) {
- captureCommitPhaseError(current, nearestMountedAncestor, error);
- }
- } // Capture errors so they don't interrupt mounting.
- function safelyAttachRef(current, nearestMountedAncestor) {
- try {
- commitAttachRef(current);
- } catch (error) {
- captureCommitPhaseError(current, nearestMountedAncestor, error);
- }
- }
- function safelyDetachRef(current, nearestMountedAncestor) {
- var ref = current.ref;
- if (ref !== null) {
- if (typeof ref === 'function') {
- var retVal;
- try {
- if (enableProfilerTimer && enableProfilerCommitHooks && current.mode & ProfileMode) {
- try {
- startLayoutEffectTimer();
- retVal = ref(null);
- } finally {
- recordLayoutEffectDuration(current);
- }
- } else {
- retVal = ref(null);
- }
- } catch (error) {
- captureCommitPhaseError(current, nearestMountedAncestor, error);
- }
- {
- if (typeof retVal === 'function') {
- error('Unexpected return value from a callback ref in %s. ' + 'A callback ref should not return a function.', getComponentNameFromFiber(current));
- }
- }
- } else {
- ref.current = null;
- }
- }
- }
- function safelyCallDestroy(current, nearestMountedAncestor, destroy) {
- try {
- destroy();
- } catch (error) {
- captureCommitPhaseError(current, nearestMountedAncestor, error);
- }
- }
- var focusedInstanceHandle = null;
- var shouldFireAfterActiveInstanceBlur = false;
- function commitBeforeMutationEffects(root, firstChild) {
- focusedInstanceHandle = prepareForCommit(root.containerInfo);
- nextEffect = firstChild;
- commitBeforeMutationEffects_begin(); // We no longer need to track the active instance fiber
- var shouldFire = shouldFireAfterActiveInstanceBlur;
- shouldFireAfterActiveInstanceBlur = false;
- focusedInstanceHandle = null;
- return shouldFire;
- }
- function commitBeforeMutationEffects_begin() {
- while (nextEffect !== null) {
- var fiber = nextEffect; // This phase is only used for beforeActiveInstanceBlur.
- var child = fiber.child;
- if ((fiber.subtreeFlags & BeforeMutationMask) !== NoFlags && child !== null) {
- child.return = fiber;
- nextEffect = child;
- } else {
- commitBeforeMutationEffects_complete();
- }
- }
- }
- function commitBeforeMutationEffects_complete() {
- while (nextEffect !== null) {
- var fiber = nextEffect;
- setCurrentFiber(fiber);
- try {
- commitBeforeMutationEffectsOnFiber(fiber);
- } catch (error) {
- captureCommitPhaseError(fiber, fiber.return, error);
- }
- resetCurrentFiber();
- var sibling = fiber.sibling;
- if (sibling !== null) {
- sibling.return = fiber.return;
- nextEffect = sibling;
- return;
- }
- nextEffect = fiber.return;
- }
- }
- function commitBeforeMutationEffectsOnFiber(finishedWork) {
- var current = finishedWork.alternate;
- var flags = finishedWork.flags;
- if ((flags & Snapshot) !== NoFlags) {
- setCurrentFiber(finishedWork);
- switch (finishedWork.tag) {
- case FunctionComponent:
- case ForwardRef:
- case SimpleMemoComponent:
- {
- break;
- }
- case ClassComponent:
- {
- if (current !== null) {
- var prevProps = current.memoizedProps;
- var prevState = current.memoizedState;
- var instance = finishedWork.stateNode; // We could update instance props and state here,
- // but instead we rely on them being set during last render.
- // TODO: revisit this when we implement resuming.
- {
- if (finishedWork.type === finishedWork.elementType && !didWarnAboutReassigningProps) {
- if (instance.props !== finishedWork.memoizedProps) {
- error('Expected %s props to match memoized props before ' + 'getSnapshotBeforeUpdate. ' + 'This might either be because of a bug in React, or because ' + 'a component reassigns its own `this.props`. ' + 'Please file an issue.', getComponentNameFromFiber(finishedWork) || 'instance');
- }
- if (instance.state !== finishedWork.memoizedState) {
- error('Expected %s state to match memoized state before ' + 'getSnapshotBeforeUpdate. ' + 'This might either be because of a bug in React, or because ' + 'a component reassigns its own `this.state`. ' + 'Please file an issue.', getComponentNameFromFiber(finishedWork) || 'instance');
- }
- }
- }
- var snapshot = instance.getSnapshotBeforeUpdate(finishedWork.elementType === finishedWork.type ? prevProps : resolveDefaultProps(finishedWork.type, prevProps), prevState);
- {
- var didWarnSet = didWarnAboutUndefinedSnapshotBeforeUpdate;
- if (snapshot === undefined && !didWarnSet.has(finishedWork.type)) {
- didWarnSet.add(finishedWork.type);
- error('%s.getSnapshotBeforeUpdate(): A snapshot value (or null) ' + 'must be returned. You have returned undefined.', getComponentNameFromFiber(finishedWork));
- }
- }
- instance.__reactInternalSnapshotBeforeUpdate = snapshot;
- }
- break;
- }
- case HostRoot:
- {
- {
- var root = finishedWork.stateNode;
- clearContainer(root.containerInfo);
- }
- break;
- }
- case HostComponent:
- case HostText:
- case HostPortal:
- case IncompleteClassComponent:
- // Nothing to do for these component types
- break;
- default:
- {
- throw new Error('This unit of work tag should not have side-effects. This error is ' + 'likely caused by a bug in React. Please file an issue.');
- }
- }
- resetCurrentFiber();
- }
- }
- function commitHookEffectListUnmount(flags, finishedWork, nearestMountedAncestor) {
- var updateQueue = finishedWork.updateQueue;
- var lastEffect = updateQueue !== null ? updateQueue.lastEffect : null;
- if (lastEffect !== null) {
- var firstEffect = lastEffect.next;
- var effect = firstEffect;
- do {
- if ((effect.tag & flags) === flags) {
- // Unmount
- var destroy = effect.destroy;
- effect.destroy = undefined;
- if (destroy !== undefined) {
- {
- if ((flags & Passive$1) !== NoFlags$1) {
- markComponentPassiveEffectUnmountStarted(finishedWork);
- } else if ((flags & Layout) !== NoFlags$1) {
- markComponentLayoutEffectUnmountStarted(finishedWork);
- }
- }
- {
- if ((flags & Insertion) !== NoFlags$1) {
- setIsRunningInsertionEffect(true);
- }
- }
- safelyCallDestroy(finishedWork, nearestMountedAncestor, destroy);
- {
- if ((flags & Insertion) !== NoFlags$1) {
- setIsRunningInsertionEffect(false);
- }
- }
- {
- if ((flags & Passive$1) !== NoFlags$1) {
- markComponentPassiveEffectUnmountStopped();
- } else if ((flags & Layout) !== NoFlags$1) {
- markComponentLayoutEffectUnmountStopped();
- }
- }
- }
- }
- effect = effect.next;
- } while (effect !== firstEffect);
- }
- }
- function commitHookEffectListMount(flags, finishedWork) {
- var updateQueue = finishedWork.updateQueue;
- var lastEffect = updateQueue !== null ? updateQueue.lastEffect : null;
- if (lastEffect !== null) {
- var firstEffect = lastEffect.next;
- var effect = firstEffect;
- do {
- if ((effect.tag & flags) === flags) {
- {
- if ((flags & Passive$1) !== NoFlags$1) {
- markComponentPassiveEffectMountStarted(finishedWork);
- } else if ((flags & Layout) !== NoFlags$1) {
- markComponentLayoutEffectMountStarted(finishedWork);
- }
- } // Mount
- var create = effect.create;
- {
- if ((flags & Insertion) !== NoFlags$1) {
- setIsRunningInsertionEffect(true);
- }
- }
- effect.destroy = create();
- {
- if ((flags & Insertion) !== NoFlags$1) {
- setIsRunningInsertionEffect(false);
- }
- }
- {
- if ((flags & Passive$1) !== NoFlags$1) {
- markComponentPassiveEffectMountStopped();
- } else if ((flags & Layout) !== NoFlags$1) {
- markComponentLayoutEffectMountStopped();
- }
- }
- {
- var destroy = effect.destroy;
- if (destroy !== undefined && typeof destroy !== 'function') {
- var hookName = void 0;
- if ((effect.tag & Layout) !== NoFlags) {
- hookName = 'useLayoutEffect';
- } else if ((effect.tag & Insertion) !== NoFlags) {
- hookName = 'useInsertionEffect';
- } else {
- hookName = 'useEffect';
- }
- var addendum = void 0;
- if (destroy === null) {
- addendum = ' You returned null. If your effect does not require clean ' + 'up, return undefined (or nothing).';
- } else if (typeof destroy.then === 'function') {
- addendum = '\n\nIt looks like you wrote ' + hookName + '(async () => ...) or returned a Promise. ' + 'Instead, write the async function inside your effect ' + 'and call it immediately:\n\n' + hookName + '(() => {\n' + ' async function fetchData() {\n' + ' // You can await here\n' + ' const response = await MyAPI.getData(someId);\n' + ' // ...\n' + ' }\n' + ' fetchData();\n' + "}, [someId]); // Or [] if effect doesn't need props or state\n\n" + 'Learn more about data fetching with Hooks: https://reactjs.org/link/hooks-data-fetching';
- } else {
- addendum = ' You returned: ' + destroy;
- }
- error('%s must not return anything besides a function, ' + 'which is used for clean-up.%s', hookName, addendum);
- }
- }
- }
- effect = effect.next;
- } while (effect !== firstEffect);
- }
- }
- function commitPassiveEffectDurations(finishedRoot, finishedWork) {
- {
- // Only Profilers with work in their subtree will have an Update effect scheduled.
- if ((finishedWork.flags & Update) !== NoFlags) {
- switch (finishedWork.tag) {
- case Profiler:
- {
- var passiveEffectDuration = finishedWork.stateNode.passiveEffectDuration;
- var _finishedWork$memoize = finishedWork.memoizedProps,
- id = _finishedWork$memoize.id,
- onPostCommit = _finishedWork$memoize.onPostCommit; // This value will still reflect the previous commit phase.
- // It does not get reset until the start of the next commit phase.
- var commitTime = getCommitTime();
- var phase = finishedWork.alternate === null ? 'mount' : 'update';
- {
- if (isCurrentUpdateNested()) {
- phase = 'nested-update';
- }
- }
- if (typeof onPostCommit === 'function') {
- onPostCommit(id, phase, passiveEffectDuration, commitTime);
- } // Bubble times to the next nearest ancestor Profiler.
- // After we process that Profiler, we'll bubble further up.
- var parentFiber = finishedWork.return;
- outer: while (parentFiber !== null) {
- switch (parentFiber.tag) {
- case HostRoot:
- var root = parentFiber.stateNode;
- root.passiveEffectDuration += passiveEffectDuration;
- break outer;
- case Profiler:
- var parentStateNode = parentFiber.stateNode;
- parentStateNode.passiveEffectDuration += passiveEffectDuration;
- break outer;
- }
- parentFiber = parentFiber.return;
- }
- break;
- }
- }
- }
- }
- }
- function commitLayoutEffectOnFiber(finishedRoot, current, finishedWork, committedLanes) {
- if ((finishedWork.flags & LayoutMask) !== NoFlags) {
- switch (finishedWork.tag) {
- case FunctionComponent:
- case ForwardRef:
- case SimpleMemoComponent:
- {
- if (!offscreenSubtreeWasHidden) {
- // At this point layout effects have already been destroyed (during mutation phase).
- // This is done to prevent sibling component effects from interfering with each other,
- // e.g. a destroy function in one component should never override a ref set
- // by a create function in another component during the same commit.
- if (finishedWork.mode & ProfileMode) {
- try {
- startLayoutEffectTimer();
- commitHookEffectListMount(Layout | HasEffect, finishedWork);
- } finally {
- recordLayoutEffectDuration(finishedWork);
- }
- } else {
- commitHookEffectListMount(Layout | HasEffect, finishedWork);
- }
- }
- break;
- }
- case ClassComponent:
- {
- var instance = finishedWork.stateNode;
- if (finishedWork.flags & Update) {
- if (!offscreenSubtreeWasHidden) {
- if (current === null) {
- // We could update instance props and state here,
- // but instead we rely on them being set during last render.
- // TODO: revisit this when we implement resuming.
- {
- if (finishedWork.type === finishedWork.elementType && !didWarnAboutReassigningProps) {
- if (instance.props !== finishedWork.memoizedProps) {
- error('Expected %s props to match memoized props before ' + 'componentDidMount. ' + 'This might either be because of a bug in React, or because ' + 'a component reassigns its own `this.props`. ' + 'Please file an issue.', getComponentNameFromFiber(finishedWork) || 'instance');
- }
- if (instance.state !== finishedWork.memoizedState) {
- error('Expected %s state to match memoized state before ' + 'componentDidMount. ' + 'This might either be because of a bug in React, or because ' + 'a component reassigns its own `this.state`. ' + 'Please file an issue.', getComponentNameFromFiber(finishedWork) || 'instance');
- }
- }
- }
- if (finishedWork.mode & ProfileMode) {
- try {
- startLayoutEffectTimer();
- instance.componentDidMount();
- } finally {
- recordLayoutEffectDuration(finishedWork);
- }
- } else {
- instance.componentDidMount();
- }
- } else {
- var prevProps = finishedWork.elementType === finishedWork.type ? current.memoizedProps : resolveDefaultProps(finishedWork.type, current.memoizedProps);
- var prevState = current.memoizedState; // We could update instance props and state here,
- // but instead we rely on them being set during last render.
- // TODO: revisit this when we implement resuming.
- {
- if (finishedWork.type === finishedWork.elementType && !didWarnAboutReassigningProps) {
- if (instance.props !== finishedWork.memoizedProps) {
- error('Expected %s props to match memoized props before ' + 'componentDidUpdate. ' + 'This might either be because of a bug in React, or because ' + 'a component reassigns its own `this.props`. ' + 'Please file an issue.', getComponentNameFromFiber(finishedWork) || 'instance');
- }
- if (instance.state !== finishedWork.memoizedState) {
- error('Expected %s state to match memoized state before ' + 'componentDidUpdate. ' + 'This might either be because of a bug in React, or because ' + 'a component reassigns its own `this.state`. ' + 'Please file an issue.', getComponentNameFromFiber(finishedWork) || 'instance');
- }
- }
- }
- if (finishedWork.mode & ProfileMode) {
- try {
- startLayoutEffectTimer();
- instance.componentDidUpdate(prevProps, prevState, instance.__reactInternalSnapshotBeforeUpdate);
- } finally {
- recordLayoutEffectDuration(finishedWork);
- }
- } else {
- instance.componentDidUpdate(prevProps, prevState, instance.__reactInternalSnapshotBeforeUpdate);
- }
- }
- }
- } // TODO: I think this is now always non-null by the time it reaches the
- // commit phase. Consider removing the type check.
- var updateQueue = finishedWork.updateQueue;
- if (updateQueue !== null) {
- {
- if (finishedWork.type === finishedWork.elementType && !didWarnAboutReassigningProps) {
- if (instance.props !== finishedWork.memoizedProps) {
- error('Expected %s props to match memoized props before ' + 'processing the update queue. ' + 'This might either be because of a bug in React, or because ' + 'a component reassigns its own `this.props`. ' + 'Please file an issue.', getComponentNameFromFiber(finishedWork) || 'instance');
- }
- if (instance.state !== finishedWork.memoizedState) {
- error('Expected %s state to match memoized state before ' + 'processing the update queue. ' + 'This might either be because of a bug in React, or because ' + 'a component reassigns its own `this.state`. ' + 'Please file an issue.', getComponentNameFromFiber(finishedWork) || 'instance');
- }
- }
- } // We could update instance props and state here,
- // but instead we rely on them being set during last render.
- // TODO: revisit this when we implement resuming.
- commitUpdateQueue(finishedWork, updateQueue, instance);
- }
- break;
- }
- case HostRoot:
- {
- // TODO: I think this is now always non-null by the time it reaches the
- // commit phase. Consider removing the type check.
- var _updateQueue = finishedWork.updateQueue;
- if (_updateQueue !== null) {
- var _instance = null;
- if (finishedWork.child !== null) {
- switch (finishedWork.child.tag) {
- case HostComponent:
- _instance = getPublicInstance(finishedWork.child.stateNode);
- break;
- case ClassComponent:
- _instance = finishedWork.child.stateNode;
- break;
- }
- }
- commitUpdateQueue(finishedWork, _updateQueue, _instance);
- }
- break;
- }
- case HostComponent:
- {
- var _instance2 = finishedWork.stateNode; // Renderers may schedule work to be done after host components are mounted
- // (eg DOM renderer may schedule auto-focus for inputs and form controls).
- // These effects should only be committed when components are first mounted,
- // aka when there is no current/alternate.
- if (current === null && finishedWork.flags & Update) {
- var type = finishedWork.type;
- var props = finishedWork.memoizedProps;
- commitMount(_instance2, type, props);
- }
- break;
- }
- case HostText:
- {
- // We have no life-cycles associated with text.
- break;
- }
- case HostPortal:
- {
- // We have no life-cycles associated with portals.
- break;
- }
- case Profiler:
- {
- {
- var _finishedWork$memoize2 = finishedWork.memoizedProps,
- onCommit = _finishedWork$memoize2.onCommit,
- onRender = _finishedWork$memoize2.onRender;
- var effectDuration = finishedWork.stateNode.effectDuration;
- var commitTime = getCommitTime();
- var phase = current === null ? 'mount' : 'update';
- {
- if (isCurrentUpdateNested()) {
- phase = 'nested-update';
- }
- }
- if (typeof onRender === 'function') {
- onRender(finishedWork.memoizedProps.id, phase, finishedWork.actualDuration, finishedWork.treeBaseDuration, finishedWork.actualStartTime, commitTime);
- }
- {
- if (typeof onCommit === 'function') {
- onCommit(finishedWork.memoizedProps.id, phase, effectDuration, commitTime);
- } // Schedule a passive effect for this Profiler to call onPostCommit hooks.
- // This effect should be scheduled even if there is no onPostCommit callback for this Profiler,
- // because the effect is also where times bubble to parent Profilers.
- enqueuePendingPassiveProfilerEffect(finishedWork); // Propagate layout effect durations to the next nearest Profiler ancestor.
- // Do not reset these values until the next render so DevTools has a chance to read them first.
- var parentFiber = finishedWork.return;
- outer: while (parentFiber !== null) {
- switch (parentFiber.tag) {
- case HostRoot:
- var root = parentFiber.stateNode;
- root.effectDuration += effectDuration;
- break outer;
- case Profiler:
- var parentStateNode = parentFiber.stateNode;
- parentStateNode.effectDuration += effectDuration;
- break outer;
- }
- parentFiber = parentFiber.return;
- }
- }
- }
- break;
- }
- case SuspenseComponent:
- {
- commitSuspenseHydrationCallbacks(finishedRoot, finishedWork);
- break;
- }
- case SuspenseListComponent:
- case IncompleteClassComponent:
- case ScopeComponent:
- case OffscreenComponent:
- case LegacyHiddenComponent:
- case TracingMarkerComponent:
- {
- break;
- }
- default:
- throw new Error('This unit of work tag should not have side-effects. This error is ' + 'likely caused by a bug in React. Please file an issue.');
- }
- }
- if (!offscreenSubtreeWasHidden) {
- {
- if (finishedWork.flags & Ref) {
- commitAttachRef(finishedWork);
- }
- }
- }
- }
- function reappearLayoutEffectsOnFiber(node) {
- // Turn on layout effects in a tree that previously disappeared.
- // TODO (Offscreen) Check: flags & LayoutStatic
- switch (node.tag) {
- case FunctionComponent:
- case ForwardRef:
- case SimpleMemoComponent:
- {
- if (node.mode & ProfileMode) {
- try {
- startLayoutEffectTimer();
- safelyCallCommitHookLayoutEffectListMount(node, node.return);
- } finally {
- recordLayoutEffectDuration(node);
- }
- } else {
- safelyCallCommitHookLayoutEffectListMount(node, node.return);
- }
- break;
- }
- case ClassComponent:
- {
- var instance = node.stateNode;
- if (typeof instance.componentDidMount === 'function') {
- safelyCallComponentDidMount(node, node.return, instance);
- }
- safelyAttachRef(node, node.return);
- break;
- }
- case HostComponent:
- {
- safelyAttachRef(node, node.return);
- break;
- }
- }
- }
- function hideOrUnhideAllChildren(finishedWork, isHidden) {
- // Only hide or unhide the top-most host nodes.
- var hostSubtreeRoot = null;
- {
- // We only have the top Fiber that was inserted but we need to recurse down its
- // children to find all the terminal nodes.
- var node = finishedWork;
- while (true) {
- if (node.tag === HostComponent) {
- if (hostSubtreeRoot === null) {
- hostSubtreeRoot = node;
- try {
- var instance = node.stateNode;
- if (isHidden) {
- hideInstance(instance);
- } else {
- unhideInstance(node.stateNode, node.memoizedProps);
- }
- } catch (error) {
- captureCommitPhaseError(finishedWork, finishedWork.return, error);
- }
- }
- } else if (node.tag === HostText) {
- if (hostSubtreeRoot === null) {
- try {
- var _instance3 = node.stateNode;
- if (isHidden) {
- hideTextInstance(_instance3);
- } else {
- unhideTextInstance(_instance3, node.memoizedProps);
- }
- } catch (error) {
- captureCommitPhaseError(finishedWork, finishedWork.return, error);
- }
- }
- } else if ((node.tag === OffscreenComponent || node.tag === LegacyHiddenComponent) && node.memoizedState !== null && node !== finishedWork); else if (node.child !== null) {
- node.child.return = node;
- node = node.child;
- continue;
- }
- if (node === finishedWork) {
- return;
- }
- while (node.sibling === null) {
- if (node.return === null || node.return === finishedWork) {
- return;
- }
- if (hostSubtreeRoot === node) {
- hostSubtreeRoot = null;
- }
- node = node.return;
- }
- if (hostSubtreeRoot === node) {
- hostSubtreeRoot = null;
- }
- node.sibling.return = node.return;
- node = node.sibling;
- }
- }
- }
- function commitAttachRef(finishedWork) {
- var ref = finishedWork.ref;
- if (ref !== null) {
- var instance = finishedWork.stateNode;
- var instanceToUse;
- switch (finishedWork.tag) {
- case HostComponent:
- instanceToUse = getPublicInstance(instance);
- break;
- default:
- instanceToUse = instance;
- } // Moved outside to ensure DCE works with this flag
- if (typeof ref === 'function') {
- var retVal;
- if (finishedWork.mode & ProfileMode) {
- try {
- startLayoutEffectTimer();
- retVal = ref(instanceToUse);
- } finally {
- recordLayoutEffectDuration(finishedWork);
- }
- } else {
- retVal = ref(instanceToUse);
- }
- {
- if (typeof retVal === 'function') {
- error('Unexpected return value from a callback ref in %s. ' + 'A callback ref should not return a function.', getComponentNameFromFiber(finishedWork));
- }
- }
- } else {
- {
- if (!ref.hasOwnProperty('current')) {
- error('Unexpected ref object provided for %s. ' + 'Use either a ref-setter function or React.createRef().', getComponentNameFromFiber(finishedWork));
- }
- }
- ref.current = instanceToUse;
- }
- }
- }
- function detachFiberMutation(fiber) {
- // Cut off the return pointer to disconnect it from the tree.
- // This enables us to detect and warn against state updates on an unmounted component.
- // It also prevents events from bubbling from within disconnected components.
- //
- // Ideally, we should also clear the child pointer of the parent alternate to let this
- // get GC:ed but we don't know which for sure which parent is the current
- // one so we'll settle for GC:ing the subtree of this child.
- // This child itself will be GC:ed when the parent updates the next time.
- //
- // Note that we can't clear child or sibling pointers yet.
- // They're needed for passive effects and for findDOMNode.
- // We defer those fields, and all other cleanup, to the passive phase (see detachFiberAfterEffects).
- //
- // Don't reset the alternate yet, either. We need that so we can detach the
- // alternate's fields in the passive phase. Clearing the return pointer is
- // sufficient for findDOMNode semantics.
- var alternate = fiber.alternate;
- if (alternate !== null) {
- alternate.return = null;
- }
- fiber.return = null;
- }
- function detachFiberAfterEffects(fiber) {
- var alternate = fiber.alternate;
- if (alternate !== null) {
- fiber.alternate = null;
- detachFiberAfterEffects(alternate);
- } // Note: Defensively using negation instead of < in case
- // `deletedTreeCleanUpLevel` is undefined.
- {
- // Clear cyclical Fiber fields. This level alone is designed to roughly
- // approximate the planned Fiber refactor. In that world, `setState` will be
- // bound to a special "instance" object instead of a Fiber. The Instance
- // object will not have any of these fields. It will only be connected to
- // the fiber tree via a single link at the root. So if this level alone is
- // sufficient to fix memory issues, that bodes well for our plans.
- fiber.child = null;
- fiber.deletions = null;
- fiber.sibling = null; // The `stateNode` is cyclical because on host nodes it points to the host
- // tree, which has its own pointers to children, parents, and siblings.
- // The other host nodes also point back to fibers, so we should detach that
- // one, too.
- if (fiber.tag === HostComponent) {
- var hostInstance = fiber.stateNode;
- if (hostInstance !== null) {
- detachDeletedInstance(hostInstance);
- }
- }
- fiber.stateNode = null; // I'm intentionally not clearing the `return` field in this level. We
- // already disconnect the `return` pointer at the root of the deleted
- // subtree (in `detachFiberMutation`). Besides, `return` by itself is not
- // cyclical — it's only cyclical when combined with `child`, `sibling`, and
- // `alternate`. But we'll clear it in the next level anyway, just in case.
- {
- fiber._debugOwner = null;
- }
- {
- // Theoretically, nothing in here should be necessary, because we already
- // disconnected the fiber from the tree. So even if something leaks this
- // particular fiber, it won't leak anything else
- //
- // The purpose of this branch is to be super aggressive so we can measure
- // if there's any difference in memory impact. If there is, that could
- // indicate a React leak we don't know about.
- fiber.return = null;
- fiber.dependencies = null;
- fiber.memoizedProps = null;
- fiber.memoizedState = null;
- fiber.pendingProps = null;
- fiber.stateNode = null; // TODO: Move to `commitPassiveUnmountInsideDeletedTreeOnFiber` instead.
- fiber.updateQueue = null;
- }
- }
- }
- function getHostParentFiber(fiber) {
- var parent = fiber.return;
- while (parent !== null) {
- if (isHostParent(parent)) {
- return parent;
- }
- parent = parent.return;
- }
- throw new Error('Expected to find a host parent. This error is likely caused by a bug ' + 'in React. Please file an issue.');
- }
- function isHostParent(fiber) {
- return fiber.tag === HostComponent || fiber.tag === HostRoot || fiber.tag === HostPortal;
- }
- function getHostSibling(fiber) {
- // We're going to search forward into the tree until we find a sibling host
- // node. Unfortunately, if multiple insertions are done in a row we have to
- // search past them. This leads to exponential search for the next sibling.
- // TODO: Find a more efficient way to do this.
- var node = fiber;
- siblings: while (true) {
- // If we didn't find anything, let's try the next sibling.
- while (node.sibling === null) {
- if (node.return === null || isHostParent(node.return)) {
- // If we pop out of the root or hit the parent the fiber we are the
- // last sibling.
- return null;
- }
- node = node.return;
- }
- node.sibling.return = node.return;
- node = node.sibling;
- while (node.tag !== HostComponent && node.tag !== HostText && node.tag !== DehydratedFragment) {
- // If it is not host node and, we might have a host node inside it.
- // Try to search down until we find one.
- if (node.flags & Placement) {
- // If we don't have a child, try the siblings instead.
- continue siblings;
- } // If we don't have a child, try the siblings instead.
- // We also skip portals because they are not part of this host tree.
- if (node.child === null || node.tag === HostPortal) {
- continue siblings;
- } else {
- node.child.return = node;
- node = node.child;
- }
- } // Check if this host node is stable or about to be placed.
- if (!(node.flags & Placement)) {
- // Found it!
- return node.stateNode;
- }
- }
- }
- function commitPlacement(finishedWork) {
- var parentFiber = getHostParentFiber(finishedWork); // Note: these two variables *must* always be updated together.
- switch (parentFiber.tag) {
- case HostComponent:
- {
- var parent = parentFiber.stateNode;
- if (parentFiber.flags & ContentReset) {
- // Reset the text content of the parent before doing any insertions
- resetTextContent(parent); // Clear ContentReset from the effect tag
- parentFiber.flags &= ~ContentReset;
- }
- var before = getHostSibling(finishedWork); // We only have the top Fiber that was inserted but we need to recurse down its
- // children to find all the terminal nodes.
- insertOrAppendPlacementNode(finishedWork, before, parent);
- break;
- }
- case HostRoot:
- case HostPortal:
- {
- var _parent = parentFiber.stateNode.containerInfo;
- var _before = getHostSibling(finishedWork);
- insertOrAppendPlacementNodeIntoContainer(finishedWork, _before, _parent);
- break;
- }
- // eslint-disable-next-line-no-fallthrough
- default:
- throw new Error('Invalid host parent fiber. This error is likely caused by a bug ' + 'in React. Please file an issue.');
- }
- }
- function insertOrAppendPlacementNodeIntoContainer(node, before, parent) {
- var tag = node.tag;
- var isHost = tag === HostComponent || tag === HostText;
- if (isHost) {
- var stateNode = node.stateNode;
- if (before) {
- insertInContainerBefore(parent, stateNode, before);
- } else {
- appendChildToContainer(parent, stateNode);
- }
- } else if (tag === HostPortal); else {
- var child = node.child;
- if (child !== null) {
- insertOrAppendPlacementNodeIntoContainer(child, before, parent);
- var sibling = child.sibling;
- while (sibling !== null) {
- insertOrAppendPlacementNodeIntoContainer(sibling, before, parent);
- sibling = sibling.sibling;
- }
- }
- }
- }
- function insertOrAppendPlacementNode(node, before, parent) {
- var tag = node.tag;
- var isHost = tag === HostComponent || tag === HostText;
- if (isHost) {
- var stateNode = node.stateNode;
- if (before) {
- insertBefore(parent, stateNode, before);
- } else {
- appendChild(parent, stateNode);
- }
- } else if (tag === HostPortal); else {
- var child = node.child;
- if (child !== null) {
- insertOrAppendPlacementNode(child, before, parent);
- var sibling = child.sibling;
- while (sibling !== null) {
- insertOrAppendPlacementNode(sibling, before, parent);
- sibling = sibling.sibling;
- }
- }
- }
- } // These are tracked on the stack as we recursively traverse a
- // deleted subtree.
- // TODO: Update these during the whole mutation phase, not just during
- // a deletion.
- var hostParent = null;
- var hostParentIsContainer = false;
- function commitDeletionEffects(root, returnFiber, deletedFiber) {
- {
- // We only have the top Fiber that was deleted but we need to recurse down its
- // children to find all the terminal nodes.
- // Recursively delete all host nodes from the parent, detach refs, clean
- // up mounted layout effects, and call componentWillUnmount.
- // We only need to remove the topmost host child in each branch. But then we
- // still need to keep traversing to unmount effects, refs, and cWU. TODO: We
- // could split this into two separate traversals functions, where the second
- // one doesn't include any removeChild logic. This is maybe the same
- // function as "disappearLayoutEffects" (or whatever that turns into after
- // the layout phase is refactored to use recursion).
- // Before starting, find the nearest host parent on the stack so we know
- // which instance/container to remove the children from.
- // TODO: Instead of searching up the fiber return path on every deletion, we
- // can track the nearest host component on the JS stack as we traverse the
- // tree during the commit phase. This would make insertions faster, too.
- var parent = returnFiber;
- findParent: while (parent !== null) {
- switch (parent.tag) {
- case HostComponent:
- {
- hostParent = parent.stateNode;
- hostParentIsContainer = false;
- break findParent;
- }
- case HostRoot:
- {
- hostParent = parent.stateNode.containerInfo;
- hostParentIsContainer = true;
- break findParent;
- }
- case HostPortal:
- {
- hostParent = parent.stateNode.containerInfo;
- hostParentIsContainer = true;
- break findParent;
- }
- }
- parent = parent.return;
- }
- if (hostParent === null) {
- throw new Error('Expected to find a host parent. This error is likely caused by ' + 'a bug in React. Please file an issue.');
- }
- commitDeletionEffectsOnFiber(root, returnFiber, deletedFiber);
- hostParent = null;
- hostParentIsContainer = false;
- }
- detachFiberMutation(deletedFiber);
- }
- function recursivelyTraverseDeletionEffects(finishedRoot, nearestMountedAncestor, parent) {
- // TODO: Use a static flag to skip trees that don't have unmount effects
- var child = parent.child;
- while (child !== null) {
- commitDeletionEffectsOnFiber(finishedRoot, nearestMountedAncestor, child);
- child = child.sibling;
- }
- }
- function commitDeletionEffectsOnFiber(finishedRoot, nearestMountedAncestor, deletedFiber) {
- onCommitUnmount(deletedFiber); // The cases in this outer switch modify the stack before they traverse
- // into their subtree. There are simpler cases in the inner switch
- // that don't modify the stack.
- switch (deletedFiber.tag) {
- case HostComponent:
- {
- if (!offscreenSubtreeWasHidden) {
- safelyDetachRef(deletedFiber, nearestMountedAncestor);
- } // Intentional fallthrough to next branch
- }
- // eslint-disable-next-line-no-fallthrough
- case HostText:
- {
- // We only need to remove the nearest host child. Set the host parent
- // to `null` on the stack to indicate that nested children don't
- // need to be removed.
- {
- var prevHostParent = hostParent;
- var prevHostParentIsContainer = hostParentIsContainer;
- hostParent = null;
- recursivelyTraverseDeletionEffects(finishedRoot, nearestMountedAncestor, deletedFiber);
- hostParent = prevHostParent;
- hostParentIsContainer = prevHostParentIsContainer;
- if (hostParent !== null) {
- // Now that all the child effects have unmounted, we can remove the
- // node from the tree.
- if (hostParentIsContainer) {
- removeChildFromContainer(hostParent, deletedFiber.stateNode);
- } else {
- removeChild(hostParent, deletedFiber.stateNode);
- }
- }
- }
- return;
- }
- case DehydratedFragment:
- {
- // Delete the dehydrated suspense boundary and all of its content.
- {
- if (hostParent !== null) {
- if (hostParentIsContainer) {
- clearSuspenseBoundaryFromContainer(hostParent, deletedFiber.stateNode);
- } else {
- clearSuspenseBoundary(hostParent, deletedFiber.stateNode);
- }
- }
- }
- return;
- }
- case HostPortal:
- {
- {
- // When we go into a portal, it becomes the parent to remove from.
- var _prevHostParent = hostParent;
- var _prevHostParentIsContainer = hostParentIsContainer;
- hostParent = deletedFiber.stateNode.containerInfo;
- hostParentIsContainer = true;
- recursivelyTraverseDeletionEffects(finishedRoot, nearestMountedAncestor, deletedFiber);
- hostParent = _prevHostParent;
- hostParentIsContainer = _prevHostParentIsContainer;
- }
- return;
- }
- case FunctionComponent:
- case ForwardRef:
- case MemoComponent:
- case SimpleMemoComponent:
- {
- if (!offscreenSubtreeWasHidden) {
- var updateQueue = deletedFiber.updateQueue;
- if (updateQueue !== null) {
- var lastEffect = updateQueue.lastEffect;
- if (lastEffect !== null) {
- var firstEffect = lastEffect.next;
- var effect = firstEffect;
- do {
- var _effect = effect,
- destroy = _effect.destroy,
- tag = _effect.tag;
- if (destroy !== undefined) {
- if ((tag & Insertion) !== NoFlags$1) {
- safelyCallDestroy(deletedFiber, nearestMountedAncestor, destroy);
- } else if ((tag & Layout) !== NoFlags$1) {
- {
- markComponentLayoutEffectUnmountStarted(deletedFiber);
- }
- if (deletedFiber.mode & ProfileMode) {
- startLayoutEffectTimer();
- safelyCallDestroy(deletedFiber, nearestMountedAncestor, destroy);
- recordLayoutEffectDuration(deletedFiber);
- } else {
- safelyCallDestroy(deletedFiber, nearestMountedAncestor, destroy);
- }
- {
- markComponentLayoutEffectUnmountStopped();
- }
- }
- }
- effect = effect.next;
- } while (effect !== firstEffect);
- }
- }
- }
- recursivelyTraverseDeletionEffects(finishedRoot, nearestMountedAncestor, deletedFiber);
- return;
- }
- case ClassComponent:
- {
- if (!offscreenSubtreeWasHidden) {
- safelyDetachRef(deletedFiber, nearestMountedAncestor);
- var instance = deletedFiber.stateNode;
- if (typeof instance.componentWillUnmount === 'function') {
- safelyCallComponentWillUnmount(deletedFiber, nearestMountedAncestor, instance);
- }
- }
- recursivelyTraverseDeletionEffects(finishedRoot, nearestMountedAncestor, deletedFiber);
- return;
- }
- case ScopeComponent:
- {
- recursivelyTraverseDeletionEffects(finishedRoot, nearestMountedAncestor, deletedFiber);
- return;
- }
- case OffscreenComponent:
- {
- if ( // TODO: Remove this dead flag
- deletedFiber.mode & ConcurrentMode) {
- // If this offscreen component is hidden, we already unmounted it. Before
- // deleting the children, track that it's already unmounted so that we
- // don't attempt to unmount the effects again.
- // TODO: If the tree is hidden, in most cases we should be able to skip
- // over the nested children entirely. An exception is we haven't yet found
- // the topmost host node to delete, which we already track on the stack.
- // But the other case is portals, which need to be detached no matter how
- // deeply they are nested. We should use a subtree flag to track whether a
- // subtree includes a nested portal.
- var prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden;
- offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden || deletedFiber.memoizedState !== null;
- recursivelyTraverseDeletionEffects(finishedRoot, nearestMountedAncestor, deletedFiber);
- offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden;
- } else {
- recursivelyTraverseDeletionEffects(finishedRoot, nearestMountedAncestor, deletedFiber);
- }
- break;
- }
- default:
- {
- recursivelyTraverseDeletionEffects(finishedRoot, nearestMountedAncestor, deletedFiber);
- return;
- }
- }
- }
- function commitSuspenseCallback(finishedWork) {
- // TODO: Move this to passive phase
- var newState = finishedWork.memoizedState;
- }
- function commitSuspenseHydrationCallbacks(finishedRoot, finishedWork) {
- var newState = finishedWork.memoizedState;
- if (newState === null) {
- var current = finishedWork.alternate;
- if (current !== null) {
- var prevState = current.memoizedState;
- if (prevState !== null) {
- var suspenseInstance = prevState.dehydrated;
- if (suspenseInstance !== null) {
- commitHydratedSuspenseInstance(suspenseInstance);
- }
- }
- }
- }
- }
- function attachSuspenseRetryListeners(finishedWork) {
- // If this boundary just timed out, then it will have a set of wakeables.
- // For each wakeable, attach a listener so that when it resolves, React
- // attempts to re-render the boundary in the primary (pre-timeout) state.
- var wakeables = finishedWork.updateQueue;
- if (wakeables !== null) {
- finishedWork.updateQueue = null;
- var retryCache = finishedWork.stateNode;
- if (retryCache === null) {
- retryCache = finishedWork.stateNode = new PossiblyWeakSet();
- }
- wakeables.forEach(function (wakeable) {
- // Memoize using the boundary fiber to prevent redundant listeners.
- var retry = resolveRetryWakeable.bind(null, finishedWork, wakeable);
- if (!retryCache.has(wakeable)) {
- retryCache.add(wakeable);
- {
- if (isDevToolsPresent) {
- if (inProgressLanes !== null && inProgressRoot !== null) {
- // If we have pending work still, associate the original updaters with it.
- restorePendingUpdaters(inProgressRoot, inProgressLanes);
- } else {
- throw Error('Expected finished root and lanes to be set. This is a bug in React.');
- }
- }
- }
- wakeable.then(retry, retry);
- }
- });
- }
- } // This function detects when a Suspense boundary goes from visible to hidden.
- function commitMutationEffects(root, finishedWork, committedLanes) {
- inProgressLanes = committedLanes;
- inProgressRoot = root;
- setCurrentFiber(finishedWork);
- commitMutationEffectsOnFiber(finishedWork, root);
- setCurrentFiber(finishedWork);
- inProgressLanes = null;
- inProgressRoot = null;
- }
- function recursivelyTraverseMutationEffects(root, parentFiber, lanes) {
- // Deletions effects can be scheduled on any fiber type. They need to happen
- // before the children effects hae fired.
- var deletions = parentFiber.deletions;
- if (deletions !== null) {
- for (var i = 0; i < deletions.length; i++) {
- var childToDelete = deletions[i];
- try {
- commitDeletionEffects(root, parentFiber, childToDelete);
- } catch (error) {
- captureCommitPhaseError(childToDelete, parentFiber, error);
- }
- }
- }
- var prevDebugFiber = getCurrentFiber();
- if (parentFiber.subtreeFlags & MutationMask) {
- var child = parentFiber.child;
- while (child !== null) {
- setCurrentFiber(child);
- commitMutationEffectsOnFiber(child, root);
- child = child.sibling;
- }
- }
- setCurrentFiber(prevDebugFiber);
- }
- function commitMutationEffectsOnFiber(finishedWork, root, lanes) {
- var current = finishedWork.alternate;
- var flags = finishedWork.flags; // The effect flag should be checked *after* we refine the type of fiber,
- // because the fiber tag is more specific. An exception is any flag related
- // to reconcilation, because those can be set on all fiber types.
- switch (finishedWork.tag) {
- case FunctionComponent:
- case ForwardRef:
- case MemoComponent:
- case SimpleMemoComponent:
- {
- recursivelyTraverseMutationEffects(root, finishedWork);
- commitReconciliationEffects(finishedWork);
- if (flags & Update) {
- try {
- commitHookEffectListUnmount(Insertion | HasEffect, finishedWork, finishedWork.return);
- commitHookEffectListMount(Insertion | HasEffect, finishedWork);
- } catch (error) {
- captureCommitPhaseError(finishedWork, finishedWork.return, error);
- } // Layout effects are destroyed during the mutation phase so that all
- // destroy functions for all fibers are called before any create functions.
- // This prevents sibling component effects from interfering with each other,
- // e.g. a destroy function in one component should never override a ref set
- // by a create function in another component during the same commit.
- if (finishedWork.mode & ProfileMode) {
- try {
- startLayoutEffectTimer();
- commitHookEffectListUnmount(Layout | HasEffect, finishedWork, finishedWork.return);
- } catch (error) {
- captureCommitPhaseError(finishedWork, finishedWork.return, error);
- }
- recordLayoutEffectDuration(finishedWork);
- } else {
- try {
- commitHookEffectListUnmount(Layout | HasEffect, finishedWork, finishedWork.return);
- } catch (error) {
- captureCommitPhaseError(finishedWork, finishedWork.return, error);
- }
- }
- }
- return;
- }
- case ClassComponent:
- {
- recursivelyTraverseMutationEffects(root, finishedWork);
- commitReconciliationEffects(finishedWork);
- if (flags & Ref) {
- if (current !== null) {
- safelyDetachRef(current, current.return);
- }
- }
- return;
- }
- case HostComponent:
- {
- recursivelyTraverseMutationEffects(root, finishedWork);
- commitReconciliationEffects(finishedWork);
- if (flags & Ref) {
- if (current !== null) {
- safelyDetachRef(current, current.return);
- }
- }
- {
- // TODO: ContentReset gets cleared by the children during the commit
- // phase. This is a refactor hazard because it means we must read
- // flags the flags after `commitReconciliationEffects` has already run;
- // the order matters. We should refactor so that ContentReset does not
- // rely on mutating the flag during commit. Like by setting a flag
- // during the render phase instead.
- if (finishedWork.flags & ContentReset) {
- var instance = finishedWork.stateNode;
- try {
- resetTextContent(instance);
- } catch (error) {
- captureCommitPhaseError(finishedWork, finishedWork.return, error);
- }
- }
- if (flags & Update) {
- var _instance4 = finishedWork.stateNode;
- if (_instance4 != null) {
- // Commit the work prepared earlier.
- var newProps = finishedWork.memoizedProps; // For hydration we reuse the update path but we treat the oldProps
- // as the newProps. The updatePayload will contain the real change in
- // this case.
- var oldProps = current !== null ? current.memoizedProps : newProps;
- var type = finishedWork.type; // TODO: Type the updateQueue to be specific to host components.
- var updatePayload = finishedWork.updateQueue;
- finishedWork.updateQueue = null;
- if (updatePayload !== null) {
- try {
- commitUpdate(_instance4, updatePayload, type, oldProps, newProps, finishedWork);
- } catch (error) {
- captureCommitPhaseError(finishedWork, finishedWork.return, error);
- }
- }
- }
- }
- }
- return;
- }
- case HostText:
- {
- recursivelyTraverseMutationEffects(root, finishedWork);
- commitReconciliationEffects(finishedWork);
- if (flags & Update) {
- {
- if (finishedWork.stateNode === null) {
- throw new Error('This should have a text node initialized. This error is likely ' + 'caused by a bug in React. Please file an issue.');
- }
- var textInstance = finishedWork.stateNode;
- var newText = finishedWork.memoizedProps; // For hydration we reuse the update path but we treat the oldProps
- // as the newProps. The updatePayload will contain the real change in
- // this case.
- var oldText = current !== null ? current.memoizedProps : newText;
- try {
- commitTextUpdate(textInstance, oldText, newText);
- } catch (error) {
- captureCommitPhaseError(finishedWork, finishedWork.return, error);
- }
- }
- }
- return;
- }
- case HostRoot:
- {
- recursivelyTraverseMutationEffects(root, finishedWork);
- commitReconciliationEffects(finishedWork);
- if (flags & Update) {
- {
- if (current !== null) {
- var prevRootState = current.memoizedState;
- if (prevRootState.isDehydrated) {
- try {
- commitHydratedContainer(root.containerInfo);
- } catch (error) {
- captureCommitPhaseError(finishedWork, finishedWork.return, error);
- }
- }
- }
- }
- }
- return;
- }
- case HostPortal:
- {
- recursivelyTraverseMutationEffects(root, finishedWork);
- commitReconciliationEffects(finishedWork);
- return;
- }
- case SuspenseComponent:
- {
- recursivelyTraverseMutationEffects(root, finishedWork);
- commitReconciliationEffects(finishedWork);
- var offscreenFiber = finishedWork.child;
- if (offscreenFiber.flags & Visibility) {
- var offscreenInstance = offscreenFiber.stateNode;
- var newState = offscreenFiber.memoizedState;
- var isHidden = newState !== null; // Track the current state on the Offscreen instance so we can
- // read it during an event
- offscreenInstance.isHidden = isHidden;
- if (isHidden) {
- var wasHidden = offscreenFiber.alternate !== null && offscreenFiber.alternate.memoizedState !== null;
- if (!wasHidden) {
- // TODO: Move to passive phase
- markCommitTimeOfFallback();
- }
- }
- }
- if (flags & Update) {
- try {
- commitSuspenseCallback(finishedWork);
- } catch (error) {
- captureCommitPhaseError(finishedWork, finishedWork.return, error);
- }
- attachSuspenseRetryListeners(finishedWork);
- }
- return;
- }
- case OffscreenComponent:
- {
- var _wasHidden = current !== null && current.memoizedState !== null;
- if ( // TODO: Remove this dead flag
- finishedWork.mode & ConcurrentMode) {
- // Before committing the children, track on the stack whether this
- // offscreen subtree was already hidden, so that we don't unmount the
- // effects again.
- var prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden;
- offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden || _wasHidden;
- recursivelyTraverseMutationEffects(root, finishedWork);
- offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden;
- } else {
- recursivelyTraverseMutationEffects(root, finishedWork);
- }
- commitReconciliationEffects(finishedWork);
- if (flags & Visibility) {
- var _offscreenInstance = finishedWork.stateNode;
- var _newState = finishedWork.memoizedState;
- var _isHidden = _newState !== null;
- var offscreenBoundary = finishedWork; // Track the current state on the Offscreen instance so we can
- // read it during an event
- _offscreenInstance.isHidden = _isHidden;
- {
- if (_isHidden) {
- if (!_wasHidden) {
- if ((offscreenBoundary.mode & ConcurrentMode) !== NoMode) {
- nextEffect = offscreenBoundary;
- var offscreenChild = offscreenBoundary.child;
- while (offscreenChild !== null) {
- nextEffect = offscreenChild;
- disappearLayoutEffects_begin(offscreenChild);
- offscreenChild = offscreenChild.sibling;
- }
- }
- }
- }
- }
- {
- // TODO: This needs to run whenever there's an insertion or update
- // inside a hidden Offscreen tree.
- hideOrUnhideAllChildren(offscreenBoundary, _isHidden);
- }
- }
- return;
- }
- case SuspenseListComponent:
- {
- recursivelyTraverseMutationEffects(root, finishedWork);
- commitReconciliationEffects(finishedWork);
- if (flags & Update) {
- attachSuspenseRetryListeners(finishedWork);
- }
- return;
- }
- case ScopeComponent:
- {
- return;
- }
- default:
- {
- recursivelyTraverseMutationEffects(root, finishedWork);
- commitReconciliationEffects(finishedWork);
- return;
- }
- }
- }
- function commitReconciliationEffects(finishedWork) {
- // Placement effects (insertions, reorders) can be scheduled on any fiber
- // type. They needs to happen after the children effects have fired, but
- // before the effects on this fiber have fired.
- var flags = finishedWork.flags;
- if (flags & Placement) {
- try {
- commitPlacement(finishedWork);
- } catch (error) {
- captureCommitPhaseError(finishedWork, finishedWork.return, error);
- } // Clear the "placement" from effect tag so that we know that this is
- // inserted, before any life-cycles like componentDidMount gets called.
- // TODO: findDOMNode doesn't rely on this any more but isMounted does
- // and isMounted is deprecated anyway so we should be able to kill this.
- finishedWork.flags &= ~Placement;
- }
- if (flags & Hydrating) {
- finishedWork.flags &= ~Hydrating;
- }
- }
- function commitLayoutEffects(finishedWork, root, committedLanes) {
- inProgressLanes = committedLanes;
- inProgressRoot = root;
- nextEffect = finishedWork;
- commitLayoutEffects_begin(finishedWork, root, committedLanes);
- inProgressLanes = null;
- inProgressRoot = null;
- }
- function commitLayoutEffects_begin(subtreeRoot, root, committedLanes) {
- // Suspense layout effects semantics don't change for legacy roots.
- var isModernRoot = (subtreeRoot.mode & ConcurrentMode) !== NoMode;
- while (nextEffect !== null) {
- var fiber = nextEffect;
- var firstChild = fiber.child;
- if (fiber.tag === OffscreenComponent && isModernRoot) {
- // Keep track of the current Offscreen stack's state.
- var isHidden = fiber.memoizedState !== null;
- var newOffscreenSubtreeIsHidden = isHidden || offscreenSubtreeIsHidden;
- if (newOffscreenSubtreeIsHidden) {
- // The Offscreen tree is hidden. Skip over its layout effects.
- commitLayoutMountEffects_complete(subtreeRoot, root, committedLanes);
- continue;
- } else {
- // TODO (Offscreen) Also check: subtreeFlags & LayoutMask
- var current = fiber.alternate;
- var wasHidden = current !== null && current.memoizedState !== null;
- var newOffscreenSubtreeWasHidden = wasHidden || offscreenSubtreeWasHidden;
- var prevOffscreenSubtreeIsHidden = offscreenSubtreeIsHidden;
- var prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden; // Traverse the Offscreen subtree with the current Offscreen as the root.
- offscreenSubtreeIsHidden = newOffscreenSubtreeIsHidden;
- offscreenSubtreeWasHidden = newOffscreenSubtreeWasHidden;
- if (offscreenSubtreeWasHidden && !prevOffscreenSubtreeWasHidden) {
- // This is the root of a reappearing boundary. Turn its layout effects
- // back on.
- nextEffect = fiber;
- reappearLayoutEffects_begin(fiber);
- }
- var child = firstChild;
- while (child !== null) {
- nextEffect = child;
- commitLayoutEffects_begin(child, // New root; bubble back up to here and stop.
- root, committedLanes);
- child = child.sibling;
- } // Restore Offscreen state and resume in our-progress traversal.
- nextEffect = fiber;
- offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden;
- offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden;
- commitLayoutMountEffects_complete(subtreeRoot, root, committedLanes);
- continue;
- }
- }
- if ((fiber.subtreeFlags & LayoutMask) !== NoFlags && firstChild !== null) {
- firstChild.return = fiber;
- nextEffect = firstChild;
- } else {
- commitLayoutMountEffects_complete(subtreeRoot, root, committedLanes);
- }
- }
- }
- function commitLayoutMountEffects_complete(subtreeRoot, root, committedLanes) {
- while (nextEffect !== null) {
- var fiber = nextEffect;
- if ((fiber.flags & LayoutMask) !== NoFlags) {
- var current = fiber.alternate;
- setCurrentFiber(fiber);
- try {
- commitLayoutEffectOnFiber(root, current, fiber, committedLanes);
- } catch (error) {
- captureCommitPhaseError(fiber, fiber.return, error);
- }
- resetCurrentFiber();
- }
- if (fiber === subtreeRoot) {
- nextEffect = null;
- return;
- }
- var sibling = fiber.sibling;
- if (sibling !== null) {
- sibling.return = fiber.return;
- nextEffect = sibling;
- return;
- }
- nextEffect = fiber.return;
- }
- }
- function disappearLayoutEffects_begin(subtreeRoot) {
- while (nextEffect !== null) {
- var fiber = nextEffect;
- var firstChild = fiber.child; // TODO (Offscreen) Check: flags & (RefStatic | LayoutStatic)
- switch (fiber.tag) {
- case FunctionComponent:
- case ForwardRef:
- case MemoComponent:
- case SimpleMemoComponent:
- {
- if (fiber.mode & ProfileMode) {
- try {
- startLayoutEffectTimer();
- commitHookEffectListUnmount(Layout, fiber, fiber.return);
- } finally {
- recordLayoutEffectDuration(fiber);
- }
- } else {
- commitHookEffectListUnmount(Layout, fiber, fiber.return);
- }
- break;
- }
- case ClassComponent:
- {
- // TODO (Offscreen) Check: flags & RefStatic
- safelyDetachRef(fiber, fiber.return);
- var instance = fiber.stateNode;
- if (typeof instance.componentWillUnmount === 'function') {
- safelyCallComponentWillUnmount(fiber, fiber.return, instance);
- }
- break;
- }
- case HostComponent:
- {
- safelyDetachRef(fiber, fiber.return);
- break;
- }
- case OffscreenComponent:
- {
- // Check if this is a
- var isHidden = fiber.memoizedState !== null;
- if (isHidden) {
- // Nested Offscreen tree is already hidden. Don't disappear
- // its effects.
- disappearLayoutEffects_complete(subtreeRoot);
- continue;
- }
- break;
- }
- } // TODO (Offscreen) Check: subtreeFlags & LayoutStatic
- if (firstChild !== null) {
- firstChild.return = fiber;
- nextEffect = firstChild;
- } else {
- disappearLayoutEffects_complete(subtreeRoot);
- }
- }
- }
- function disappearLayoutEffects_complete(subtreeRoot) {
- while (nextEffect !== null) {
- var fiber = nextEffect;
- if (fiber === subtreeRoot) {
- nextEffect = null;
- return;
- }
- var sibling = fiber.sibling;
- if (sibling !== null) {
- sibling.return = fiber.return;
- nextEffect = sibling;
- return;
- }
- nextEffect = fiber.return;
- }
- }
- function reappearLayoutEffects_begin(subtreeRoot) {
- while (nextEffect !== null) {
- var fiber = nextEffect;
- var firstChild = fiber.child;
- if (fiber.tag === OffscreenComponent) {
- var isHidden = fiber.memoizedState !== null;
- if (isHidden) {
- // Nested Offscreen tree is still hidden. Don't re-appear its effects.
- reappearLayoutEffects_complete(subtreeRoot);
- continue;
- }
- } // TODO (Offscreen) Check: subtreeFlags & LayoutStatic
- if (firstChild !== null) {
- // This node may have been reused from a previous render, so we can't
- // assume its return pointer is correct.
- firstChild.return = fiber;
- nextEffect = firstChild;
- } else {
- reappearLayoutEffects_complete(subtreeRoot);
- }
- }
- }
- function reappearLayoutEffects_complete(subtreeRoot) {
- while (nextEffect !== null) {
- var fiber = nextEffect; // TODO (Offscreen) Check: flags & LayoutStatic
- setCurrentFiber(fiber);
- try {
- reappearLayoutEffectsOnFiber(fiber);
- } catch (error) {
- captureCommitPhaseError(fiber, fiber.return, error);
- }
- resetCurrentFiber();
- if (fiber === subtreeRoot) {
- nextEffect = null;
- return;
- }
- var sibling = fiber.sibling;
- if (sibling !== null) {
- // This node may have been reused from a previous render, so we can't
- // assume its return pointer is correct.
- sibling.return = fiber.return;
- nextEffect = sibling;
- return;
- }
- nextEffect = fiber.return;
- }
- }
- function commitPassiveMountEffects(root, finishedWork, committedLanes, committedTransitions) {
- nextEffect = finishedWork;
- commitPassiveMountEffects_begin(finishedWork, root, committedLanes, committedTransitions);
- }
- function commitPassiveMountEffects_begin(subtreeRoot, root, committedLanes, committedTransitions) {
- while (nextEffect !== null) {
- var fiber = nextEffect;
- var firstChild = fiber.child;
- if ((fiber.subtreeFlags & PassiveMask) !== NoFlags && firstChild !== null) {
- firstChild.return = fiber;
- nextEffect = firstChild;
- } else {
- commitPassiveMountEffects_complete(subtreeRoot, root, committedLanes, committedTransitions);
- }
- }
- }
- function commitPassiveMountEffects_complete(subtreeRoot, root, committedLanes, committedTransitions) {
- while (nextEffect !== null) {
- var fiber = nextEffect;
- if ((fiber.flags & Passive) !== NoFlags) {
- setCurrentFiber(fiber);
- try {
- commitPassiveMountOnFiber(root, fiber, committedLanes, committedTransitions);
- } catch (error) {
- captureCommitPhaseError(fiber, fiber.return, error);
- }
- resetCurrentFiber();
- }
- if (fiber === subtreeRoot) {
- nextEffect = null;
- return;
- }
- var sibling = fiber.sibling;
- if (sibling !== null) {
- sibling.return = fiber.return;
- nextEffect = sibling;
- return;
- }
- nextEffect = fiber.return;
- }
- }
- function commitPassiveMountOnFiber(finishedRoot, finishedWork, committedLanes, committedTransitions) {
- switch (finishedWork.tag) {
- case FunctionComponent:
- case ForwardRef:
- case SimpleMemoComponent:
- {
- if (finishedWork.mode & ProfileMode) {
- startPassiveEffectTimer();
- try {
- commitHookEffectListMount(Passive$1 | HasEffect, finishedWork);
- } finally {
- recordPassiveEffectDuration(finishedWork);
- }
- } else {
- commitHookEffectListMount(Passive$1 | HasEffect, finishedWork);
- }
- break;
- }
- }
- }
- function commitPassiveUnmountEffects(firstChild) {
- nextEffect = firstChild;
- commitPassiveUnmountEffects_begin();
- }
- function commitPassiveUnmountEffects_begin() {
- while (nextEffect !== null) {
- var fiber = nextEffect;
- var child = fiber.child;
- if ((nextEffect.flags & ChildDeletion) !== NoFlags) {
- var deletions = fiber.deletions;
- if (deletions !== null) {
- for (var i = 0; i < deletions.length; i++) {
- var fiberToDelete = deletions[i];
- nextEffect = fiberToDelete;
- commitPassiveUnmountEffectsInsideOfDeletedTree_begin(fiberToDelete, fiber);
- }
- {
- // A fiber was deleted from this parent fiber, but it's still part of
- // the previous (alternate) parent fiber's list of children. Because
- // children are a linked list, an earlier sibling that's still alive
- // will be connected to the deleted fiber via its `alternate`:
- //
- // live fiber
- // --alternate--> previous live fiber
- // --sibling--> deleted fiber
- //
- // We can't disconnect `alternate` on nodes that haven't been deleted
- // yet, but we can disconnect the `sibling` and `child` pointers.
- var previousFiber = fiber.alternate;
- if (previousFiber !== null) {
- var detachedChild = previousFiber.child;
- if (detachedChild !== null) {
- previousFiber.child = null;
- do {
- var detachedSibling = detachedChild.sibling;
- detachedChild.sibling = null;
- detachedChild = detachedSibling;
- } while (detachedChild !== null);
- }
- }
- }
- nextEffect = fiber;
- }
- }
- if ((fiber.subtreeFlags & PassiveMask) !== NoFlags && child !== null) {
- child.return = fiber;
- nextEffect = child;
- } else {
- commitPassiveUnmountEffects_complete();
- }
- }
- }
- function commitPassiveUnmountEffects_complete() {
- while (nextEffect !== null) {
- var fiber = nextEffect;
- if ((fiber.flags & Passive) !== NoFlags) {
- setCurrentFiber(fiber);
- commitPassiveUnmountOnFiber(fiber);
- resetCurrentFiber();
- }
- var sibling = fiber.sibling;
- if (sibling !== null) {
- sibling.return = fiber.return;
- nextEffect = sibling;
- return;
- }
- nextEffect = fiber.return;
- }
- }
- function commitPassiveUnmountOnFiber(finishedWork) {
- switch (finishedWork.tag) {
- case FunctionComponent:
- case ForwardRef:
- case SimpleMemoComponent:
- {
- if (finishedWork.mode & ProfileMode) {
- startPassiveEffectTimer();
- commitHookEffectListUnmount(Passive$1 | HasEffect, finishedWork, finishedWork.return);
- recordPassiveEffectDuration(finishedWork);
- } else {
- commitHookEffectListUnmount(Passive$1 | HasEffect, finishedWork, finishedWork.return);
- }
- break;
- }
- }
- }
- function commitPassiveUnmountEffectsInsideOfDeletedTree_begin(deletedSubtreeRoot, nearestMountedAncestor) {
- while (nextEffect !== null) {
- var fiber = nextEffect; // Deletion effects fire in parent -> child order
- // TODO: Check if fiber has a PassiveStatic flag
- setCurrentFiber(fiber);
- commitPassiveUnmountInsideDeletedTreeOnFiber(fiber, nearestMountedAncestor);
- resetCurrentFiber();
- var child = fiber.child; // TODO: Only traverse subtree if it has a PassiveStatic flag. (But, if we
- // do this, still need to handle `deletedTreeCleanUpLevel` correctly.)
- if (child !== null) {
- child.return = fiber;
- nextEffect = child;
- } else {
- commitPassiveUnmountEffectsInsideOfDeletedTree_complete(deletedSubtreeRoot);
- }
- }
- }
- function commitPassiveUnmountEffectsInsideOfDeletedTree_complete(deletedSubtreeRoot) {
- while (nextEffect !== null) {
- var fiber = nextEffect;
- var sibling = fiber.sibling;
- var returnFiber = fiber.return;
- {
- // Recursively traverse the entire deleted tree and clean up fiber fields.
- // This is more aggressive than ideal, and the long term goal is to only
- // have to detach the deleted tree at the root.
- detachFiberAfterEffects(fiber);
- if (fiber === deletedSubtreeRoot) {
- nextEffect = null;
- return;
- }
- }
- if (sibling !== null) {
- sibling.return = returnFiber;
- nextEffect = sibling;
- return;
- }
- nextEffect = returnFiber;
- }
- }
- function commitPassiveUnmountInsideDeletedTreeOnFiber(current, nearestMountedAncestor) {
- switch (current.tag) {
- case FunctionComponent:
- case ForwardRef:
- case SimpleMemoComponent:
- {
- if (current.mode & ProfileMode) {
- startPassiveEffectTimer();
- commitHookEffectListUnmount(Passive$1, current, nearestMountedAncestor);
- recordPassiveEffectDuration(current);
- } else {
- commitHookEffectListUnmount(Passive$1, current, nearestMountedAncestor);
- }
- break;
- }
- }
- } // TODO: Reuse reappearLayoutEffects traversal here?
- function invokeLayoutEffectMountInDEV(fiber) {
- {
- // We don't need to re-check StrictEffectsMode here.
- // This function is only called if that check has already passed.
- switch (fiber.tag) {
- case FunctionComponent:
- case ForwardRef:
- case SimpleMemoComponent:
- {
- try {
- commitHookEffectListMount(Layout | HasEffect, fiber);
- } catch (error) {
- captureCommitPhaseError(fiber, fiber.return, error);
- }
- break;
- }
- case ClassComponent:
- {
- var instance = fiber.stateNode;
- try {
- instance.componentDidMount();
- } catch (error) {
- captureCommitPhaseError(fiber, fiber.return, error);
- }
- break;
- }
- }
- }
- }
- function invokePassiveEffectMountInDEV(fiber) {
- {
- // We don't need to re-check StrictEffectsMode here.
- // This function is only called if that check has already passed.
- switch (fiber.tag) {
- case FunctionComponent:
- case ForwardRef:
- case SimpleMemoComponent:
- {
- try {
- commitHookEffectListMount(Passive$1 | HasEffect, fiber);
- } catch (error) {
- captureCommitPhaseError(fiber, fiber.return, error);
- }
- break;
- }
- }
- }
- }
- function invokeLayoutEffectUnmountInDEV(fiber) {
- {
- // We don't need to re-check StrictEffectsMode here.
- // This function is only called if that check has already passed.
- switch (fiber.tag) {
- case FunctionComponent:
- case ForwardRef:
- case SimpleMemoComponent:
- {
- try {
- commitHookEffectListUnmount(Layout | HasEffect, fiber, fiber.return);
- } catch (error) {
- captureCommitPhaseError(fiber, fiber.return, error);
- }
- break;
- }
- case ClassComponent:
- {
- var instance = fiber.stateNode;
- if (typeof instance.componentWillUnmount === 'function') {
- safelyCallComponentWillUnmount(fiber, fiber.return, instance);
- }
- break;
- }
- }
- }
- }
- function invokePassiveEffectUnmountInDEV(fiber) {
- {
- // We don't need to re-check StrictEffectsMode here.
- // This function is only called if that check has already passed.
- switch (fiber.tag) {
- case FunctionComponent:
- case ForwardRef:
- case SimpleMemoComponent:
- {
- try {
- commitHookEffectListUnmount(Passive$1 | HasEffect, fiber, fiber.return);
- } catch (error) {
- captureCommitPhaseError(fiber, fiber.return, error);
- }
- }
- }
- }
- }
- var COMPONENT_TYPE = 0;
- var HAS_PSEUDO_CLASS_TYPE = 1;
- var ROLE_TYPE = 2;
- var TEST_NAME_TYPE = 3;
- var TEXT_TYPE = 4;
- if (typeof Symbol === 'function' && Symbol.for) {
- var symbolFor = Symbol.for;
- COMPONENT_TYPE = symbolFor('selector.component');
- HAS_PSEUDO_CLASS_TYPE = symbolFor('selector.has_pseudo_class');
- ROLE_TYPE = symbolFor('selector.role');
- TEST_NAME_TYPE = symbolFor('selector.test_id');
- TEXT_TYPE = symbolFor('selector.text');
- }
- var commitHooks = [];
- function onCommitRoot$1() {
- {
- commitHooks.forEach(function (commitHook) {
- return commitHook();
- });
- }
- }
- var ReactCurrentActQueue = ReactSharedInternals.ReactCurrentActQueue;
- function isLegacyActEnvironment(fiber) {
- {
- // Legacy mode. We preserve the behavior of React 17's act. It assumes an
- // act environment whenever `jest` is defined, but you can still turn off
- // spurious warnings by setting IS_REACT_ACT_ENVIRONMENT explicitly
- // to false.
- var isReactActEnvironmentGlobal = // $FlowExpectedError – Flow doesn't know about IS_REACT_ACT_ENVIRONMENT global
- typeof IS_REACT_ACT_ENVIRONMENT !== 'undefined' ? IS_REACT_ACT_ENVIRONMENT : undefined; // $FlowExpectedError - Flow doesn't know about jest
- var jestIsDefined = typeof jest !== 'undefined';
- return jestIsDefined && isReactActEnvironmentGlobal !== false;
- }
- }
- function isConcurrentActEnvironment() {
- {
- var isReactActEnvironmentGlobal = // $FlowExpectedError – Flow doesn't know about IS_REACT_ACT_ENVIRONMENT global
- typeof IS_REACT_ACT_ENVIRONMENT !== 'undefined' ? IS_REACT_ACT_ENVIRONMENT : undefined;
- if (!isReactActEnvironmentGlobal && ReactCurrentActQueue.current !== null) {
- // TODO: Include link to relevant documentation page.
- error('The current testing environment is not configured to support ' + 'act(...)');
- }
- return isReactActEnvironmentGlobal;
- }
- }
- var ceil = Math.ceil;
- var ReactCurrentDispatcher$2 = ReactSharedInternals.ReactCurrentDispatcher,
- ReactCurrentOwner$2 = ReactSharedInternals.ReactCurrentOwner,
- ReactCurrentBatchConfig$3 = ReactSharedInternals.ReactCurrentBatchConfig,
- ReactCurrentActQueue$1 = ReactSharedInternals.ReactCurrentActQueue;
- var NoContext =
- /* */
- 0;
- var BatchedContext =
- /* */
- 1;
- var RenderContext =
- /* */
- 2;
- var CommitContext =
- /* */
- 4;
- var RootInProgress = 0;
- var RootFatalErrored = 1;
- var RootErrored = 2;
- var RootSuspended = 3;
- var RootSuspendedWithDelay = 4;
- var RootCompleted = 5;
- var RootDidNotComplete = 6; // Describes where we are in the React execution stack
- var executionContext = NoContext; // The root we're working on
- var workInProgressRoot = null; // The fiber we're working on
- var workInProgress = null; // The lanes we're rendering
- var workInProgressRootRenderLanes = NoLanes; // Stack that allows components to change the render lanes for its subtree
- // This is a superset of the lanes we started working on at the root. The only
- // case where it's different from `workInProgressRootRenderLanes` is when we
- // enter a subtree that is hidden and needs to be unhidden: Suspense and
- // Offscreen component.
- //
- // Most things in the work loop should deal with workInProgressRootRenderLanes.
- // Most things in begin/complete phases should deal with subtreeRenderLanes.
- var subtreeRenderLanes = NoLanes;
- var subtreeRenderLanesCursor = createCursor(NoLanes); // Whether to root completed, errored, suspended, etc.
- var workInProgressRootExitStatus = RootInProgress; // A fatal error, if one is thrown
- var workInProgressRootFatalError = null; // "Included" lanes refer to lanes that were worked on during this render. It's
- // slightly different than `renderLanes` because `renderLanes` can change as you
- // enter and exit an Offscreen tree. This value is the combination of all render
- // lanes for the entire render phase.
- var workInProgressRootIncludedLanes = NoLanes; // The work left over by components that were visited during this render. Only
- // includes unprocessed updates, not work in bailed out children.
- var workInProgressRootSkippedLanes = NoLanes; // Lanes that were updated (in an interleaved event) during this render.
- var workInProgressRootInterleavedUpdatedLanes = NoLanes; // Lanes that were updated during the render phase (*not* an interleaved event).
- var workInProgressRootPingedLanes = NoLanes; // Errors that are thrown during the render phase.
- var workInProgressRootConcurrentErrors = null; // These are errors that we recovered from without surfacing them to the UI.
- // We will log them once the tree commits.
- var workInProgressRootRecoverableErrors = null; // The most recent time we committed a fallback. This lets us ensure a train
- // model where we don't commit new loading states in too quick succession.
- var globalMostRecentFallbackTime = 0;
- var FALLBACK_THROTTLE_MS = 500; // The absolute time for when we should start giving up on rendering
- // more and prefer CPU suspense heuristics instead.
- var workInProgressRootRenderTargetTime = Infinity; // How long a render is supposed to take before we start following CPU
- // suspense heuristics and opt out of rendering more content.
- var RENDER_TIMEOUT_MS = 500;
- var workInProgressTransitions = null;
- function resetRenderTimer() {
- workInProgressRootRenderTargetTime = now() + RENDER_TIMEOUT_MS;
- }
- function getRenderTargetTime() {
- return workInProgressRootRenderTargetTime;
- }
- var hasUncaughtError = false;
- var firstUncaughtError = null;
- var legacyErrorBoundariesThatAlreadyFailed = null; // Only used when enableProfilerNestedUpdateScheduledHook is true;
- var rootDoesHavePassiveEffects = false;
- var rootWithPendingPassiveEffects = null;
- var pendingPassiveEffectsLanes = NoLanes;
- var pendingPassiveProfilerEffects = [];
- var pendingPassiveTransitions = null; // Use these to prevent an infinite loop of nested updates
- var NESTED_UPDATE_LIMIT = 50;
- var nestedUpdateCount = 0;
- var rootWithNestedUpdates = null;
- var isFlushingPassiveEffects = false;
- var didScheduleUpdateDuringPassiveEffects = false;
- var NESTED_PASSIVE_UPDATE_LIMIT = 50;
- var nestedPassiveUpdateCount = 0;
- var rootWithPassiveNestedUpdates = null; // If two updates are scheduled within the same event, we should treat their
- // event times as simultaneous, even if the actual clock time has advanced
- // between the first and second call.
- var currentEventTime = NoTimestamp;
- var currentEventTransitionLane = NoLanes;
- var isRunningInsertionEffect = false;
- function getWorkInProgressRoot() {
- return workInProgressRoot;
- }
- function requestEventTime() {
- if ((executionContext & (RenderContext | CommitContext)) !== NoContext) {
- // We're inside React, so it's fine to read the actual time.
- return now();
- } // We're not inside React, so we may be in the middle of a browser event.
- if (currentEventTime !== NoTimestamp) {
- // Use the same start time for all updates until we enter React again.
- return currentEventTime;
- } // This is the first update since React yielded. Compute a new start time.
- currentEventTime = now();
- return currentEventTime;
- }
- function requestUpdateLane(fiber) {
- // Special cases
- var mode = fiber.mode;
- if ((mode & ConcurrentMode) === NoMode) {
- return SyncLane;
- } else if ((executionContext & RenderContext) !== NoContext && workInProgressRootRenderLanes !== NoLanes) {
- // This is a render phase update. These are not officially supported. The
- // old behavior is to give this the same "thread" (lanes) as
- // whatever is currently rendering. So if you call `setState` on a component
- // that happens later in the same render, it will flush. Ideally, we want to
- // remove the special case and treat them as if they came from an
- // interleaved event. Regardless, this pattern is not officially supported.
- // This behavior is only a fallback. The flag only exists until we can roll
- // out the setState warning, since existing code might accidentally rely on
- // the current behavior.
- return pickArbitraryLane(workInProgressRootRenderLanes);
- }
- var isTransition = requestCurrentTransition() !== NoTransition;
- if (isTransition) {
- if (ReactCurrentBatchConfig$3.transition !== null) {
- var transition = ReactCurrentBatchConfig$3.transition;
- if (!transition._updatedFibers) {
- transition._updatedFibers = new Set();
- }
- transition._updatedFibers.add(fiber);
- } // The algorithm for assigning an update to a lane should be stable for all
- // updates at the same priority within the same event. To do this, the
- // inputs to the algorithm must be the same.
- //
- // The trick we use is to cache the first of each of these inputs within an
- // event. Then reset the cached values once we can be sure the event is
- // over. Our heuristic for that is whenever we enter a concurrent work loop.
- if (currentEventTransitionLane === NoLane) {
- // All transitions within the same event are assigned the same lane.
- currentEventTransitionLane = claimNextTransitionLane();
- }
- return currentEventTransitionLane;
- } // Updates originating inside certain React methods, like flushSync, have
- // their priority set by tracking it with a context variable.
- //
- // The opaque type returned by the host config is internally a lane, so we can
- // use that directly.
- // TODO: Move this type conversion to the event priority module.
- var updateLane = getCurrentUpdatePriority();
- if (updateLane !== NoLane) {
- return updateLane;
- } // This update originated outside React. Ask the host environment for an
- // appropriate priority, based on the type of event.
- //
- // The opaque type returned by the host config is internally a lane, so we can
- // use that directly.
- // TODO: Move this type conversion to the event priority module.
- var eventLane = getCurrentEventPriority();
- return eventLane;
- }
- function requestRetryLane(fiber) {
- // This is a fork of `requestUpdateLane` designed specifically for Suspense
- // "retries" — a special update that attempts to flip a Suspense boundary
- // from its placeholder state to its primary/resolved state.
- // Special cases
- var mode = fiber.mode;
- if ((mode & ConcurrentMode) === NoMode) {
- return SyncLane;
- }
- return claimNextRetryLane();
- }
- function scheduleUpdateOnFiber(root, fiber, lane, eventTime) {
- checkForNestedUpdates();
- {
- if (isRunningInsertionEffect) {
- error('useInsertionEffect must not schedule updates.');
- }
- }
- {
- if (isFlushingPassiveEffects) {
- didScheduleUpdateDuringPassiveEffects = true;
- }
- } // Mark that the root has a pending update.
- markRootUpdated(root, lane, eventTime);
- if ((executionContext & RenderContext) !== NoLanes && root === workInProgressRoot) {
- // This update was dispatched during the render phase. This is a mistake
- // if the update originates from user space (with the exception of local
- // hook updates, which are handled differently and don't reach this
- // function), but there are some internal React features that use this as
- // an implementation detail, like selective hydration.
- warnAboutRenderPhaseUpdatesInDEV(fiber); // Track lanes that were updated during the render phase
- } else {
- // This is a normal update, scheduled from outside the render phase. For
- // example, during an input event.
- {
- if (isDevToolsPresent) {
- addFiberToLanesMap(root, fiber, lane);
- }
- }
- warnIfUpdatesNotWrappedWithActDEV(fiber);
- if (root === workInProgressRoot) {
- // Received an update to a tree that's in the middle of rendering. Mark
- // that there was an interleaved update work on this root. Unless the
- // `deferRenderPhaseUpdateToNextBatch` flag is off and this is a render
- // phase update. In that case, we don't treat render phase updates as if
- // they were interleaved, for backwards compat reasons.
- if ((executionContext & RenderContext) === NoContext) {
- workInProgressRootInterleavedUpdatedLanes = mergeLanes(workInProgressRootInterleavedUpdatedLanes, lane);
- }
- if (workInProgressRootExitStatus === RootSuspendedWithDelay) {
- // The root already suspended with a delay, which means this render
- // definitely won't finish. Since we have a new update, let's mark it as
- // suspended now, right before marking the incoming update. This has the
- // effect of interrupting the current render and switching to the update.
- // TODO: Make sure this doesn't override pings that happen while we've
- // already started rendering.
- markRootSuspended$1(root, workInProgressRootRenderLanes);
- }
- }
- ensureRootIsScheduled(root, eventTime);
- if (lane === SyncLane && executionContext === NoContext && (fiber.mode & ConcurrentMode) === NoMode && // Treat `act` as if it's inside `batchedUpdates`, even in legacy mode.
- !(ReactCurrentActQueue$1.isBatchingLegacy)) {
- // Flush the synchronous work now, unless we're already working or inside
- // a batch. This is intentionally inside scheduleUpdateOnFiber instead of
- // scheduleCallbackForFiber to preserve the ability to schedule a callback
- // without immediately flushing it. We only do this for user-initiated
- // updates, to preserve historical behavior of legacy mode.
- resetRenderTimer();
- flushSyncCallbacksOnlyInLegacyMode();
- }
- }
- }
- function scheduleInitialHydrationOnRoot(root, lane, eventTime) {
- // This is a special fork of scheduleUpdateOnFiber that is only used to
- // schedule the initial hydration of a root that has just been created. Most
- // of the stuff in scheduleUpdateOnFiber can be skipped.
- //
- // The main reason for this separate path, though, is to distinguish the
- // initial children from subsequent updates. In fully client-rendered roots
- // (createRoot instead of hydrateRoot), all top-level renders are modeled as
- // updates, but hydration roots are special because the initial render must
- // match what was rendered on the server.
- var current = root.current;
- current.lanes = lane;
- markRootUpdated(root, lane, eventTime);
- ensureRootIsScheduled(root, eventTime);
- }
- function isUnsafeClassRenderPhaseUpdate(fiber) {
- // Check if this is a render phase update. Only called by class components,
- // which special (deprecated) behavior for UNSAFE_componentWillReceive props.
- return (// TODO: Remove outdated deferRenderPhaseUpdateToNextBatch experiment. We
- // decided not to enable it.
- (executionContext & RenderContext) !== NoContext
- );
- } // Use this function to schedule a task for a root. There's only one task per
- // root; if a task was already scheduled, we'll check to make sure the priority
- // of the existing task is the same as the priority of the next level that the
- // root has work on. This function is called on every update, and right before
- // exiting a task.
- function ensureRootIsScheduled(root, currentTime) {
- var existingCallbackNode = root.callbackNode; // Check if any lanes are being starved by other work. If so, mark them as
- // expired so we know to work on those next.
- markStarvedLanesAsExpired(root, currentTime); // Determine the next lanes to work on, and their priority.
- var nextLanes = getNextLanes(root, root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes);
- if (nextLanes === NoLanes) {
- // Special case: There's nothing to work on.
- if (existingCallbackNode !== null) {
- cancelCallback$1(existingCallbackNode);
- }
- root.callbackNode = null;
- root.callbackPriority = NoLane;
- return;
- } // We use the highest priority lane to represent the priority of the callback.
- var newCallbackPriority = getHighestPriorityLane(nextLanes); // Check if there's an existing task. We may be able to reuse it.
- var existingCallbackPriority = root.callbackPriority;
- if (existingCallbackPriority === newCallbackPriority && // Special case related to `act`. If the currently scheduled task is a
- // Scheduler task, rather than an `act` task, cancel it and re-scheduled
- // on the `act` queue.
- !(ReactCurrentActQueue$1.current !== null && existingCallbackNode !== fakeActCallbackNode)) {
- {
- // If we're going to re-use an existing task, it needs to exist.
- // Assume that discrete update microtasks are non-cancellable and null.
- // TODO: Temporary until we confirm this warning is not fired.
- if (existingCallbackNode == null && existingCallbackPriority !== SyncLane) {
- error('Expected scheduled callback to exist. This error is likely caused by a bug in React. Please file an issue.');
- }
- } // The priority hasn't changed. We can reuse the existing task. Exit.
- return;
- }
- if (existingCallbackNode != null) {
- // Cancel the existing callback. We'll schedule a new one below.
- cancelCallback$1(existingCallbackNode);
- } // Schedule a new callback.
- var newCallbackNode;
- if (newCallbackPriority === SyncLane) {
- // Special case: Sync React callbacks are scheduled on a special
- // internal queue
- if (root.tag === LegacyRoot) {
- if (ReactCurrentActQueue$1.isBatchingLegacy !== null) {
- ReactCurrentActQueue$1.didScheduleLegacyUpdate = true;
- }
- scheduleLegacySyncCallback(performSyncWorkOnRoot.bind(null, root));
- } else {
- scheduleSyncCallback(performSyncWorkOnRoot.bind(null, root));
- }
- {
- // Flush the queue in a microtask.
- if (ReactCurrentActQueue$1.current !== null) {
- // Inside `act`, use our internal `act` queue so that these get flushed
- // at the end of the current scope even when using the sync version
- // of `act`.
- ReactCurrentActQueue$1.current.push(flushSyncCallbacks);
- } else {
- scheduleMicrotask(function () {
- // In Safari, appending an iframe forces microtasks to run.
- // https://github.com/facebook/react/issues/22459
- // We don't support running callbacks in the middle of render
- // or commit so we need to check against that.
- if ((executionContext & (RenderContext | CommitContext)) === NoContext) {
- // Note that this would still prematurely flush the callbacks
- // if this happens outside render or commit phase (e.g. in an event).
- flushSyncCallbacks();
- }
- });
- }
- }
- newCallbackNode = null;
- } else {
- var schedulerPriorityLevel;
- switch (lanesToEventPriority(nextLanes)) {
- case DiscreteEventPriority:
- schedulerPriorityLevel = ImmediatePriority;
- break;
- case ContinuousEventPriority:
- schedulerPriorityLevel = UserBlockingPriority;
- break;
- case DefaultEventPriority:
- schedulerPriorityLevel = NormalPriority;
- break;
- case IdleEventPriority:
- schedulerPriorityLevel = IdlePriority;
- break;
- default:
- schedulerPriorityLevel = NormalPriority;
- break;
- }
- newCallbackNode = scheduleCallback$1(schedulerPriorityLevel, performConcurrentWorkOnRoot.bind(null, root));
- }
- root.callbackPriority = newCallbackPriority;
- root.callbackNode = newCallbackNode;
- } // This is the entry point for every concurrent task, i.e. anything that
- // goes through Scheduler.
- function performConcurrentWorkOnRoot(root, didTimeout) {
- {
- resetNestedUpdateFlag();
- } // Since we know we're in a React event, we can clear the current
- // event time. The next update will compute a new event time.
- currentEventTime = NoTimestamp;
- currentEventTransitionLane = NoLanes;
- if ((executionContext & (RenderContext | CommitContext)) !== NoContext) {
- throw new Error('Should not already be working.');
- } // Flush any pending passive effects before deciding which lanes to work on,
- // in case they schedule additional work.
- var originalCallbackNode = root.callbackNode;
- var didFlushPassiveEffects = flushPassiveEffects();
- if (didFlushPassiveEffects) {
- // Something in the passive effect phase may have canceled the current task.
- // Check if the task node for this root was changed.
- if (root.callbackNode !== originalCallbackNode) {
- // The current task was canceled. Exit. We don't need to call
- // `ensureRootIsScheduled` because the check above implies either that
- // there's a new task, or that there's no remaining work on this root.
- return null;
- }
- } // Determine the next lanes to work on, using the fields stored
- // on the root.
- var lanes = getNextLanes(root, root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes);
- if (lanes === NoLanes) {
- // Defensive coding. This is never expected to happen.
- return null;
- } // We disable time-slicing in some cases: if the work has been CPU-bound
- // for too long ("expired" work, to prevent starvation), or we're in
- // sync-updates-by-default mode.
- // TODO: We only check `didTimeout` defensively, to account for a Scheduler
- // bug we're still investigating. Once the bug in Scheduler is fixed,
- // we can remove this, since we track expiration ourselves.
- var shouldTimeSlice = !includesBlockingLane(root, lanes) && !includesExpiredLane(root, lanes) && (!didTimeout);
- var exitStatus = shouldTimeSlice ? renderRootConcurrent(root, lanes) : renderRootSync(root, lanes);
- if (exitStatus !== RootInProgress) {
- if (exitStatus === RootErrored) {
- // If something threw an error, try rendering one more time. We'll
- // render synchronously to block concurrent data mutations, and we'll
- // includes all pending updates are included. If it still fails after
- // the second attempt, we'll give up and commit the resulting tree.
- var errorRetryLanes = getLanesToRetrySynchronouslyOnError(root);
- if (errorRetryLanes !== NoLanes) {
- lanes = errorRetryLanes;
- exitStatus = recoverFromConcurrentError(root, errorRetryLanes);
- }
- }
- if (exitStatus === RootFatalErrored) {
- var fatalError = workInProgressRootFatalError;
- prepareFreshStack(root, NoLanes);
- markRootSuspended$1(root, lanes);
- ensureRootIsScheduled(root, now());
- throw fatalError;
- }
- if (exitStatus === RootDidNotComplete) {
- // The render unwound without completing the tree. This happens in special
- // cases where need to exit the current render without producing a
- // consistent tree or committing.
- //
- // This should only happen during a concurrent render, not a discrete or
- // synchronous update. We should have already checked for this when we
- // unwound the stack.
- markRootSuspended$1(root, lanes);
- } else {
- // The render completed.
- // Check if this render may have yielded to a concurrent event, and if so,
- // confirm that any newly rendered stores are consistent.
- // TODO: It's possible that even a concurrent render may never have yielded
- // to the main thread, if it was fast enough, or if it expired. We could
- // skip the consistency check in that case, too.
- var renderWasConcurrent = !includesBlockingLane(root, lanes);
- var finishedWork = root.current.alternate;
- if (renderWasConcurrent && !isRenderConsistentWithExternalStores(finishedWork)) {
- // A store was mutated in an interleaved event. Render again,
- // synchronously, to block further mutations.
- exitStatus = renderRootSync(root, lanes); // We need to check again if something threw
- if (exitStatus === RootErrored) {
- var _errorRetryLanes = getLanesToRetrySynchronouslyOnError(root);
- if (_errorRetryLanes !== NoLanes) {
- lanes = _errorRetryLanes;
- exitStatus = recoverFromConcurrentError(root, _errorRetryLanes); // We assume the tree is now consistent because we didn't yield to any
- // concurrent events.
- }
- }
- if (exitStatus === RootFatalErrored) {
- var _fatalError = workInProgressRootFatalError;
- prepareFreshStack(root, NoLanes);
- markRootSuspended$1(root, lanes);
- ensureRootIsScheduled(root, now());
- throw _fatalError;
- }
- } // We now have a consistent tree. The next step is either to commit it,
- // or, if something suspended, wait to commit it after a timeout.
- root.finishedWork = finishedWork;
- root.finishedLanes = lanes;
- finishConcurrentRender(root, exitStatus, lanes);
- }
- }
- ensureRootIsScheduled(root, now());
- if (root.callbackNode === originalCallbackNode) {
- // The task node scheduled for this root is the same one that's
- // currently executed. Need to return a continuation.
- return performConcurrentWorkOnRoot.bind(null, root);
- }
- return null;
- }
- function recoverFromConcurrentError(root, errorRetryLanes) {
- // If an error occurred during hydration, discard server response and fall
- // back to client side render.
- // Before rendering again, save the errors from the previous attempt.
- var errorsFromFirstAttempt = workInProgressRootConcurrentErrors;
- if (isRootDehydrated(root)) {
- // The shell failed to hydrate. Set a flag to force a client rendering
- // during the next attempt. To do this, we call prepareFreshStack now
- // to create the root work-in-progress fiber. This is a bit weird in terms
- // of factoring, because it relies on renderRootSync not calling
- // prepareFreshStack again in the call below, which happens because the
- // root and lanes haven't changed.
- //
- // TODO: I think what we should do is set ForceClientRender inside
- // throwException, like we do for nested Suspense boundaries. The reason
- // it's here instead is so we can switch to the synchronous work loop, too.
- // Something to consider for a future refactor.
- var rootWorkInProgress = prepareFreshStack(root, errorRetryLanes);
- rootWorkInProgress.flags |= ForceClientRender;
- {
- errorHydratingContainer(root.containerInfo);
- }
- }
- var exitStatus = renderRootSync(root, errorRetryLanes);
- if (exitStatus !== RootErrored) {
- // Successfully finished rendering on retry
- // The errors from the failed first attempt have been recovered. Add
- // them to the collection of recoverable errors. We'll log them in the
- // commit phase.
- var errorsFromSecondAttempt = workInProgressRootRecoverableErrors;
- workInProgressRootRecoverableErrors = errorsFromFirstAttempt; // The errors from the second attempt should be queued after the errors
- // from the first attempt, to preserve the causal sequence.
- if (errorsFromSecondAttempt !== null) {
- queueRecoverableErrors(errorsFromSecondAttempt);
- }
- }
- return exitStatus;
- }
- function queueRecoverableErrors(errors) {
- if (workInProgressRootRecoverableErrors === null) {
- workInProgressRootRecoverableErrors = errors;
- } else {
- workInProgressRootRecoverableErrors.push.apply(workInProgressRootRecoverableErrors, errors);
- }
- }
- function finishConcurrentRender(root, exitStatus, lanes) {
- switch (exitStatus) {
- case RootInProgress:
- case RootFatalErrored:
- {
- throw new Error('Root did not complete. This is a bug in React.');
- }
- // Flow knows about invariant, so it complains if I add a break
- // statement, but eslint doesn't know about invariant, so it complains
- // if I do. eslint-disable-next-line no-fallthrough
- case RootErrored:
- {
- // We should have already attempted to retry this tree. If we reached
- // this point, it errored again. Commit it.
- commitRoot(root, workInProgressRootRecoverableErrors, workInProgressTransitions);
- break;
- }
- case RootSuspended:
- {
- markRootSuspended$1(root, lanes); // We have an acceptable loading state. We need to figure out if we
- // should immediately commit it or wait a bit.
- if (includesOnlyRetries(lanes) && // do not delay if we're inside an act() scope
- !shouldForceFlushFallbacksInDEV()) {
- // This render only included retries, no updates. Throttle committing
- // retries so that we don't show too many loading states too quickly.
- var msUntilTimeout = globalMostRecentFallbackTime + FALLBACK_THROTTLE_MS - now(); // Don't bother with a very short suspense time.
- if (msUntilTimeout > 10) {
- var nextLanes = getNextLanes(root, NoLanes);
- if (nextLanes !== NoLanes) {
- // There's additional work on this root.
- break;
- }
- var suspendedLanes = root.suspendedLanes;
- if (!isSubsetOfLanes(suspendedLanes, lanes)) {
- // We should prefer to render the fallback of at the last
- // suspended level. Ping the last suspended level to try
- // rendering it again.
- // FIXME: What if the suspended lanes are Idle? Should not restart.
- var eventTime = requestEventTime();
- markRootPinged(root, suspendedLanes);
- break;
- } // The render is suspended, it hasn't timed out, and there's no
- // lower priority work to do. Instead of committing the fallback
- // immediately, wait for more data to arrive.
- root.timeoutHandle = scheduleTimeout(commitRoot.bind(null, root, workInProgressRootRecoverableErrors, workInProgressTransitions), msUntilTimeout);
- break;
- }
- } // The work expired. Commit immediately.
- commitRoot(root, workInProgressRootRecoverableErrors, workInProgressTransitions);
- break;
- }
- case RootSuspendedWithDelay:
- {
- markRootSuspended$1(root, lanes);
- if (includesOnlyTransitions(lanes)) {
- // This is a transition, so we should exit without committing a
- // placeholder and without scheduling a timeout. Delay indefinitely
- // until we receive more data.
- break;
- }
- if (!shouldForceFlushFallbacksInDEV()) {
- // This is not a transition, but we did trigger an avoided state.
- // Schedule a placeholder to display after a short delay, using the Just
- // Noticeable Difference.
- // TODO: Is the JND optimization worth the added complexity? If this is
- // the only reason we track the event time, then probably not.
- // Consider removing.
- var mostRecentEventTime = getMostRecentEventTime(root, lanes);
- var eventTimeMs = mostRecentEventTime;
- var timeElapsedMs = now() - eventTimeMs;
- var _msUntilTimeout = jnd(timeElapsedMs) - timeElapsedMs; // Don't bother with a very short suspense time.
- if (_msUntilTimeout > 10) {
- // Instead of committing the fallback immediately, wait for more data
- // to arrive.
- root.timeoutHandle = scheduleTimeout(commitRoot.bind(null, root, workInProgressRootRecoverableErrors, workInProgressTransitions), _msUntilTimeout);
- break;
- }
- } // Commit the placeholder.
- commitRoot(root, workInProgressRootRecoverableErrors, workInProgressTransitions);
- break;
- }
- case RootCompleted:
- {
- // The work completed. Ready to commit.
- commitRoot(root, workInProgressRootRecoverableErrors, workInProgressTransitions);
- break;
- }
- default:
- {
- throw new Error('Unknown root exit status.');
- }
- }
- }
- function isRenderConsistentWithExternalStores(finishedWork) {
- // Search the rendered tree for external store reads, and check whether the
- // stores were mutated in a concurrent event. Intentionally using an iterative
- // loop instead of recursion so we can exit early.
- var node = finishedWork;
- while (true) {
- if (node.flags & StoreConsistency) {
- var updateQueue = node.updateQueue;
- if (updateQueue !== null) {
- var checks = updateQueue.stores;
- if (checks !== null) {
- for (var i = 0; i < checks.length; i++) {
- var check = checks[i];
- var getSnapshot = check.getSnapshot;
- var renderedValue = check.value;
- try {
- if (!objectIs(getSnapshot(), renderedValue)) {
- // Found an inconsistent store.
- return false;
- }
- } catch (error) {
- // If `getSnapshot` throws, return `false`. This will schedule
- // a re-render, and the error will be rethrown during render.
- return false;
- }
- }
- }
- }
- }
- var child = node.child;
- if (node.subtreeFlags & StoreConsistency && child !== null) {
- child.return = node;
- node = child;
- continue;
- }
- if (node === finishedWork) {
- return true;
- }
- while (node.sibling === null) {
- if (node.return === null || node.return === finishedWork) {
- return true;
- }
- node = node.return;
- }
- node.sibling.return = node.return;
- node = node.sibling;
- } // Flow doesn't know this is unreachable, but eslint does
- // eslint-disable-next-line no-unreachable
- return true;
- }
- function markRootSuspended$1(root, suspendedLanes) {
- // When suspending, we should always exclude lanes that were pinged or (more
- // rarely, since we try to avoid it) updated during the render phase.
- // TODO: Lol maybe there's a better way to factor this besides this
- // obnoxiously named function :)
- suspendedLanes = removeLanes(suspendedLanes, workInProgressRootPingedLanes);
- suspendedLanes = removeLanes(suspendedLanes, workInProgressRootInterleavedUpdatedLanes);
- markRootSuspended(root, suspendedLanes);
- } // This is the entry point for synchronous tasks that don't go
- // through Scheduler
- function performSyncWorkOnRoot(root) {
- {
- syncNestedUpdateFlag();
- }
- if ((executionContext & (RenderContext | CommitContext)) !== NoContext) {
- throw new Error('Should not already be working.');
- }
- flushPassiveEffects();
- var lanes = getNextLanes(root, NoLanes);
- if (!includesSomeLane(lanes, SyncLane)) {
- // There's no remaining sync work left.
- ensureRootIsScheduled(root, now());
- return null;
- }
- var exitStatus = renderRootSync(root, lanes);
- if (root.tag !== LegacyRoot && exitStatus === RootErrored) {
- // If something threw an error, try rendering one more time. We'll render
- // synchronously to block concurrent data mutations, and we'll includes
- // all pending updates are included. If it still fails after the second
- // attempt, we'll give up and commit the resulting tree.
- var errorRetryLanes = getLanesToRetrySynchronouslyOnError(root);
- if (errorRetryLanes !== NoLanes) {
- lanes = errorRetryLanes;
- exitStatus = recoverFromConcurrentError(root, errorRetryLanes);
- }
- }
- if (exitStatus === RootFatalErrored) {
- var fatalError = workInProgressRootFatalError;
- prepareFreshStack(root, NoLanes);
- markRootSuspended$1(root, lanes);
- ensureRootIsScheduled(root, now());
- throw fatalError;
- }
- if (exitStatus === RootDidNotComplete) {
- throw new Error('Root did not complete. This is a bug in React.');
- } // We now have a consistent tree. Because this is a sync render, we
- // will commit it even if something suspended.
- var finishedWork = root.current.alternate;
- root.finishedWork = finishedWork;
- root.finishedLanes = lanes;
- commitRoot(root, workInProgressRootRecoverableErrors, workInProgressTransitions); // Before exiting, make sure there's a callback scheduled for the next
- // pending level.
- ensureRootIsScheduled(root, now());
- return null;
- }
- function flushRoot(root, lanes) {
- if (lanes !== NoLanes) {
- markRootEntangled(root, mergeLanes(lanes, SyncLane));
- ensureRootIsScheduled(root, now());
- if ((executionContext & (RenderContext | CommitContext)) === NoContext) {
- resetRenderTimer();
- flushSyncCallbacks();
- }
- }
- }
- function batchedUpdates$1(fn, a) {
- var prevExecutionContext = executionContext;
- executionContext |= BatchedContext;
- try {
- return fn(a);
- } finally {
- executionContext = prevExecutionContext; // If there were legacy sync updates, flush them at the end of the outer
- // most batchedUpdates-like method.
- if (executionContext === NoContext && // Treat `act` as if it's inside `batchedUpdates`, even in legacy mode.
- !(ReactCurrentActQueue$1.isBatchingLegacy)) {
- resetRenderTimer();
- flushSyncCallbacksOnlyInLegacyMode();
- }
- }
- }
- function discreteUpdates(fn, a, b, c, d) {
- var previousPriority = getCurrentUpdatePriority();
- var prevTransition = ReactCurrentBatchConfig$3.transition;
- try {
- ReactCurrentBatchConfig$3.transition = null;
- setCurrentUpdatePriority(DiscreteEventPriority);
- return fn(a, b, c, d);
- } finally {
- setCurrentUpdatePriority(previousPriority);
- ReactCurrentBatchConfig$3.transition = prevTransition;
- if (executionContext === NoContext) {
- resetRenderTimer();
- }
- }
- } // Overload the definition to the two valid signatures.
- // Warning, this opts-out of checking the function body.
- // eslint-disable-next-line no-redeclare
- function flushSync(fn) {
- // In legacy mode, we flush pending passive effects at the beginning of the
- // next event, not at the end of the previous one.
- if (rootWithPendingPassiveEffects !== null && rootWithPendingPassiveEffects.tag === LegacyRoot && (executionContext & (RenderContext | CommitContext)) === NoContext) {
- flushPassiveEffects();
- }
- var prevExecutionContext = executionContext;
- executionContext |= BatchedContext;
- var prevTransition = ReactCurrentBatchConfig$3.transition;
- var previousPriority = getCurrentUpdatePriority();
- try {
- ReactCurrentBatchConfig$3.transition = null;
- setCurrentUpdatePriority(DiscreteEventPriority);
- if (fn) {
- return fn();
- } else {
- return undefined;
- }
- } finally {
- setCurrentUpdatePriority(previousPriority);
- ReactCurrentBatchConfig$3.transition = prevTransition;
- executionContext = prevExecutionContext; // Flush the immediate callbacks that were scheduled during this batch.
- // Note that this will happen even if batchedUpdates is higher up
- // the stack.
- if ((executionContext & (RenderContext | CommitContext)) === NoContext) {
- flushSyncCallbacks();
- }
- }
- }
- function isAlreadyRendering() {
- // Used by the renderer to print a warning if certain APIs are called from
- // the wrong context.
- return (executionContext & (RenderContext | CommitContext)) !== NoContext;
- }
- function pushRenderLanes(fiber, lanes) {
- push(subtreeRenderLanesCursor, subtreeRenderLanes, fiber);
- subtreeRenderLanes = mergeLanes(subtreeRenderLanes, lanes);
- workInProgressRootIncludedLanes = mergeLanes(workInProgressRootIncludedLanes, lanes);
- }
- function popRenderLanes(fiber) {
- subtreeRenderLanes = subtreeRenderLanesCursor.current;
- pop(subtreeRenderLanesCursor, fiber);
- }
- function prepareFreshStack(root, lanes) {
- root.finishedWork = null;
- root.finishedLanes = NoLanes;
- var timeoutHandle = root.timeoutHandle;
- if (timeoutHandle !== noTimeout) {
- // The root previous suspended and scheduled a timeout to commit a fallback
- // state. Now that we have additional work, cancel the timeout.
- root.timeoutHandle = noTimeout; // $FlowFixMe Complains noTimeout is not a TimeoutID, despite the check above
- cancelTimeout(timeoutHandle);
- }
- if (workInProgress !== null) {
- var interruptedWork = workInProgress.return;
- while (interruptedWork !== null) {
- var current = interruptedWork.alternate;
- unwindInterruptedWork(current, interruptedWork);
- interruptedWork = interruptedWork.return;
- }
- }
- workInProgressRoot = root;
- var rootWorkInProgress = createWorkInProgress(root.current, null);
- workInProgress = rootWorkInProgress;
- workInProgressRootRenderLanes = subtreeRenderLanes = workInProgressRootIncludedLanes = lanes;
- workInProgressRootExitStatus = RootInProgress;
- workInProgressRootFatalError = null;
- workInProgressRootSkippedLanes = NoLanes;
- workInProgressRootInterleavedUpdatedLanes = NoLanes;
- workInProgressRootPingedLanes = NoLanes;
- workInProgressRootConcurrentErrors = null;
- workInProgressRootRecoverableErrors = null;
- finishQueueingConcurrentUpdates();
- {
- ReactStrictModeWarnings.discardPendingWarnings();
- }
- return rootWorkInProgress;
- }
- function handleError(root, thrownValue) {
- do {
- var erroredWork = workInProgress;
- try {
- // Reset module-level state that was set during the render phase.
- resetContextDependencies();
- resetHooksAfterThrow();
- resetCurrentFiber(); // TODO: I found and added this missing line while investigating a
- // separate issue. Write a regression test using string refs.
- ReactCurrentOwner$2.current = null;
- if (erroredWork === null || erroredWork.return === null) {
- // Expected to be working on a non-root fiber. This is a fatal error
- // because there's no ancestor that can handle it; the root is
- // supposed to capture all errors that weren't caught by an error
- // boundary.
- workInProgressRootExitStatus = RootFatalErrored;
- workInProgressRootFatalError = thrownValue; // Set `workInProgress` to null. This represents advancing to the next
- // sibling, or the parent if there are no siblings. But since the root
- // has no siblings nor a parent, we set it to null. Usually this is
- // handled by `completeUnitOfWork` or `unwindWork`, but since we're
- // intentionally not calling those, we need set it here.
- // TODO: Consider calling `unwindWork` to pop the contexts.
- workInProgress = null;
- return;
- }
- if (enableProfilerTimer && erroredWork.mode & ProfileMode) {
- // Record the time spent rendering before an error was thrown. This
- // avoids inaccurate Profiler durations in the case of a
- // suspended render.
- stopProfilerTimerIfRunningAndRecordDelta(erroredWork, true);
- }
- if (enableSchedulingProfiler) {
- markComponentRenderStopped();
- if (thrownValue !== null && typeof thrownValue === 'object' && typeof thrownValue.then === 'function') {
- var wakeable = thrownValue;
- markComponentSuspended(erroredWork, wakeable, workInProgressRootRenderLanes);
- } else {
- markComponentErrored(erroredWork, thrownValue, workInProgressRootRenderLanes);
- }
- }
- throwException(root, erroredWork.return, erroredWork, thrownValue, workInProgressRootRenderLanes);
- completeUnitOfWork(erroredWork);
- } catch (yetAnotherThrownValue) {
- // Something in the return path also threw.
- thrownValue = yetAnotherThrownValue;
- if (workInProgress === erroredWork && erroredWork !== null) {
- // If this boundary has already errored, then we had trouble processing
- // the error. Bubble it to the next boundary.
- erroredWork = erroredWork.return;
- workInProgress = erroredWork;
- } else {
- erroredWork = workInProgress;
- }
- continue;
- } // Return to the normal work loop.
- return;
- } while (true);
- }
- function pushDispatcher() {
- var prevDispatcher = ReactCurrentDispatcher$2.current;
- ReactCurrentDispatcher$2.current = ContextOnlyDispatcher;
- if (prevDispatcher === null) {
- // The React isomorphic package does not include a default dispatcher.
- // Instead the first renderer will lazily attach one, in order to give
- // nicer error messages.
- return ContextOnlyDispatcher;
- } else {
- return prevDispatcher;
- }
- }
- function popDispatcher(prevDispatcher) {
- ReactCurrentDispatcher$2.current = prevDispatcher;
- }
- function markCommitTimeOfFallback() {
- globalMostRecentFallbackTime = now();
- }
- function markSkippedUpdateLanes(lane) {
- workInProgressRootSkippedLanes = mergeLanes(lane, workInProgressRootSkippedLanes);
- }
- function renderDidSuspend() {
- if (workInProgressRootExitStatus === RootInProgress) {
- workInProgressRootExitStatus = RootSuspended;
- }
- }
- function renderDidSuspendDelayIfPossible() {
- if (workInProgressRootExitStatus === RootInProgress || workInProgressRootExitStatus === RootSuspended || workInProgressRootExitStatus === RootErrored) {
- workInProgressRootExitStatus = RootSuspendedWithDelay;
- } // Check if there are updates that we skipped tree that might have unblocked
- // this render.
- if (workInProgressRoot !== null && (includesNonIdleWork(workInProgressRootSkippedLanes) || includesNonIdleWork(workInProgressRootInterleavedUpdatedLanes))) {
- // Mark the current render as suspended so that we switch to working on
- // the updates that were skipped. Usually we only suspend at the end of
- // the render phase.
- // TODO: We should probably always mark the root as suspended immediately
- // (inside this function), since by suspending at the end of the render
- // phase introduces a potential mistake where we suspend lanes that were
- // pinged or updated while we were rendering.
- markRootSuspended$1(workInProgressRoot, workInProgressRootRenderLanes);
- }
- }
- function renderDidError(error) {
- if (workInProgressRootExitStatus !== RootSuspendedWithDelay) {
- workInProgressRootExitStatus = RootErrored;
- }
- if (workInProgressRootConcurrentErrors === null) {
- workInProgressRootConcurrentErrors = [error];
- } else {
- workInProgressRootConcurrentErrors.push(error);
- }
- } // Called during render to determine if anything has suspended.
- // Returns false if we're not sure.
- function renderHasNotSuspendedYet() {
- // If something errored or completed, we can't really be sure,
- // so those are false.
- return workInProgressRootExitStatus === RootInProgress;
- }
- function renderRootSync(root, lanes) {
- var prevExecutionContext = executionContext;
- executionContext |= RenderContext;
- var prevDispatcher = pushDispatcher(); // If the root or lanes have changed, throw out the existing stack
- // and prepare a fresh one. Otherwise we'll continue where we left off.
- if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) {
- {
- if (isDevToolsPresent) {
- var memoizedUpdaters = root.memoizedUpdaters;
- if (memoizedUpdaters.size > 0) {
- restorePendingUpdaters(root, workInProgressRootRenderLanes);
- memoizedUpdaters.clear();
- } // At this point, move Fibers that scheduled the upcoming work from the Map to the Set.
- // If we bailout on this work, we'll move them back (like above).
- // It's important to move them now in case the work spawns more work at the same priority with different updaters.
- // That way we can keep the current update and future updates separate.
- movePendingFibersToMemoized(root, lanes);
- }
- }
- workInProgressTransitions = getTransitionsForLanes();
- prepareFreshStack(root, lanes);
- }
- {
- markRenderStarted(lanes);
- }
- do {
- try {
- workLoopSync();
- break;
- } catch (thrownValue) {
- handleError(root, thrownValue);
- }
- } while (true);
- resetContextDependencies();
- executionContext = prevExecutionContext;
- popDispatcher(prevDispatcher);
- if (workInProgress !== null) {
- // This is a sync render, so we should have finished the whole tree.
- throw new Error('Cannot commit an incomplete root. This error is likely caused by a ' + 'bug in React. Please file an issue.');
- }
- {
- markRenderStopped();
- } // Set this to null to indicate there's no in-progress render.
- workInProgressRoot = null;
- workInProgressRootRenderLanes = NoLanes;
- return workInProgressRootExitStatus;
- } // The work loop is an extremely hot path. Tell Closure not to inline it.
- /** @noinline */
- function workLoopSync() {
- // Already timed out, so perform work without checking if we need to yield.
- while (workInProgress !== null) {
- performUnitOfWork(workInProgress);
- }
- }
- function renderRootConcurrent(root, lanes) {
- var prevExecutionContext = executionContext;
- executionContext |= RenderContext;
- var prevDispatcher = pushDispatcher(); // If the root or lanes have changed, throw out the existing stack
- // and prepare a fresh one. Otherwise we'll continue where we left off.
- if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) {
- {
- if (isDevToolsPresent) {
- var memoizedUpdaters = root.memoizedUpdaters;
- if (memoizedUpdaters.size > 0) {
- restorePendingUpdaters(root, workInProgressRootRenderLanes);
- memoizedUpdaters.clear();
- } // At this point, move Fibers that scheduled the upcoming work from the Map to the Set.
- // If we bailout on this work, we'll move them back (like above).
- // It's important to move them now in case the work spawns more work at the same priority with different updaters.
- // That way we can keep the current update and future updates separate.
- movePendingFibersToMemoized(root, lanes);
- }
- }
- workInProgressTransitions = getTransitionsForLanes();
- resetRenderTimer();
- prepareFreshStack(root, lanes);
- }
- {
- markRenderStarted(lanes);
- }
- do {
- try {
- workLoopConcurrent();
- break;
- } catch (thrownValue) {
- handleError(root, thrownValue);
- }
- } while (true);
- resetContextDependencies();
- popDispatcher(prevDispatcher);
- executionContext = prevExecutionContext;
- if (workInProgress !== null) {
- // Still work remaining.
- {
- markRenderYielded();
- }
- return RootInProgress;
- } else {
- // Completed the tree.
- {
- markRenderStopped();
- } // Set this to null to indicate there's no in-progress render.
- workInProgressRoot = null;
- workInProgressRootRenderLanes = NoLanes; // Return the final exit status.
- return workInProgressRootExitStatus;
- }
- }
- /** @noinline */
- function workLoopConcurrent() {
- // Perform work until Scheduler asks us to yield
- while (workInProgress !== null && !shouldYield()) {
- performUnitOfWork(workInProgress);
- }
- }
- function performUnitOfWork(unitOfWork) {
- // The current, flushed, state of this fiber is the alternate. Ideally
- // nothing should rely on this, but relying on it here means that we don't
- // need an additional field on the work in progress.
- var current = unitOfWork.alternate;
- setCurrentFiber(unitOfWork);
- var next;
- if ((unitOfWork.mode & ProfileMode) !== NoMode) {
- startProfilerTimer(unitOfWork);
- next = beginWork$1(current, unitOfWork, subtreeRenderLanes);
- stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, true);
- } else {
- next = beginWork$1(current, unitOfWork, subtreeRenderLanes);
- }
- resetCurrentFiber();
- unitOfWork.memoizedProps = unitOfWork.pendingProps;
- if (next === null) {
- // If this doesn't spawn new work, complete the current work.
- completeUnitOfWork(unitOfWork);
- } else {
- workInProgress = next;
- }
- ReactCurrentOwner$2.current = null;
- }
- function completeUnitOfWork(unitOfWork) {
- // Attempt to complete the current unit of work, then move to the next
- // sibling. If there are no more siblings, return to the parent fiber.
- var completedWork = unitOfWork;
- do {
- // The current, flushed, state of this fiber is the alternate. Ideally
- // nothing should rely on this, but relying on it here means that we don't
- // need an additional field on the work in progress.
- var current = completedWork.alternate;
- var returnFiber = completedWork.return; // Check if the work completed or if something threw.
- if ((completedWork.flags & Incomplete) === NoFlags) {
- setCurrentFiber(completedWork);
- var next = void 0;
- if ((completedWork.mode & ProfileMode) === NoMode) {
- next = completeWork(current, completedWork, subtreeRenderLanes);
- } else {
- startProfilerTimer(completedWork);
- next = completeWork(current, completedWork, subtreeRenderLanes); // Update render duration assuming we didn't error.
- stopProfilerTimerIfRunningAndRecordDelta(completedWork, false);
- }
- resetCurrentFiber();
- if (next !== null) {
- // Completing this fiber spawned new work. Work on that next.
- workInProgress = next;
- return;
- }
- } else {
- // This fiber did not complete because something threw. Pop values off
- // the stack without entering the complete phase. If this is a boundary,
- // capture values if possible.
- var _next = unwindWork(current, completedWork); // Because this fiber did not complete, don't reset its lanes.
- if (_next !== null) {
- // If completing this work spawned new work, do that next. We'll come
- // back here again.
- // Since we're restarting, remove anything that is not a host effect
- // from the effect tag.
- _next.flags &= HostEffectMask;
- workInProgress = _next;
- return;
- }
- if ((completedWork.mode & ProfileMode) !== NoMode) {
- // Record the render duration for the fiber that errored.
- stopProfilerTimerIfRunningAndRecordDelta(completedWork, false); // Include the time spent working on failed children before continuing.
- var actualDuration = completedWork.actualDuration;
- var child = completedWork.child;
- while (child !== null) {
- actualDuration += child.actualDuration;
- child = child.sibling;
- }
- completedWork.actualDuration = actualDuration;
- }
- if (returnFiber !== null) {
- // Mark the parent fiber as incomplete and clear its subtree flags.
- returnFiber.flags |= Incomplete;
- returnFiber.subtreeFlags = NoFlags;
- returnFiber.deletions = null;
- } else {
- // We've unwound all the way to the root.
- workInProgressRootExitStatus = RootDidNotComplete;
- workInProgress = null;
- return;
- }
- }
- var siblingFiber = completedWork.sibling;
- if (siblingFiber !== null) {
- // If there is more work to do in this returnFiber, do that next.
- workInProgress = siblingFiber;
- return;
- } // Otherwise, return to the parent
- completedWork = returnFiber; // Update the next thing we're working on in case something throws.
- workInProgress = completedWork;
- } while (completedWork !== null); // We've reached the root.
- if (workInProgressRootExitStatus === RootInProgress) {
- workInProgressRootExitStatus = RootCompleted;
- }
- }
- function commitRoot(root, recoverableErrors, transitions) {
- // TODO: This no longer makes any sense. We already wrap the mutation and
- // layout phases. Should be able to remove.
- var previousUpdateLanePriority = getCurrentUpdatePriority();
- var prevTransition = ReactCurrentBatchConfig$3.transition;
- try {
- ReactCurrentBatchConfig$3.transition = null;
- setCurrentUpdatePriority(DiscreteEventPriority);
- commitRootImpl(root, recoverableErrors, transitions, previousUpdateLanePriority);
- } finally {
- ReactCurrentBatchConfig$3.transition = prevTransition;
- setCurrentUpdatePriority(previousUpdateLanePriority);
- }
- return null;
- }
- function commitRootImpl(root, recoverableErrors, transitions, renderPriorityLevel) {
- do {
- // `flushPassiveEffects` will call `flushSyncUpdateQueue` at the end, which
- // means `flushPassiveEffects` will sometimes result in additional
- // passive effects. So we need to keep flushing in a loop until there are
- // no more pending effects.
- // TODO: Might be better if `flushPassiveEffects` did not automatically
- // flush synchronous work at the end, to avoid factoring hazards like this.
- flushPassiveEffects();
- } while (rootWithPendingPassiveEffects !== null);
- flushRenderPhaseStrictModeWarningsInDEV();
- if ((executionContext & (RenderContext | CommitContext)) !== NoContext) {
- throw new Error('Should not already be working.');
- }
- var finishedWork = root.finishedWork;
- var lanes = root.finishedLanes;
- {
- markCommitStarted(lanes);
- }
- if (finishedWork === null) {
- {
- markCommitStopped();
- }
- return null;
- } else {
- {
- if (lanes === NoLanes) {
- error('root.finishedLanes should not be empty during a commit. This is a ' + 'bug in React.');
- }
- }
- }
- root.finishedWork = null;
- root.finishedLanes = NoLanes;
- if (finishedWork === root.current) {
- throw new Error('Cannot commit the same tree as before. This error is likely caused by ' + 'a bug in React. Please file an issue.');
- } // commitRoot never returns a continuation; it always finishes synchronously.
- // So we can clear these now to allow a new callback to be scheduled.
- root.callbackNode = null;
- root.callbackPriority = NoLane; // Update the first and last pending times on this root. The new first
- // pending time is whatever is left on the root fiber.
- var remainingLanes = mergeLanes(finishedWork.lanes, finishedWork.childLanes);
- markRootFinished(root, remainingLanes);
- if (root === workInProgressRoot) {
- // We can reset these now that they are finished.
- workInProgressRoot = null;
- workInProgress = null;
- workInProgressRootRenderLanes = NoLanes;
- } // If there are pending passive effects, schedule a callback to process them.
- // Do this as early as possible, so it is queued before anything else that
- // might get scheduled in the commit phase. (See #16714.)
- // TODO: Delete all other places that schedule the passive effect callback
- // They're redundant.
- if ((finishedWork.subtreeFlags & PassiveMask) !== NoFlags || (finishedWork.flags & PassiveMask) !== NoFlags) {
- if (!rootDoesHavePassiveEffects) {
- rootDoesHavePassiveEffects = true;
- // to store it in pendingPassiveTransitions until they get processed
- // We need to pass this through as an argument to commitRoot
- // because workInProgressTransitions might have changed between
- // the previous render and commit if we throttle the commit
- // with setTimeout
- pendingPassiveTransitions = transitions;
- scheduleCallback$1(NormalPriority, function () {
- flushPassiveEffects(); // This render triggered passive effects: release the root cache pool
- // *after* passive effects fire to avoid freeing a cache pool that may
- // be referenced by a node in the tree (HostRoot, Cache boundary etc)
- return null;
- });
- }
- } // Check if there are any effects in the whole tree.
- // TODO: This is left over from the effect list implementation, where we had
- // to check for the existence of `firstEffect` to satisfy Flow. I think the
- // only other reason this optimization exists is because it affects profiling.
- // Reconsider whether this is necessary.
- var subtreeHasEffects = (finishedWork.subtreeFlags & (BeforeMutationMask | MutationMask | LayoutMask | PassiveMask)) !== NoFlags;
- var rootHasEffect = (finishedWork.flags & (BeforeMutationMask | MutationMask | LayoutMask | PassiveMask)) !== NoFlags;
- if (subtreeHasEffects || rootHasEffect) {
- var prevTransition = ReactCurrentBatchConfig$3.transition;
- ReactCurrentBatchConfig$3.transition = null;
- var previousPriority = getCurrentUpdatePriority();
- setCurrentUpdatePriority(DiscreteEventPriority);
- var prevExecutionContext = executionContext;
- executionContext |= CommitContext; // Reset this to null before calling lifecycles
- ReactCurrentOwner$2.current = null; // The commit phase is broken into several sub-phases. We do a separate pass
- // of the effect list for each phase: all mutation effects come before all
- // layout effects, and so on.
- // The first phase a "before mutation" phase. We use this phase to read the
- // state of the host tree right before we mutate it. This is where
- // getSnapshotBeforeUpdate is called.
- var shouldFireAfterActiveInstanceBlur = commitBeforeMutationEffects(root, finishedWork);
- {
- // Mark the current commit time to be shared by all Profilers in this
- // batch. This enables them to be grouped later.
- recordCommitTime();
- }
- commitMutationEffects(root, finishedWork, lanes);
- resetAfterCommit(root.containerInfo); // The work-in-progress tree is now the current tree. This must come after
- // the mutation phase, so that the previous tree is still current during
- // componentWillUnmount, but before the layout phase, so that the finished
- // work is current during componentDidMount/Update.
- root.current = finishedWork; // The next phase is the layout phase, where we call effects that read
- {
- markLayoutEffectsStarted(lanes);
- }
- commitLayoutEffects(finishedWork, root, lanes);
- {
- markLayoutEffectsStopped();
- }
- // opportunity to paint.
- requestPaint();
- executionContext = prevExecutionContext; // Reset the priority to the previous non-sync value.
- setCurrentUpdatePriority(previousPriority);
- ReactCurrentBatchConfig$3.transition = prevTransition;
- } else {
- // No effects.
- root.current = finishedWork; // Measure these anyway so the flamegraph explicitly shows that there were
- // no effects.
- // TODO: Maybe there's a better way to report this.
- {
- recordCommitTime();
- }
- }
- var rootDidHavePassiveEffects = rootDoesHavePassiveEffects;
- if (rootDoesHavePassiveEffects) {
- // This commit has passive effects. Stash a reference to them. But don't
- // schedule a callback until after flushing layout work.
- rootDoesHavePassiveEffects = false;
- rootWithPendingPassiveEffects = root;
- pendingPassiveEffectsLanes = lanes;
- } else {
- {
- nestedPassiveUpdateCount = 0;
- rootWithPassiveNestedUpdates = null;
- }
- } // Read this again, since an effect might have updated it
- remainingLanes = root.pendingLanes; // Check if there's remaining work on this root
- // TODO: This is part of the `componentDidCatch` implementation. Its purpose
- // is to detect whether something might have called setState inside
- // `componentDidCatch`. The mechanism is known to be flawed because `setState`
- // inside `componentDidCatch` is itself flawed — that's why we recommend
- // `getDerivedStateFromError` instead. However, it could be improved by
- // checking if remainingLanes includes Sync work, instead of whether there's
- // any work remaining at all (which would also include stuff like Suspense
- // retries or transitions). It's been like this for a while, though, so fixing
- // it probably isn't that urgent.
- if (remainingLanes === NoLanes) {
- // If there's no remaining work, we can clear the set of already failed
- // error boundaries.
- legacyErrorBoundariesThatAlreadyFailed = null;
- }
- {
- if (!rootDidHavePassiveEffects) {
- commitDoubleInvokeEffectsInDEV(root.current, false);
- }
- }
- onCommitRoot(finishedWork.stateNode, renderPriorityLevel);
- {
- if (isDevToolsPresent) {
- root.memoizedUpdaters.clear();
- }
- }
- {
- onCommitRoot$1();
- } // Always call this before exiting `commitRoot`, to ensure that any
- // additional work on this root is scheduled.
- ensureRootIsScheduled(root, now());
- if (recoverableErrors !== null) {
- // There were errors during this render, but recovered from them without
- // needing to surface it to the UI. We log them here.
- var onRecoverableError = root.onRecoverableError;
- for (var i = 0; i < recoverableErrors.length; i++) {
- var recoverableError = recoverableErrors[i];
- var componentStack = recoverableError.stack;
- var digest = recoverableError.digest;
- onRecoverableError(recoverableError.value, {
- componentStack: componentStack,
- digest: digest
- });
- }
- }
- if (hasUncaughtError) {
- hasUncaughtError = false;
- var error$1 = firstUncaughtError;
- firstUncaughtError = null;
- throw error$1;
- } // If the passive effects are the result of a discrete render, flush them
- // synchronously at the end of the current task so that the result is
- // immediately observable. Otherwise, we assume that they are not
- // order-dependent and do not need to be observed by external systems, so we
- // can wait until after paint.
- // TODO: We can optimize this by not scheduling the callback earlier. Since we
- // currently schedule the callback in multiple places, will wait until those
- // are consolidated.
- if (includesSomeLane(pendingPassiveEffectsLanes, SyncLane) && root.tag !== LegacyRoot) {
- flushPassiveEffects();
- } // Read this again, since a passive effect might have updated it
- remainingLanes = root.pendingLanes;
- if (includesSomeLane(remainingLanes, SyncLane)) {
- {
- markNestedUpdateScheduled();
- } // Count the number of times the root synchronously re-renders without
- // finishing. If there are too many, it indicates an infinite update loop.
- if (root === rootWithNestedUpdates) {
- nestedUpdateCount++;
- } else {
- nestedUpdateCount = 0;
- rootWithNestedUpdates = root;
- }
- } else {
- nestedUpdateCount = 0;
- } // If layout work was scheduled, flush it now.
- flushSyncCallbacks();
- {
- markCommitStopped();
- }
- return null;
- }
- function flushPassiveEffects() {
- // Returns whether passive effects were flushed.
- // TODO: Combine this check with the one in flushPassiveEFfectsImpl. We should
- // probably just combine the two functions. I believe they were only separate
- // in the first place because we used to wrap it with
- // `Scheduler.runWithPriority`, which accepts a function. But now we track the
- // priority within React itself, so we can mutate the variable directly.
- if (rootWithPendingPassiveEffects !== null) {
- var renderPriority = lanesToEventPriority(pendingPassiveEffectsLanes);
- var priority = lowerEventPriority(DefaultEventPriority, renderPriority);
- var prevTransition = ReactCurrentBatchConfig$3.transition;
- var previousPriority = getCurrentUpdatePriority();
- try {
- ReactCurrentBatchConfig$3.transition = null;
- setCurrentUpdatePriority(priority);
- return flushPassiveEffectsImpl();
- } finally {
- setCurrentUpdatePriority(previousPriority);
- ReactCurrentBatchConfig$3.transition = prevTransition; // Once passive effects have run for the tree - giving components a
- }
- }
- return false;
- }
- function enqueuePendingPassiveProfilerEffect(fiber) {
- {
- pendingPassiveProfilerEffects.push(fiber);
- if (!rootDoesHavePassiveEffects) {
- rootDoesHavePassiveEffects = true;
- scheduleCallback$1(NormalPriority, function () {
- flushPassiveEffects();
- return null;
- });
- }
- }
- }
- function flushPassiveEffectsImpl() {
- if (rootWithPendingPassiveEffects === null) {
- return false;
- } // Cache and clear the transitions flag
- var transitions = pendingPassiveTransitions;
- pendingPassiveTransitions = null;
- var root = rootWithPendingPassiveEffects;
- var lanes = pendingPassiveEffectsLanes;
- rootWithPendingPassiveEffects = null; // TODO: This is sometimes out of sync with rootWithPendingPassiveEffects.
- // Figure out why and fix it. It's not causing any known issues (probably
- // because it's only used for profiling), but it's a refactor hazard.
- pendingPassiveEffectsLanes = NoLanes;
- if ((executionContext & (RenderContext | CommitContext)) !== NoContext) {
- throw new Error('Cannot flush passive effects while already rendering.');
- }
- {
- isFlushingPassiveEffects = true;
- didScheduleUpdateDuringPassiveEffects = false;
- }
- {
- markPassiveEffectsStarted(lanes);
- }
- var prevExecutionContext = executionContext;
- executionContext |= CommitContext;
- commitPassiveUnmountEffects(root.current);
- commitPassiveMountEffects(root, root.current, lanes, transitions); // TODO: Move to commitPassiveMountEffects
- {
- var profilerEffects = pendingPassiveProfilerEffects;
- pendingPassiveProfilerEffects = [];
- for (var i = 0; i < profilerEffects.length; i++) {
- var _fiber = profilerEffects[i];
- commitPassiveEffectDurations(root, _fiber);
- }
- }
- {
- markPassiveEffectsStopped();
- }
- {
- commitDoubleInvokeEffectsInDEV(root.current, true);
- }
- executionContext = prevExecutionContext;
- flushSyncCallbacks();
- {
- // If additional passive effects were scheduled, increment a counter. If this
- // exceeds the limit, we'll fire a warning.
- if (didScheduleUpdateDuringPassiveEffects) {
- if (root === rootWithPassiveNestedUpdates) {
- nestedPassiveUpdateCount++;
- } else {
- nestedPassiveUpdateCount = 0;
- rootWithPassiveNestedUpdates = root;
- }
- } else {
- nestedPassiveUpdateCount = 0;
- }
- isFlushingPassiveEffects = false;
- didScheduleUpdateDuringPassiveEffects = false;
- } // TODO: Move to commitPassiveMountEffects
- onPostCommitRoot(root);
- {
- var stateNode = root.current.stateNode;
- stateNode.effectDuration = 0;
- stateNode.passiveEffectDuration = 0;
- }
- return true;
- }
- function isAlreadyFailedLegacyErrorBoundary(instance) {
- return legacyErrorBoundariesThatAlreadyFailed !== null && legacyErrorBoundariesThatAlreadyFailed.has(instance);
- }
- function markLegacyErrorBoundaryAsFailed(instance) {
- if (legacyErrorBoundariesThatAlreadyFailed === null) {
- legacyErrorBoundariesThatAlreadyFailed = new Set([instance]);
- } else {
- legacyErrorBoundariesThatAlreadyFailed.add(instance);
- }
- }
- function prepareToThrowUncaughtError(error) {
- if (!hasUncaughtError) {
- hasUncaughtError = true;
- firstUncaughtError = error;
- }
- }
- var onUncaughtError = prepareToThrowUncaughtError;
- function captureCommitPhaseErrorOnRoot(rootFiber, sourceFiber, error) {
- var errorInfo = createCapturedValueAtFiber(error, sourceFiber);
- var update = createRootErrorUpdate(rootFiber, errorInfo, SyncLane);
- var root = enqueueUpdate(rootFiber, update, SyncLane);
- var eventTime = requestEventTime();
- if (root !== null) {
- markRootUpdated(root, SyncLane, eventTime);
- ensureRootIsScheduled(root, eventTime);
- }
- }
- function captureCommitPhaseError(sourceFiber, nearestMountedAncestor, error$1) {
- {
- reportUncaughtErrorInDEV(error$1);
- setIsRunningInsertionEffect(false);
- }
- if (sourceFiber.tag === HostRoot) {
- // Error was thrown at the root. There is no parent, so the root
- // itself should capture it.
- captureCommitPhaseErrorOnRoot(sourceFiber, sourceFiber, error$1);
- return;
- }
- var fiber = null;
- {
- fiber = nearestMountedAncestor;
- }
- while (fiber !== null) {
- if (fiber.tag === HostRoot) {
- captureCommitPhaseErrorOnRoot(fiber, sourceFiber, error$1);
- return;
- } else if (fiber.tag === ClassComponent) {
- var ctor = fiber.type;
- var instance = fiber.stateNode;
- if (typeof ctor.getDerivedStateFromError === 'function' || typeof instance.componentDidCatch === 'function' && !isAlreadyFailedLegacyErrorBoundary(instance)) {
- var errorInfo = createCapturedValueAtFiber(error$1, sourceFiber);
- var update = createClassErrorUpdate(fiber, errorInfo, SyncLane);
- var root = enqueueUpdate(fiber, update, SyncLane);
- var eventTime = requestEventTime();
- if (root !== null) {
- markRootUpdated(root, SyncLane, eventTime);
- ensureRootIsScheduled(root, eventTime);
- }
- return;
- }
- }
- fiber = fiber.return;
- }
- {
- // TODO: Until we re-land skipUnmountedBoundaries (see #20147), this warning
- // will fire for errors that are thrown by destroy functions inside deleted
- // trees. What it should instead do is propagate the error to the parent of
- // the deleted tree. In the meantime, do not add this warning to the
- // allowlist; this is only for our internal use.
- error('Internal React error: Attempted to capture a commit phase error ' + 'inside a detached tree. This indicates a bug in React. Likely ' + 'causes include deleting the same fiber more than once, committing an ' + 'already-finished tree, or an inconsistent return pointer.\n\n' + 'Error message:\n\n%s', error$1);
- }
- }
- function pingSuspendedRoot(root, wakeable, pingedLanes) {
- var pingCache = root.pingCache;
- if (pingCache !== null) {
- // The wakeable resolved, so we no longer need to memoize, because it will
- // never be thrown again.
- pingCache.delete(wakeable);
- }
- var eventTime = requestEventTime();
- markRootPinged(root, pingedLanes);
- warnIfSuspenseResolutionNotWrappedWithActDEV(root);
- if (workInProgressRoot === root && isSubsetOfLanes(workInProgressRootRenderLanes, pingedLanes)) {
- // Received a ping at the same priority level at which we're currently
- // rendering. We might want to restart this render. This should mirror
- // the logic of whether or not a root suspends once it completes.
- // TODO: If we're rendering sync either due to Sync, Batched or expired,
- // we should probably never restart.
- // If we're suspended with delay, or if it's a retry, we'll always suspend
- // so we can always restart.
- if (workInProgressRootExitStatus === RootSuspendedWithDelay || workInProgressRootExitStatus === RootSuspended && includesOnlyRetries(workInProgressRootRenderLanes) && now() - globalMostRecentFallbackTime < FALLBACK_THROTTLE_MS) {
- // Restart from the root.
- prepareFreshStack(root, NoLanes);
- } else {
- // Even though we can't restart right now, we might get an
- // opportunity later. So we mark this render as having a ping.
- workInProgressRootPingedLanes = mergeLanes(workInProgressRootPingedLanes, pingedLanes);
- }
- }
- ensureRootIsScheduled(root, eventTime);
- }
- function retryTimedOutBoundary(boundaryFiber, retryLane) {
- // The boundary fiber (a Suspense component or SuspenseList component)
- // previously was rendered in its fallback state. One of the promises that
- // suspended it has resolved, which means at least part of the tree was
- // likely unblocked. Try rendering again, at a new lanes.
- if (retryLane === NoLane) {
- // TODO: Assign this to `suspenseState.retryLane`? to avoid
- // unnecessary entanglement?
- retryLane = requestRetryLane(boundaryFiber);
- } // TODO: Special case idle priority?
- var eventTime = requestEventTime();
- var root = enqueueConcurrentRenderForLane(boundaryFiber, retryLane);
- if (root !== null) {
- markRootUpdated(root, retryLane, eventTime);
- ensureRootIsScheduled(root, eventTime);
- }
- }
- function retryDehydratedSuspenseBoundary(boundaryFiber) {
- var suspenseState = boundaryFiber.memoizedState;
- var retryLane = NoLane;
- if (suspenseState !== null) {
- retryLane = suspenseState.retryLane;
- }
- retryTimedOutBoundary(boundaryFiber, retryLane);
- }
- function resolveRetryWakeable(boundaryFiber, wakeable) {
- var retryLane = NoLane; // Default
- var retryCache;
- switch (boundaryFiber.tag) {
- case SuspenseComponent:
- retryCache = boundaryFiber.stateNode;
- var suspenseState = boundaryFiber.memoizedState;
- if (suspenseState !== null) {
- retryLane = suspenseState.retryLane;
- }
- break;
- case SuspenseListComponent:
- retryCache = boundaryFiber.stateNode;
- break;
- default:
- throw new Error('Pinged unknown suspense boundary type. ' + 'This is probably a bug in React.');
- }
- if (retryCache !== null) {
- // The wakeable resolved, so we no longer need to memoize, because it will
- // never be thrown again.
- retryCache.delete(wakeable);
- }
- retryTimedOutBoundary(boundaryFiber, retryLane);
- } // Computes the next Just Noticeable Difference (JND) boundary.
- // The theory is that a person can't tell the difference between small differences in time.
- // Therefore, if we wait a bit longer than necessary that won't translate to a noticeable
- // difference in the experience. However, waiting for longer might mean that we can avoid
- // showing an intermediate loading state. The longer we have already waited, the harder it
- // is to tell small differences in time. Therefore, the longer we've already waited,
- // the longer we can wait additionally. At some point we have to give up though.
- // We pick a train model where the next boundary commits at a consistent schedule.
- // These particular numbers are vague estimates. We expect to adjust them based on research.
- function jnd(timeElapsed) {
- return timeElapsed < 120 ? 120 : timeElapsed < 480 ? 480 : timeElapsed < 1080 ? 1080 : timeElapsed < 1920 ? 1920 : timeElapsed < 3000 ? 3000 : timeElapsed < 4320 ? 4320 : ceil(timeElapsed / 1960) * 1960;
- }
- function checkForNestedUpdates() {
- if (nestedUpdateCount > NESTED_UPDATE_LIMIT) {
- nestedUpdateCount = 0;
- rootWithNestedUpdates = null;
- throw new Error('Maximum update depth exceeded. This can happen when a component ' + 'repeatedly calls setState inside componentWillUpdate or ' + 'componentDidUpdate. React limits the number of nested updates to ' + 'prevent infinite loops.');
- }
- {
- if (nestedPassiveUpdateCount > NESTED_PASSIVE_UPDATE_LIMIT) {
- nestedPassiveUpdateCount = 0;
- rootWithPassiveNestedUpdates = null;
- error('Maximum update depth exceeded. This can happen when a component ' + "calls setState inside useEffect, but useEffect either doesn't " + 'have a dependency array, or one of the dependencies changes on ' + 'every render.');
- }
- }
- }
- function flushRenderPhaseStrictModeWarningsInDEV() {
- {
- ReactStrictModeWarnings.flushLegacyContextWarning();
- {
- ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings();
- }
- }
- }
- function commitDoubleInvokeEffectsInDEV(fiber, hasPassiveEffects) {
- {
- // TODO (StrictEffects) Should we set a marker on the root if it contains strict effects
- // so we don't traverse unnecessarily? similar to subtreeFlags but just at the root level.
- // Maybe not a big deal since this is DEV only behavior.
- setCurrentFiber(fiber);
- invokeEffectsInDev(fiber, MountLayoutDev, invokeLayoutEffectUnmountInDEV);
- if (hasPassiveEffects) {
- invokeEffectsInDev(fiber, MountPassiveDev, invokePassiveEffectUnmountInDEV);
- }
- invokeEffectsInDev(fiber, MountLayoutDev, invokeLayoutEffectMountInDEV);
- if (hasPassiveEffects) {
- invokeEffectsInDev(fiber, MountPassiveDev, invokePassiveEffectMountInDEV);
- }
- resetCurrentFiber();
- }
- }
- function invokeEffectsInDev(firstChild, fiberFlags, invokeEffectFn) {
- {
- // We don't need to re-check StrictEffectsMode here.
- // This function is only called if that check has already passed.
- var current = firstChild;
- var subtreeRoot = null;
- while (current !== null) {
- var primarySubtreeFlag = current.subtreeFlags & fiberFlags;
- if (current !== subtreeRoot && current.child !== null && primarySubtreeFlag !== NoFlags) {
- current = current.child;
- } else {
- if ((current.flags & fiberFlags) !== NoFlags) {
- invokeEffectFn(current);
- }
- if (current.sibling !== null) {
- current = current.sibling;
- } else {
- current = subtreeRoot = current.return;
- }
- }
- }
- }
- }
- var didWarnStateUpdateForNotYetMountedComponent = null;
- function warnAboutUpdateOnNotYetMountedFiberInDEV(fiber) {
- {
- if ((executionContext & RenderContext) !== NoContext) {
- // We let the other warning about render phase updates deal with this one.
- return;
- }
- if (!(fiber.mode & ConcurrentMode)) {
- return;
- }
- var tag = fiber.tag;
- if (tag !== IndeterminateComponent && tag !== HostRoot && tag !== ClassComponent && tag !== FunctionComponent && tag !== ForwardRef && tag !== MemoComponent && tag !== SimpleMemoComponent) {
- // Only warn for user-defined components, not internal ones like Suspense.
- return;
- } // We show the whole stack but dedupe on the top component's name because
- // the problematic code almost always lies inside that component.
- var componentName = getComponentNameFromFiber(fiber) || 'ReactComponent';
- if (didWarnStateUpdateForNotYetMountedComponent !== null) {
- if (didWarnStateUpdateForNotYetMountedComponent.has(componentName)) {
- return;
- }
- didWarnStateUpdateForNotYetMountedComponent.add(componentName);
- } else {
- didWarnStateUpdateForNotYetMountedComponent = new Set([componentName]);
- }
- var previousFiber = current;
- try {
- setCurrentFiber(fiber);
- error("Can't perform a React state update on a component that hasn't mounted yet. " + 'This indicates that you have a side-effect in your render function that ' + 'asynchronously later calls tries to update the component. Move this work to ' + 'useEffect instead.');
- } finally {
- if (previousFiber) {
- setCurrentFiber(fiber);
- } else {
- resetCurrentFiber();
- }
- }
- }
- }
- var beginWork$1;
- {
- var dummyFiber = null;
- beginWork$1 = function (current, unitOfWork, lanes) {
- // If a component throws an error, we replay it again in a synchronously
- // dispatched event, so that the debugger will treat it as an uncaught
- // error See ReactErrorUtils for more information.
- // Before entering the begin phase, copy the work-in-progress onto a dummy
- // fiber. If beginWork throws, we'll use this to reset the state.
- var originalWorkInProgressCopy = assignFiberPropertiesInDEV(dummyFiber, unitOfWork);
- try {
- return beginWork(current, unitOfWork, lanes);
- } catch (originalError) {
- if (didSuspendOrErrorWhileHydratingDEV() || originalError !== null && typeof originalError === 'object' && typeof originalError.then === 'function') {
- // Don't replay promises.
- // Don't replay errors if we are hydrating and have already suspended or handled an error
- throw originalError;
- } // Keep this code in sync with handleError; any changes here must have
- // corresponding changes there.
- resetContextDependencies();
- resetHooksAfterThrow(); // Don't reset current debug fiber, since we're about to work on the
- // same fiber again.
- // Unwind the failed stack frame
- unwindInterruptedWork(current, unitOfWork); // Restore the original properties of the fiber.
- assignFiberPropertiesInDEV(unitOfWork, originalWorkInProgressCopy);
- if (unitOfWork.mode & ProfileMode) {
- // Reset the profiler timer.
- startProfilerTimer(unitOfWork);
- } // Run beginWork again.
- invokeGuardedCallback(null, beginWork, null, current, unitOfWork, lanes);
- if (hasCaughtError()) {
- var replayError = clearCaughtError();
- if (typeof replayError === 'object' && replayError !== null && replayError._suppressLogging && typeof originalError === 'object' && originalError !== null && !originalError._suppressLogging) {
- // If suppressed, let the flag carry over to the original error which is the one we'll rethrow.
- originalError._suppressLogging = true;
- }
- } // We always throw the original error in case the second render pass is not idempotent.
- // This can happen if a memoized function or CommonJS module doesn't throw after first invocation.
- throw originalError;
- }
- };
- }
- var didWarnAboutUpdateInRender = false;
- var didWarnAboutUpdateInRenderForAnotherComponent;
- {
- didWarnAboutUpdateInRenderForAnotherComponent = new Set();
- }
- function warnAboutRenderPhaseUpdatesInDEV(fiber) {
- {
- if (isRendering && !getIsUpdatingOpaqueValueInRenderPhaseInDEV()) {
- switch (fiber.tag) {
- case FunctionComponent:
- case ForwardRef:
- case SimpleMemoComponent:
- {
- var renderingComponentName = workInProgress && getComponentNameFromFiber(workInProgress) || 'Unknown'; // Dedupe by the rendering component because it's the one that needs to be fixed.
- var dedupeKey = renderingComponentName;
- if (!didWarnAboutUpdateInRenderForAnotherComponent.has(dedupeKey)) {
- didWarnAboutUpdateInRenderForAnotherComponent.add(dedupeKey);
- var setStateComponentName = getComponentNameFromFiber(fiber) || 'Unknown';
- error('Cannot update a component (`%s`) while rendering a ' + 'different component (`%s`). To locate the bad setState() call inside `%s`, ' + 'follow the stack trace as described in https://reactjs.org/link/setstate-in-render', setStateComponentName, renderingComponentName, renderingComponentName);
- }
- break;
- }
- case ClassComponent:
- {
- if (!didWarnAboutUpdateInRender) {
- error('Cannot update during an existing state transition (such as ' + 'within `render`). Render methods should be a pure ' + 'function of props and state.');
- didWarnAboutUpdateInRender = true;
- }
- break;
- }
- }
- }
- }
- }
- function restorePendingUpdaters(root, lanes) {
- {
- if (isDevToolsPresent) {
- var memoizedUpdaters = root.memoizedUpdaters;
- memoizedUpdaters.forEach(function (schedulingFiber) {
- addFiberToLanesMap(root, schedulingFiber, lanes);
- }); // This function intentionally does not clear memoized updaters.
- // Those may still be relevant to the current commit
- // and a future one (e.g. Suspense).
- }
- }
- }
- var fakeActCallbackNode = {};
- function scheduleCallback$1(priorityLevel, callback) {
- {
- // If we're currently inside an `act` scope, bypass Scheduler and push to
- // the `act` queue instead.
- var actQueue = ReactCurrentActQueue$1.current;
- if (actQueue !== null) {
- actQueue.push(callback);
- return fakeActCallbackNode;
- } else {
- return scheduleCallback(priorityLevel, callback);
- }
- }
- }
- function cancelCallback$1(callbackNode) {
- if (callbackNode === fakeActCallbackNode) {
- return;
- } // In production, always call Scheduler. This function will be stripped out.
- return cancelCallback(callbackNode);
- }
- function shouldForceFlushFallbacksInDEV() {
- // Never force flush in production. This function should get stripped out.
- return ReactCurrentActQueue$1.current !== null;
- }
- function warnIfUpdatesNotWrappedWithActDEV(fiber) {
- {
- if (fiber.mode & ConcurrentMode) {
- if (!isConcurrentActEnvironment()) {
- // Not in an act environment. No need to warn.
- return;
- }
- } else {
- // Legacy mode has additional cases where we suppress a warning.
- if (!isLegacyActEnvironment()) {
- // Not in an act environment. No need to warn.
- return;
- }
- if (executionContext !== NoContext) {
- // Legacy mode doesn't warn if the update is batched, i.e.
- // batchedUpdates or flushSync.
- return;
- }
- if (fiber.tag !== FunctionComponent && fiber.tag !== ForwardRef && fiber.tag !== SimpleMemoComponent) {
- // For backwards compatibility with pre-hooks code, legacy mode only
- // warns for updates that originate from a hook.
- return;
- }
- }
- if (ReactCurrentActQueue$1.current === null) {
- var previousFiber = current;
- try {
- setCurrentFiber(fiber);
- error('An update to %s inside a test was not wrapped in act(...).\n\n' + 'When testing, code that causes React state updates should be ' + 'wrapped into act(...):\n\n' + 'act(() => {\n' + ' /* fire events that update state */\n' + '});\n' + '/* assert on the output */\n\n' + "This ensures that you're testing the behavior the user would see " + 'in the browser.' + ' Learn more at https://reactjs.org/link/wrap-tests-with-act', getComponentNameFromFiber(fiber));
- } finally {
- if (previousFiber) {
- setCurrentFiber(fiber);
- } else {
- resetCurrentFiber();
- }
- }
- }
- }
- }
- function warnIfSuspenseResolutionNotWrappedWithActDEV(root) {
- {
- if (root.tag !== LegacyRoot && isConcurrentActEnvironment() && ReactCurrentActQueue$1.current === null) {
- error('A suspended resource finished loading inside a test, but the event ' + 'was not wrapped in act(...).\n\n' + 'When testing, code that resolves suspended data should be wrapped ' + 'into act(...):\n\n' + 'act(() => {\n' + ' /* finish loading suspended data */\n' + '});\n' + '/* assert on the output */\n\n' + "This ensures that you're testing the behavior the user would see " + 'in the browser.' + ' Learn more at https://reactjs.org/link/wrap-tests-with-act');
- }
- }
- }
- function setIsRunningInsertionEffect(isRunning) {
- {
- isRunningInsertionEffect = isRunning;
- }
- }
- /* eslint-disable react-internal/prod-error-codes */
- var resolveFamily = null; // $FlowFixMe Flow gets confused by a WeakSet feature check below.
- var failedBoundaries = null;
- var setRefreshHandler = function (handler) {
- {
- resolveFamily = handler;
- }
- };
- function resolveFunctionForHotReloading(type) {
- {
- if (resolveFamily === null) {
- // Hot reloading is disabled.
- return type;
- }
- var family = resolveFamily(type);
- if (family === undefined) {
- return type;
- } // Use the latest known implementation.
- return family.current;
- }
- }
- function resolveClassForHotReloading(type) {
- // No implementation differences.
- return resolveFunctionForHotReloading(type);
- }
- function resolveForwardRefForHotReloading(type) {
- {
- if (resolveFamily === null) {
- // Hot reloading is disabled.
- return type;
- }
- var family = resolveFamily(type);
- if (family === undefined) {
- // Check if we're dealing with a real forwardRef. Don't want to crash early.
- if (type !== null && type !== undefined && typeof type.render === 'function') {
- // ForwardRef is special because its resolved .type is an object,
- // but it's possible that we only have its inner render function in the map.
- // If that inner render function is different, we'll build a new forwardRef type.
- var currentRender = resolveFunctionForHotReloading(type.render);
- if (type.render !== currentRender) {
- var syntheticType = {
- $$typeof: REACT_FORWARD_REF_TYPE,
- render: currentRender
- };
- if (type.displayName !== undefined) {
- syntheticType.displayName = type.displayName;
- }
- return syntheticType;
- }
- }
- return type;
- } // Use the latest known implementation.
- return family.current;
- }
- }
- function isCompatibleFamilyForHotReloading(fiber, element) {
- {
- if (resolveFamily === null) {
- // Hot reloading is disabled.
- return false;
- }
- var prevType = fiber.elementType;
- var nextType = element.type; // If we got here, we know types aren't === equal.
- var needsCompareFamilies = false;
- var $$typeofNextType = typeof nextType === 'object' && nextType !== null ? nextType.$$typeof : null;
- switch (fiber.tag) {
- case ClassComponent:
- {
- if (typeof nextType === 'function') {
- needsCompareFamilies = true;
- }
- break;
- }
- case FunctionComponent:
- {
- if (typeof nextType === 'function') {
- needsCompareFamilies = true;
- } else if ($$typeofNextType === REACT_LAZY_TYPE) {
- // We don't know the inner type yet.
- // We're going to assume that the lazy inner type is stable,
- // and so it is sufficient to avoid reconciling it away.
- // We're not going to unwrap or actually use the new lazy type.
- needsCompareFamilies = true;
- }
- break;
- }
- case ForwardRef:
- {
- if ($$typeofNextType === REACT_FORWARD_REF_TYPE) {
- needsCompareFamilies = true;
- } else if ($$typeofNextType === REACT_LAZY_TYPE) {
- needsCompareFamilies = true;
- }
- break;
- }
- case MemoComponent:
- case SimpleMemoComponent:
- {
- if ($$typeofNextType === REACT_MEMO_TYPE) {
- // TODO: if it was but can no longer be simple,
- // we shouldn't set this.
- needsCompareFamilies = true;
- } else if ($$typeofNextType === REACT_LAZY_TYPE) {
- needsCompareFamilies = true;
- }
- break;
- }
- default:
- return false;
- } // Check if both types have a family and it's the same one.
- if (needsCompareFamilies) {
- // Note: memo() and forwardRef() we'll compare outer rather than inner type.
- // This means both of them need to be registered to preserve state.
- // If we unwrapped and compared the inner types for wrappers instead,
- // then we would risk falsely saying two separate memo(Foo)
- // calls are equivalent because they wrap the same Foo function.
- var prevFamily = resolveFamily(prevType);
- if (prevFamily !== undefined && prevFamily === resolveFamily(nextType)) {
- return true;
- }
- }
- return false;
- }
- }
- function markFailedErrorBoundaryForHotReloading(fiber) {
- {
- if (resolveFamily === null) {
- // Hot reloading is disabled.
- return;
- }
- if (typeof WeakSet !== 'function') {
- return;
- }
- if (failedBoundaries === null) {
- failedBoundaries = new WeakSet();
- }
- failedBoundaries.add(fiber);
- }
- }
- var scheduleRefresh = function (root, update) {
- {
- if (resolveFamily === null) {
- // Hot reloading is disabled.
- return;
- }
- var staleFamilies = update.staleFamilies,
- updatedFamilies = update.updatedFamilies;
- flushPassiveEffects();
- flushSync(function () {
- scheduleFibersWithFamiliesRecursively(root.current, updatedFamilies, staleFamilies);
- });
- }
- };
- var scheduleRoot = function (root, element) {
- {
- if (root.context !== emptyContextObject) {
- // Super edge case: root has a legacy _renderSubtree context
- // but we don't know the parentComponent so we can't pass it.
- // Just ignore. We'll delete this with _renderSubtree code path later.
- return;
- }
- flushPassiveEffects();
- flushSync(function () {
- updateContainer(element, root, null, null);
- });
- }
- };
- function scheduleFibersWithFamiliesRecursively(fiber, updatedFamilies, staleFamilies) {
- {
- var alternate = fiber.alternate,
- child = fiber.child,
- sibling = fiber.sibling,
- tag = fiber.tag,
- type = fiber.type;
- var candidateType = null;
- switch (tag) {
- case FunctionComponent:
- case SimpleMemoComponent:
- case ClassComponent:
- candidateType = type;
- break;
- case ForwardRef:
- candidateType = type.render;
- break;
- }
- if (resolveFamily === null) {
- throw new Error('Expected resolveFamily to be set during hot reload.');
- }
- var needsRender = false;
- var needsRemount = false;
- if (candidateType !== null) {
- var family = resolveFamily(candidateType);
- if (family !== undefined) {
- if (staleFamilies.has(family)) {
- needsRemount = true;
- } else if (updatedFamilies.has(family)) {
- if (tag === ClassComponent) {
- needsRemount = true;
- } else {
- needsRender = true;
- }
- }
- }
- }
- if (failedBoundaries !== null) {
- if (failedBoundaries.has(fiber) || alternate !== null && failedBoundaries.has(alternate)) {
- needsRemount = true;
- }
- }
- if (needsRemount) {
- fiber._debugNeedsRemount = true;
- }
- if (needsRemount || needsRender) {
- var _root = enqueueConcurrentRenderForLane(fiber, SyncLane);
- if (_root !== null) {
- scheduleUpdateOnFiber(_root, fiber, SyncLane, NoTimestamp);
- }
- }
- if (child !== null && !needsRemount) {
- scheduleFibersWithFamiliesRecursively(child, updatedFamilies, staleFamilies);
- }
- if (sibling !== null) {
- scheduleFibersWithFamiliesRecursively(sibling, updatedFamilies, staleFamilies);
- }
- }
- }
- var findHostInstancesForRefresh = function (root, families) {
- {
- var hostInstances = new Set();
- var types = new Set(families.map(function (family) {
- return family.current;
- }));
- findHostInstancesForMatchingFibersRecursively(root.current, types, hostInstances);
- return hostInstances;
- }
- };
- function findHostInstancesForMatchingFibersRecursively(fiber, types, hostInstances) {
- {
- var child = fiber.child,
- sibling = fiber.sibling,
- tag = fiber.tag,
- type = fiber.type;
- var candidateType = null;
- switch (tag) {
- case FunctionComponent:
- case SimpleMemoComponent:
- case ClassComponent:
- candidateType = type;
- break;
- case ForwardRef:
- candidateType = type.render;
- break;
- }
- var didMatch = false;
- if (candidateType !== null) {
- if (types.has(candidateType)) {
- didMatch = true;
- }
- }
- if (didMatch) {
- // We have a match. This only drills down to the closest host components.
- // There's no need to search deeper because for the purpose of giving
- // visual feedback, "flashing" outermost parent rectangles is sufficient.
- findHostInstancesForFiberShallowly(fiber, hostInstances);
- } else {
- // If there's no match, maybe there will be one further down in the child tree.
- if (child !== null) {
- findHostInstancesForMatchingFibersRecursively(child, types, hostInstances);
- }
- }
- if (sibling !== null) {
- findHostInstancesForMatchingFibersRecursively(sibling, types, hostInstances);
- }
- }
- }
- function findHostInstancesForFiberShallowly(fiber, hostInstances) {
- {
- var foundHostInstances = findChildHostInstancesForFiberShallowly(fiber, hostInstances);
- if (foundHostInstances) {
- return;
- } // If we didn't find any host children, fallback to closest host parent.
- var node = fiber;
- while (true) {
- switch (node.tag) {
- case HostComponent:
- hostInstances.add(node.stateNode);
- return;
- case HostPortal:
- hostInstances.add(node.stateNode.containerInfo);
- return;
- case HostRoot:
- hostInstances.add(node.stateNode.containerInfo);
- return;
- }
- if (node.return === null) {
- throw new Error('Expected to reach root first.');
- }
- node = node.return;
- }
- }
- }
- function findChildHostInstancesForFiberShallowly(fiber, hostInstances) {
- {
- var node = fiber;
- var foundHostInstances = false;
- while (true) {
- if (node.tag === HostComponent) {
- // We got a match.
- foundHostInstances = true;
- hostInstances.add(node.stateNode); // There may still be more, so keep searching.
- } else if (node.child !== null) {
- node.child.return = node;
- node = node.child;
- continue;
- }
- if (node === fiber) {
- return foundHostInstances;
- }
- while (node.sibling === null) {
- if (node.return === null || node.return === fiber) {
- return foundHostInstances;
- }
- node = node.return;
- }
- node.sibling.return = node.return;
- node = node.sibling;
- }
- }
- return false;
- }
- var hasBadMapPolyfill;
- {
- hasBadMapPolyfill = false;
- try {
- var nonExtensibleObject = Object.preventExtensions({});
- /* eslint-disable no-new */
- new Map([[nonExtensibleObject, null]]);
- new Set([nonExtensibleObject]);
- /* eslint-enable no-new */
- } catch (e) {
- // TODO: Consider warning about bad polyfills
- hasBadMapPolyfill = true;
- }
- }
- function FiberNode(tag, pendingProps, key, mode) {
- // Instance
- this.tag = tag;
- this.key = key;
- this.elementType = null;
- this.type = null;
- this.stateNode = null; // Fiber
- this.return = null;
- this.child = null;
- this.sibling = null;
- this.index = 0;
- this.ref = null;
- this.pendingProps = pendingProps;
- this.memoizedProps = null;
- this.updateQueue = null;
- this.memoizedState = null;
- this.dependencies = null;
- this.mode = mode; // Effects
- this.flags = NoFlags;
- this.subtreeFlags = NoFlags;
- this.deletions = null;
- this.lanes = NoLanes;
- this.childLanes = NoLanes;
- this.alternate = null;
- {
- // Note: The following is done to avoid a v8 performance cliff.
- //
- // Initializing the fields below to smis and later updating them with
- // double values will cause Fibers to end up having separate shapes.
- // This behavior/bug has something to do with Object.preventExtension().
- // Fortunately this only impacts DEV builds.
- // Unfortunately it makes React unusably slow for some applications.
- // To work around this, initialize the fields below with doubles.
- //
- // Learn more about this here:
- // https://github.com/facebook/react/issues/14365
- // https://bugs.chromium.org/p/v8/issues/detail?id=8538
- this.actualDuration = Number.NaN;
- this.actualStartTime = Number.NaN;
- this.selfBaseDuration = Number.NaN;
- this.treeBaseDuration = Number.NaN; // It's okay to replace the initial doubles with smis after initialization.
- // This won't trigger the performance cliff mentioned above,
- // and it simplifies other profiler code (including DevTools).
- this.actualDuration = 0;
- this.actualStartTime = -1;
- this.selfBaseDuration = 0;
- this.treeBaseDuration = 0;
- }
- {
- // This isn't directly used but is handy for debugging internals:
- this._debugSource = null;
- this._debugOwner = null;
- this._debugNeedsRemount = false;
- this._debugHookTypes = null;
- if (!hasBadMapPolyfill && typeof Object.preventExtensions === 'function') {
- Object.preventExtensions(this);
- }
- }
- } // This is a constructor function, rather than a POJO constructor, still
- // please ensure we do the following:
- // 1) Nobody should add any instance methods on this. Instance methods can be
- // more difficult to predict when they get optimized and they are almost
- // never inlined properly in static compilers.
- // 2) Nobody should rely on `instanceof Fiber` for type testing. We should
- // always know when it is a fiber.
- // 3) We might want to experiment with using numeric keys since they are easier
- // to optimize in a non-JIT environment.
- // 4) We can easily go from a constructor to a createFiber object literal if that
- // is faster.
- // 5) It should be easy to port this to a C struct and keep a C implementation
- // compatible.
- var createFiber = function (tag, pendingProps, key, mode) {
- // $FlowFixMe: the shapes are exact here but Flow doesn't like constructors
- return new FiberNode(tag, pendingProps, key, mode);
- };
- function shouldConstruct$1(Component) {
- var prototype = Component.prototype;
- return !!(prototype && prototype.isReactComponent);
- }
- function isSimpleFunctionComponent(type) {
- return typeof type === 'function' && !shouldConstruct$1(type) && type.defaultProps === undefined;
- }
- function resolveLazyComponentTag(Component) {
- if (typeof Component === 'function') {
- return shouldConstruct$1(Component) ? ClassComponent : FunctionComponent;
- } else if (Component !== undefined && Component !== null) {
- var $$typeof = Component.$$typeof;
- if ($$typeof === REACT_FORWARD_REF_TYPE) {
- return ForwardRef;
- }
- if ($$typeof === REACT_MEMO_TYPE) {
- return MemoComponent;
- }
- }
- return IndeterminateComponent;
- } // This is used to create an alternate fiber to do work on.
- function createWorkInProgress(current, pendingProps) {
- var workInProgress = current.alternate;
- if (workInProgress === null) {
- // We use a double buffering pooling technique because we know that we'll
- // only ever need at most two versions of a tree. We pool the "other" unused
- // node that we're free to reuse. This is lazily created to avoid allocating
- // extra objects for things that are never updated. It also allow us to
- // reclaim the extra memory if needed.
- workInProgress = createFiber(current.tag, pendingProps, current.key, current.mode);
- workInProgress.elementType = current.elementType;
- workInProgress.type = current.type;
- workInProgress.stateNode = current.stateNode;
- {
- // DEV-only fields
- workInProgress._debugSource = current._debugSource;
- workInProgress._debugOwner = current._debugOwner;
- workInProgress._debugHookTypes = current._debugHookTypes;
- }
- workInProgress.alternate = current;
- current.alternate = workInProgress;
- } else {
- workInProgress.pendingProps = pendingProps; // Needed because Blocks store data on type.
- workInProgress.type = current.type; // We already have an alternate.
- // Reset the effect tag.
- workInProgress.flags = NoFlags; // The effects are no longer valid.
- workInProgress.subtreeFlags = NoFlags;
- workInProgress.deletions = null;
- {
- // We intentionally reset, rather than copy, actualDuration & actualStartTime.
- // This prevents time from endlessly accumulating in new commits.
- // This has the downside of resetting values for different priority renders,
- // But works for yielding (the common case) and should support resuming.
- workInProgress.actualDuration = 0;
- workInProgress.actualStartTime = -1;
- }
- } // Reset all effects except static ones.
- // Static effects are not specific to a render.
- workInProgress.flags = current.flags & StaticMask;
- workInProgress.childLanes = current.childLanes;
- workInProgress.lanes = current.lanes;
- workInProgress.child = current.child;
- workInProgress.memoizedProps = current.memoizedProps;
- workInProgress.memoizedState = current.memoizedState;
- workInProgress.updateQueue = current.updateQueue; // Clone the dependencies object. This is mutated during the render phase, so
- // it cannot be shared with the current fiber.
- var currentDependencies = current.dependencies;
- workInProgress.dependencies = currentDependencies === null ? null : {
- lanes: currentDependencies.lanes,
- firstContext: currentDependencies.firstContext
- }; // These will be overridden during the parent's reconciliation
- workInProgress.sibling = current.sibling;
- workInProgress.index = current.index;
- workInProgress.ref = current.ref;
- {
- workInProgress.selfBaseDuration = current.selfBaseDuration;
- workInProgress.treeBaseDuration = current.treeBaseDuration;
- }
- {
- workInProgress._debugNeedsRemount = current._debugNeedsRemount;
- switch (workInProgress.tag) {
- case IndeterminateComponent:
- case FunctionComponent:
- case SimpleMemoComponent:
- workInProgress.type = resolveFunctionForHotReloading(current.type);
- break;
- case ClassComponent:
- workInProgress.type = resolveClassForHotReloading(current.type);
- break;
- case ForwardRef:
- workInProgress.type = resolveForwardRefForHotReloading(current.type);
- break;
- }
- }
- return workInProgress;
- } // Used to reuse a Fiber for a second pass.
- function resetWorkInProgress(workInProgress, renderLanes) {
- // This resets the Fiber to what createFiber or createWorkInProgress would
- // have set the values to before during the first pass. Ideally this wouldn't
- // be necessary but unfortunately many code paths reads from the workInProgress
- // when they should be reading from current and writing to workInProgress.
- // We assume pendingProps, index, key, ref, return are still untouched to
- // avoid doing another reconciliation.
- // Reset the effect flags but keep any Placement tags, since that's something
- // that child fiber is setting, not the reconciliation.
- workInProgress.flags &= StaticMask | Placement; // The effects are no longer valid.
- var current = workInProgress.alternate;
- if (current === null) {
- // Reset to createFiber's initial values.
- workInProgress.childLanes = NoLanes;
- workInProgress.lanes = renderLanes;
- workInProgress.child = null;
- workInProgress.subtreeFlags = NoFlags;
- workInProgress.memoizedProps = null;
- workInProgress.memoizedState = null;
- workInProgress.updateQueue = null;
- workInProgress.dependencies = null;
- workInProgress.stateNode = null;
- {
- // Note: We don't reset the actualTime counts. It's useful to accumulate
- // actual time across multiple render passes.
- workInProgress.selfBaseDuration = 0;
- workInProgress.treeBaseDuration = 0;
- }
- } else {
- // Reset to the cloned values that createWorkInProgress would've.
- workInProgress.childLanes = current.childLanes;
- workInProgress.lanes = current.lanes;
- workInProgress.child = current.child;
- workInProgress.subtreeFlags = NoFlags;
- workInProgress.deletions = null;
- workInProgress.memoizedProps = current.memoizedProps;
- workInProgress.memoizedState = current.memoizedState;
- workInProgress.updateQueue = current.updateQueue; // Needed because Blocks store data on type.
- workInProgress.type = current.type; // Clone the dependencies object. This is mutated during the render phase, so
- // it cannot be shared with the current fiber.
- var currentDependencies = current.dependencies;
- workInProgress.dependencies = currentDependencies === null ? null : {
- lanes: currentDependencies.lanes,
- firstContext: currentDependencies.firstContext
- };
- {
- // Note: We don't reset the actualTime counts. It's useful to accumulate
- // actual time across multiple render passes.
- workInProgress.selfBaseDuration = current.selfBaseDuration;
- workInProgress.treeBaseDuration = current.treeBaseDuration;
- }
- }
- return workInProgress;
- }
- function createHostRootFiber(tag, isStrictMode, concurrentUpdatesByDefaultOverride) {
- var mode;
- if (tag === ConcurrentRoot) {
- mode = ConcurrentMode;
- if (isStrictMode === true) {
- mode |= StrictLegacyMode;
- {
- mode |= StrictEffectsMode;
- }
- }
- } else {
- mode = NoMode;
- }
- if (isDevToolsPresent) {
- // Always collect profile timings when DevTools are present.
- // This enables DevTools to start capturing timing at any point–
- // Without some nodes in the tree having empty base times.
- mode |= ProfileMode;
- }
- return createFiber(HostRoot, null, null, mode);
- }
- function createFiberFromTypeAndProps(type, // React$ElementType
- key, pendingProps, owner, mode, lanes) {
- var fiberTag = IndeterminateComponent; // The resolved type is set if we know what the final type will be. I.e. it's not lazy.
- var resolvedType = type;
- if (typeof type === 'function') {
- if (shouldConstruct$1(type)) {
- fiberTag = ClassComponent;
- {
- resolvedType = resolveClassForHotReloading(resolvedType);
- }
- } else {
- {
- resolvedType = resolveFunctionForHotReloading(resolvedType);
- }
- }
- } else if (typeof type === 'string') {
- fiberTag = HostComponent;
- } else {
- getTag: switch (type) {
- case REACT_FRAGMENT_TYPE:
- return createFiberFromFragment(pendingProps.children, mode, lanes, key);
- case REACT_STRICT_MODE_TYPE:
- fiberTag = Mode;
- mode |= StrictLegacyMode;
- if ((mode & ConcurrentMode) !== NoMode) {
- // Strict effects should never run on legacy roots
- mode |= StrictEffectsMode;
- }
- break;
- case REACT_PROFILER_TYPE:
- return createFiberFromProfiler(pendingProps, mode, lanes, key);
- case REACT_SUSPENSE_TYPE:
- return createFiberFromSuspense(pendingProps, mode, lanes, key);
- case REACT_SUSPENSE_LIST_TYPE:
- return createFiberFromSuspenseList(pendingProps, mode, lanes, key);
- case REACT_OFFSCREEN_TYPE:
- return createFiberFromOffscreen(pendingProps, mode, lanes, key);
- case REACT_LEGACY_HIDDEN_TYPE:
- // eslint-disable-next-line no-fallthrough
- case REACT_SCOPE_TYPE:
- // eslint-disable-next-line no-fallthrough
- case REACT_CACHE_TYPE:
- // eslint-disable-next-line no-fallthrough
- case REACT_TRACING_MARKER_TYPE:
- // eslint-disable-next-line no-fallthrough
- case REACT_DEBUG_TRACING_MODE_TYPE:
- // eslint-disable-next-line no-fallthrough
- default:
- {
- if (typeof type === 'object' && type !== null) {
- switch (type.$$typeof) {
- case REACT_PROVIDER_TYPE:
- fiberTag = ContextProvider;
- break getTag;
- case REACT_CONTEXT_TYPE:
- // This is a consumer
- fiberTag = ContextConsumer;
- break getTag;
- case REACT_FORWARD_REF_TYPE:
- fiberTag = ForwardRef;
- {
- resolvedType = resolveForwardRefForHotReloading(resolvedType);
- }
- break getTag;
- case REACT_MEMO_TYPE:
- fiberTag = MemoComponent;
- break getTag;
- case REACT_LAZY_TYPE:
- fiberTag = LazyComponent;
- resolvedType = null;
- break getTag;
- }
- }
- var info = '';
- {
- if (type === undefined || typeof type === 'object' && type !== null && Object.keys(type).length === 0) {
- info += ' You likely forgot to export your component from the file ' + "it's defined in, or you might have mixed up default and " + 'named imports.';
- }
- var ownerName = owner ? getComponentNameFromFiber(owner) : null;
- if (ownerName) {
- info += '\n\nCheck the render method of `' + ownerName + '`.';
- }
- }
- throw new Error('Element type is invalid: expected a string (for built-in ' + 'components) or a class/function (for composite components) ' + ("but got: " + (type == null ? type : typeof type) + "." + info));
- }
- }
- }
- var fiber = createFiber(fiberTag, pendingProps, key, mode);
- fiber.elementType = type;
- fiber.type = resolvedType;
- fiber.lanes = lanes;
- {
- fiber._debugOwner = owner;
- }
- return fiber;
- }
- function createFiberFromElement(element, mode, lanes) {
- var owner = null;
- {
- owner = element._owner;
- }
- var type = element.type;
- var key = element.key;
- var pendingProps = element.props;
- var fiber = createFiberFromTypeAndProps(type, key, pendingProps, owner, mode, lanes);
- {
- fiber._debugSource = element._source;
- fiber._debugOwner = element._owner;
- }
- return fiber;
- }
- function createFiberFromFragment(elements, mode, lanes, key) {
- var fiber = createFiber(Fragment, elements, key, mode);
- fiber.lanes = lanes;
- return fiber;
- }
- function createFiberFromProfiler(pendingProps, mode, lanes, key) {
- {
- if (typeof pendingProps.id !== 'string') {
- error('Profiler must specify an "id" of type `string` as a prop. Received the type `%s` instead.', typeof pendingProps.id);
- }
- }
- var fiber = createFiber(Profiler, pendingProps, key, mode | ProfileMode);
- fiber.elementType = REACT_PROFILER_TYPE;
- fiber.lanes = lanes;
- {
- fiber.stateNode = {
- effectDuration: 0,
- passiveEffectDuration: 0
- };
- }
- return fiber;
- }
- function createFiberFromSuspense(pendingProps, mode, lanes, key) {
- var fiber = createFiber(SuspenseComponent, pendingProps, key, mode);
- fiber.elementType = REACT_SUSPENSE_TYPE;
- fiber.lanes = lanes;
- return fiber;
- }
- function createFiberFromSuspenseList(pendingProps, mode, lanes, key) {
- var fiber = createFiber(SuspenseListComponent, pendingProps, key, mode);
- fiber.elementType = REACT_SUSPENSE_LIST_TYPE;
- fiber.lanes = lanes;
- return fiber;
- }
- function createFiberFromOffscreen(pendingProps, mode, lanes, key) {
- var fiber = createFiber(OffscreenComponent, pendingProps, key, mode);
- fiber.elementType = REACT_OFFSCREEN_TYPE;
- fiber.lanes = lanes;
- var primaryChildInstance = {
- isHidden: false
- };
- fiber.stateNode = primaryChildInstance;
- return fiber;
- }
- function createFiberFromText(content, mode, lanes) {
- var fiber = createFiber(HostText, content, null, mode);
- fiber.lanes = lanes;
- return fiber;
- }
- function createFiberFromHostInstanceForDeletion() {
- var fiber = createFiber(HostComponent, null, null, NoMode);
- fiber.elementType = 'DELETED';
- return fiber;
- }
- function createFiberFromDehydratedFragment(dehydratedNode) {
- var fiber = createFiber(DehydratedFragment, null, null, NoMode);
- fiber.stateNode = dehydratedNode;
- return fiber;
- }
- function createFiberFromPortal(portal, mode, lanes) {
- var pendingProps = portal.children !== null ? portal.children : [];
- var fiber = createFiber(HostPortal, pendingProps, portal.key, mode);
- fiber.lanes = lanes;
- fiber.stateNode = {
- containerInfo: portal.containerInfo,
- pendingChildren: null,
- // Used by persistent updates
- implementation: portal.implementation
- };
- return fiber;
- } // Used for stashing WIP properties to replay failed work in DEV.
- function assignFiberPropertiesInDEV(target, source) {
- if (target === null) {
- // This Fiber's initial properties will always be overwritten.
- // We only use a Fiber to ensure the same hidden class so DEV isn't slow.
- target = createFiber(IndeterminateComponent, null, null, NoMode);
- } // This is intentionally written as a list of all properties.
- // We tried to use Object.assign() instead but this is called in
- // the hottest path, and Object.assign() was too slow:
- // https://github.com/facebook/react/issues/12502
- // This code is DEV-only so size is not a concern.
- target.tag = source.tag;
- target.key = source.key;
- target.elementType = source.elementType;
- target.type = source.type;
- target.stateNode = source.stateNode;
- target.return = source.return;
- target.child = source.child;
- target.sibling = source.sibling;
- target.index = source.index;
- target.ref = source.ref;
- target.pendingProps = source.pendingProps;
- target.memoizedProps = source.memoizedProps;
- target.updateQueue = source.updateQueue;
- target.memoizedState = source.memoizedState;
- target.dependencies = source.dependencies;
- target.mode = source.mode;
- target.flags = source.flags;
- target.subtreeFlags = source.subtreeFlags;
- target.deletions = source.deletions;
- target.lanes = source.lanes;
- target.childLanes = source.childLanes;
- target.alternate = source.alternate;
- {
- target.actualDuration = source.actualDuration;
- target.actualStartTime = source.actualStartTime;
- target.selfBaseDuration = source.selfBaseDuration;
- target.treeBaseDuration = source.treeBaseDuration;
- }
- target._debugSource = source._debugSource;
- target._debugOwner = source._debugOwner;
- target._debugNeedsRemount = source._debugNeedsRemount;
- target._debugHookTypes = source._debugHookTypes;
- return target;
- }
- function FiberRootNode(containerInfo, tag, hydrate, identifierPrefix, onRecoverableError) {
- this.tag = tag;
- this.containerInfo = containerInfo;
- this.pendingChildren = null;
- this.current = null;
- this.pingCache = null;
- this.finishedWork = null;
- this.timeoutHandle = noTimeout;
- this.context = null;
- this.pendingContext = null;
- this.callbackNode = null;
- this.callbackPriority = NoLane;
- this.eventTimes = createLaneMap(NoLanes);
- this.expirationTimes = createLaneMap(NoTimestamp);
- this.pendingLanes = NoLanes;
- this.suspendedLanes = NoLanes;
- this.pingedLanes = NoLanes;
- this.expiredLanes = NoLanes;
- this.mutableReadLanes = NoLanes;
- this.finishedLanes = NoLanes;
- this.entangledLanes = NoLanes;
- this.entanglements = createLaneMap(NoLanes);
- this.identifierPrefix = identifierPrefix;
- this.onRecoverableError = onRecoverableError;
- {
- this.mutableSourceEagerHydrationData = null;
- }
- {
- this.effectDuration = 0;
- this.passiveEffectDuration = 0;
- }
- {
- this.memoizedUpdaters = new Set();
- var pendingUpdatersLaneMap = this.pendingUpdatersLaneMap = [];
- for (var _i = 0; _i < TotalLanes; _i++) {
- pendingUpdatersLaneMap.push(new Set());
- }
- }
- {
- switch (tag) {
- case ConcurrentRoot:
- this._debugRootType = hydrate ? 'hydrateRoot()' : 'createRoot()';
- break;
- case LegacyRoot:
- this._debugRootType = hydrate ? 'hydrate()' : 'render()';
- break;
- }
- }
- }
- function createFiberRoot(containerInfo, tag, hydrate, initialChildren, hydrationCallbacks, isStrictMode, concurrentUpdatesByDefaultOverride, // TODO: We have several of these arguments that are conceptually part of the
- // host config, but because they are passed in at runtime, we have to thread
- // them through the root constructor. Perhaps we should put them all into a
- // single type, like a DynamicHostConfig that is defined by the renderer.
- identifierPrefix, onRecoverableError, transitionCallbacks) {
- var root = new FiberRootNode(containerInfo, tag, hydrate, identifierPrefix, onRecoverableError);
- // stateNode is any.
- var uninitializedFiber = createHostRootFiber(tag, isStrictMode);
- root.current = uninitializedFiber;
- uninitializedFiber.stateNode = root;
- {
- var _initialState = {
- element: initialChildren,
- isDehydrated: hydrate,
- cache: null,
- // not enabled yet
- transitions: null,
- pendingSuspenseBoundaries: null
- };
- uninitializedFiber.memoizedState = _initialState;
- }
- initializeUpdateQueue(uninitializedFiber);
- return root;
- }
- var ReactVersion = '18.2.0';
- function createPortal(children, containerInfo, // TODO: figure out the API for cross-renderer implementation.
- implementation) {
- var key = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
- {
- checkKeyStringCoercion(key);
- }
- return {
- // This tag allow us to uniquely identify this as a React Portal
- $$typeof: REACT_PORTAL_TYPE,
- key: key == null ? null : '' + key,
- children: children,
- containerInfo: containerInfo,
- implementation: implementation
- };
- }
- var didWarnAboutNestedUpdates;
- var didWarnAboutFindNodeInStrictMode;
- {
- didWarnAboutNestedUpdates = false;
- didWarnAboutFindNodeInStrictMode = {};
- }
- function getContextForSubtree(parentComponent) {
- if (!parentComponent) {
- return emptyContextObject;
- }
- var fiber = get(parentComponent);
- var parentContext = findCurrentUnmaskedContext(fiber);
- if (fiber.tag === ClassComponent) {
- var Component = fiber.type;
- if (isContextProvider(Component)) {
- return processChildContext(fiber, Component, parentContext);
- }
- }
- return parentContext;
- }
- function findHostInstanceWithWarning(component, methodName) {
- {
- var fiber = get(component);
- if (fiber === undefined) {
- if (typeof component.render === 'function') {
- throw new Error('Unable to find node on an unmounted component.');
- } else {
- var keys = Object.keys(component).join(',');
- throw new Error("Argument appears to not be a ReactComponent. Keys: " + keys);
- }
- }
- var hostFiber = findCurrentHostFiber(fiber);
- if (hostFiber === null) {
- return null;
- }
- if (hostFiber.mode & StrictLegacyMode) {
- var componentName = getComponentNameFromFiber(fiber) || 'Component';
- if (!didWarnAboutFindNodeInStrictMode[componentName]) {
- didWarnAboutFindNodeInStrictMode[componentName] = true;
- var previousFiber = current;
- try {
- setCurrentFiber(hostFiber);
- if (fiber.mode & StrictLegacyMode) {
- error('%s is deprecated in StrictMode. ' + '%s was passed an instance of %s which is inside StrictMode. ' + 'Instead, add a ref directly to the element you want to reference. ' + 'Learn more about using refs safely here: ' + 'https://reactjs.org/link/strict-mode-find-node', methodName, methodName, componentName);
- } else {
- error('%s is deprecated in StrictMode. ' + '%s was passed an instance of %s which renders StrictMode children. ' + 'Instead, add a ref directly to the element you want to reference. ' + 'Learn more about using refs safely here: ' + 'https://reactjs.org/link/strict-mode-find-node', methodName, methodName, componentName);
- }
- } finally {
- // Ideally this should reset to previous but this shouldn't be called in
- // render and there's another warning for that anyway.
- if (previousFiber) {
- setCurrentFiber(previousFiber);
- } else {
- resetCurrentFiber();
- }
- }
- }
- }
- return hostFiber.stateNode;
- }
- }
- function createContainer(containerInfo, tag, hydrationCallbacks, isStrictMode, concurrentUpdatesByDefaultOverride, identifierPrefix, onRecoverableError, transitionCallbacks) {
- var hydrate = false;
- var initialChildren = null;
- return createFiberRoot(containerInfo, tag, hydrate, initialChildren, hydrationCallbacks, isStrictMode, concurrentUpdatesByDefaultOverride, identifierPrefix, onRecoverableError);
- }
- function createHydrationContainer(initialChildren, // TODO: Remove `callback` when we delete legacy mode.
- callback, containerInfo, tag, hydrationCallbacks, isStrictMode, concurrentUpdatesByDefaultOverride, identifierPrefix, onRecoverableError, transitionCallbacks) {
- var hydrate = true;
- var root = createFiberRoot(containerInfo, tag, hydrate, initialChildren, hydrationCallbacks, isStrictMode, concurrentUpdatesByDefaultOverride, identifierPrefix, onRecoverableError); // TODO: Move this to FiberRoot constructor
- root.context = getContextForSubtree(null); // Schedule the initial render. In a hydration root, this is different from
- // a regular update because the initial render must match was was rendered
- // on the server.
- // NOTE: This update intentionally doesn't have a payload. We're only using
- // the update to schedule work on the root fiber (and, for legacy roots, to
- // enqueue the callback if one is provided).
- var current = root.current;
- var eventTime = requestEventTime();
- var lane = requestUpdateLane(current);
- var update = createUpdate(eventTime, lane);
- update.callback = callback !== undefined && callback !== null ? callback : null;
- enqueueUpdate(current, update, lane);
- scheduleInitialHydrationOnRoot(root, lane, eventTime);
- return root;
- }
- function updateContainer(element, container, parentComponent, callback) {
- {
- onScheduleRoot(container, element);
- }
- var current$1 = container.current;
- var eventTime = requestEventTime();
- var lane = requestUpdateLane(current$1);
- {
- markRenderScheduled(lane);
- }
- var context = getContextForSubtree(parentComponent);
- if (container.context === null) {
- container.context = context;
- } else {
- container.pendingContext = context;
- }
- {
- if (isRendering && current !== null && !didWarnAboutNestedUpdates) {
- didWarnAboutNestedUpdates = true;
- error('Render methods should be a pure function of props and state; ' + 'triggering nested component updates from render is not allowed. ' + 'If necessary, trigger nested updates in componentDidUpdate.\n\n' + 'Check the render method of %s.', getComponentNameFromFiber(current) || 'Unknown');
- }
- }
- var update = createUpdate(eventTime, lane); // Caution: React DevTools currently depends on this property
- // being called "element".
- update.payload = {
- element: element
- };
- callback = callback === undefined ? null : callback;
- if (callback !== null) {
- {
- if (typeof callback !== 'function') {
- error('render(...): Expected the last optional `callback` argument to be a ' + 'function. Instead received: %s.', callback);
- }
- }
- update.callback = callback;
- }
- var root = enqueueUpdate(current$1, update, lane);
- if (root !== null) {
- scheduleUpdateOnFiber(root, current$1, lane, eventTime);
- entangleTransitions(root, current$1, lane);
- }
- return lane;
- }
- function getPublicRootInstance(container) {
- var containerFiber = container.current;
- if (!containerFiber.child) {
- return null;
- }
- switch (containerFiber.child.tag) {
- case HostComponent:
- return getPublicInstance(containerFiber.child.stateNode);
- default:
- return containerFiber.child.stateNode;
- }
- }
- function attemptSynchronousHydration$1(fiber) {
- switch (fiber.tag) {
- case HostRoot:
- {
- var root = fiber.stateNode;
- if (isRootDehydrated(root)) {
- // Flush the first scheduled "update".
- var lanes = getHighestPriorityPendingLanes(root);
- flushRoot(root, lanes);
- }
- break;
- }
- case SuspenseComponent:
- {
- flushSync(function () {
- var root = enqueueConcurrentRenderForLane(fiber, SyncLane);
- if (root !== null) {
- var eventTime = requestEventTime();
- scheduleUpdateOnFiber(root, fiber, SyncLane, eventTime);
- }
- }); // If we're still blocked after this, we need to increase
- // the priority of any promises resolving within this
- // boundary so that they next attempt also has higher pri.
- var retryLane = SyncLane;
- markRetryLaneIfNotHydrated(fiber, retryLane);
- break;
- }
- }
- }
- function markRetryLaneImpl(fiber, retryLane) {
- var suspenseState = fiber.memoizedState;
- if (suspenseState !== null && suspenseState.dehydrated !== null) {
- suspenseState.retryLane = higherPriorityLane(suspenseState.retryLane, retryLane);
- }
- } // Increases the priority of thenables when they resolve within this boundary.
- function markRetryLaneIfNotHydrated(fiber, retryLane) {
- markRetryLaneImpl(fiber, retryLane);
- var alternate = fiber.alternate;
- if (alternate) {
- markRetryLaneImpl(alternate, retryLane);
- }
- }
- function attemptContinuousHydration$1(fiber) {
- if (fiber.tag !== SuspenseComponent) {
- // We ignore HostRoots here because we can't increase
- // their priority and they should not suspend on I/O,
- // since you have to wrap anything that might suspend in
- // Suspense.
- return;
- }
- var lane = SelectiveHydrationLane;
- var root = enqueueConcurrentRenderForLane(fiber, lane);
- if (root !== null) {
- var eventTime = requestEventTime();
- scheduleUpdateOnFiber(root, fiber, lane, eventTime);
- }
- markRetryLaneIfNotHydrated(fiber, lane);
- }
- function attemptHydrationAtCurrentPriority$1(fiber) {
- if (fiber.tag !== SuspenseComponent) {
- // We ignore HostRoots here because we can't increase
- // their priority other than synchronously flush it.
- return;
- }
- var lane = requestUpdateLane(fiber);
- var root = enqueueConcurrentRenderForLane(fiber, lane);
- if (root !== null) {
- var eventTime = requestEventTime();
- scheduleUpdateOnFiber(root, fiber, lane, eventTime);
- }
- markRetryLaneIfNotHydrated(fiber, lane);
- }
- function findHostInstanceWithNoPortals(fiber) {
- var hostFiber = findCurrentHostFiberWithNoPortals(fiber);
- if (hostFiber === null) {
- return null;
- }
- return hostFiber.stateNode;
- }
- var shouldErrorImpl = function (fiber) {
- return null;
- };
- function shouldError(fiber) {
- return shouldErrorImpl(fiber);
- }
- var shouldSuspendImpl = function (fiber) {
- return false;
- };
- function shouldSuspend(fiber) {
- return shouldSuspendImpl(fiber);
- }
- var overrideHookState = null;
- var overrideHookStateDeletePath = null;
- var overrideHookStateRenamePath = null;
- var overrideProps = null;
- var overridePropsDeletePath = null;
- var overridePropsRenamePath = null;
- var scheduleUpdate = null;
- var setErrorHandler = null;
- var setSuspenseHandler = null;
- {
- var copyWithDeleteImpl = function (obj, path, index) {
- var key = path[index];
- var updated = isArray(obj) ? obj.slice() : assign({}, obj);
- if (index + 1 === path.length) {
- if (isArray(updated)) {
- updated.splice(key, 1);
- } else {
- delete updated[key];
- }
- return updated;
- } // $FlowFixMe number or string is fine here
- updated[key] = copyWithDeleteImpl(obj[key], path, index + 1);
- return updated;
- };
- var copyWithDelete = function (obj, path) {
- return copyWithDeleteImpl(obj, path, 0);
- };
- var copyWithRenameImpl = function (obj, oldPath, newPath, index) {
- var oldKey = oldPath[index];
- var updated = isArray(obj) ? obj.slice() : assign({}, obj);
- if (index + 1 === oldPath.length) {
- var newKey = newPath[index]; // $FlowFixMe number or string is fine here
- updated[newKey] = updated[oldKey];
- if (isArray(updated)) {
- updated.splice(oldKey, 1);
- } else {
- delete updated[oldKey];
- }
- } else {
- // $FlowFixMe number or string is fine here
- updated[oldKey] = copyWithRenameImpl( // $FlowFixMe number or string is fine here
- obj[oldKey], oldPath, newPath, index + 1);
- }
- return updated;
- };
- var copyWithRename = function (obj, oldPath, newPath) {
- if (oldPath.length !== newPath.length) {
- warn('copyWithRename() expects paths of the same length');
- return;
- } else {
- for (var i = 0; i < newPath.length - 1; i++) {
- if (oldPath[i] !== newPath[i]) {
- warn('copyWithRename() expects paths to be the same except for the deepest key');
- return;
- }
- }
- }
- return copyWithRenameImpl(obj, oldPath, newPath, 0);
- };
- var copyWithSetImpl = function (obj, path, index, value) {
- if (index >= path.length) {
- return value;
- }
- var key = path[index];
- var updated = isArray(obj) ? obj.slice() : assign({}, obj); // $FlowFixMe number or string is fine here
- updated[key] = copyWithSetImpl(obj[key], path, index + 1, value);
- return updated;
- };
- var copyWithSet = function (obj, path, value) {
- return copyWithSetImpl(obj, path, 0, value);
- };
- var findHook = function (fiber, id) {
- // For now, the "id" of stateful hooks is just the stateful hook index.
- // This may change in the future with e.g. nested hooks.
- var currentHook = fiber.memoizedState;
- while (currentHook !== null && id > 0) {
- currentHook = currentHook.next;
- id--;
- }
- return currentHook;
- }; // Support DevTools editable values for useState and useReducer.
- overrideHookState = function (fiber, id, path, value) {
- var hook = findHook(fiber, id);
- if (hook !== null) {
- var newState = copyWithSet(hook.memoizedState, path, value);
- hook.memoizedState = newState;
- hook.baseState = newState; // We aren't actually adding an update to the queue,
- // because there is no update we can add for useReducer hooks that won't trigger an error.
- // (There's no appropriate action type for DevTools overrides.)
- // As a result though, React will see the scheduled update as a noop and bailout.
- // Shallow cloning props works as a workaround for now to bypass the bailout check.
- fiber.memoizedProps = assign({}, fiber.memoizedProps);
- var root = enqueueConcurrentRenderForLane(fiber, SyncLane);
- if (root !== null) {
- scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp);
- }
- }
- };
- overrideHookStateDeletePath = function (fiber, id, path) {
- var hook = findHook(fiber, id);
- if (hook !== null) {
- var newState = copyWithDelete(hook.memoizedState, path);
- hook.memoizedState = newState;
- hook.baseState = newState; // We aren't actually adding an update to the queue,
- // because there is no update we can add for useReducer hooks that won't trigger an error.
- // (There's no appropriate action type for DevTools overrides.)
- // As a result though, React will see the scheduled update as a noop and bailout.
- // Shallow cloning props works as a workaround for now to bypass the bailout check.
- fiber.memoizedProps = assign({}, fiber.memoizedProps);
- var root = enqueueConcurrentRenderForLane(fiber, SyncLane);
- if (root !== null) {
- scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp);
- }
- }
- };
- overrideHookStateRenamePath = function (fiber, id, oldPath, newPath) {
- var hook = findHook(fiber, id);
- if (hook !== null) {
- var newState = copyWithRename(hook.memoizedState, oldPath, newPath);
- hook.memoizedState = newState;
- hook.baseState = newState; // We aren't actually adding an update to the queue,
- // because there is no update we can add for useReducer hooks that won't trigger an error.
- // (There's no appropriate action type for DevTools overrides.)
- // As a result though, React will see the scheduled update as a noop and bailout.
- // Shallow cloning props works as a workaround for now to bypass the bailout check.
- fiber.memoizedProps = assign({}, fiber.memoizedProps);
- var root = enqueueConcurrentRenderForLane(fiber, SyncLane);
- if (root !== null) {
- scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp);
- }
- }
- }; // Support DevTools props for function components, forwardRef, memo, host components, etc.
- overrideProps = function (fiber, path, value) {
- fiber.pendingProps = copyWithSet(fiber.memoizedProps, path, value);
- if (fiber.alternate) {
- fiber.alternate.pendingProps = fiber.pendingProps;
- }
- var root = enqueueConcurrentRenderForLane(fiber, SyncLane);
- if (root !== null) {
- scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp);
- }
- };
- overridePropsDeletePath = function (fiber, path) {
- fiber.pendingProps = copyWithDelete(fiber.memoizedProps, path);
- if (fiber.alternate) {
- fiber.alternate.pendingProps = fiber.pendingProps;
- }
- var root = enqueueConcurrentRenderForLane(fiber, SyncLane);
- if (root !== null) {
- scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp);
- }
- };
- overridePropsRenamePath = function (fiber, oldPath, newPath) {
- fiber.pendingProps = copyWithRename(fiber.memoizedProps, oldPath, newPath);
- if (fiber.alternate) {
- fiber.alternate.pendingProps = fiber.pendingProps;
- }
- var root = enqueueConcurrentRenderForLane(fiber, SyncLane);
- if (root !== null) {
- scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp);
- }
- };
- scheduleUpdate = function (fiber) {
- var root = enqueueConcurrentRenderForLane(fiber, SyncLane);
- if (root !== null) {
- scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp);
- }
- };
- setErrorHandler = function (newShouldErrorImpl) {
- shouldErrorImpl = newShouldErrorImpl;
- };
- setSuspenseHandler = function (newShouldSuspendImpl) {
- shouldSuspendImpl = newShouldSuspendImpl;
- };
- }
- function findHostInstanceByFiber(fiber) {
- var hostFiber = findCurrentHostFiber(fiber);
- if (hostFiber === null) {
- return null;
- }
- return hostFiber.stateNode;
- }
- function emptyFindFiberByHostInstance(instance) {
- return null;
- }
- function getCurrentFiberForDevTools() {
- return current;
- }
- function injectIntoDevTools(devToolsConfig) {
- var findFiberByHostInstance = devToolsConfig.findFiberByHostInstance;
- var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher;
- return injectInternals({
- bundleType: devToolsConfig.bundleType,
- version: devToolsConfig.version,
- rendererPackageName: devToolsConfig.rendererPackageName,
- rendererConfig: devToolsConfig.rendererConfig,
- overrideHookState: overrideHookState,
- overrideHookStateDeletePath: overrideHookStateDeletePath,
- overrideHookStateRenamePath: overrideHookStateRenamePath,
- overrideProps: overrideProps,
- overridePropsDeletePath: overridePropsDeletePath,
- overridePropsRenamePath: overridePropsRenamePath,
- setErrorHandler: setErrorHandler,
- setSuspenseHandler: setSuspenseHandler,
- scheduleUpdate: scheduleUpdate,
- currentDispatcherRef: ReactCurrentDispatcher,
- findHostInstanceByFiber: findHostInstanceByFiber,
- findFiberByHostInstance: findFiberByHostInstance || emptyFindFiberByHostInstance,
- // React Refresh
- findHostInstancesForRefresh: findHostInstancesForRefresh,
- scheduleRefresh: scheduleRefresh,
- scheduleRoot: scheduleRoot,
- setRefreshHandler: setRefreshHandler,
- // Enables DevTools to append owner stacks to error messages in DEV mode.
- getCurrentFiber: getCurrentFiberForDevTools,
- // Enables DevTools to detect reconciler version rather than renderer version
- // which may not match for third party renderers.
- reconcilerVersion: ReactVersion
- });
- }
- /* global reportError */
- var defaultOnRecoverableError = typeof reportError === 'function' ? // In modern browsers, reportError will dispatch an error event,
- // emulating an uncaught JavaScript error.
- reportError : function (error) {
- // In older browsers and test environments, fallback to console.error.
- // eslint-disable-next-line react-internal/no-production-logging
- console['error'](error);
- };
- function ReactDOMRoot(internalRoot) {
- this._internalRoot = internalRoot;
- }
- ReactDOMHydrationRoot.prototype.render = ReactDOMRoot.prototype.render = function (children) {
- var root = this._internalRoot;
- if (root === null) {
- throw new Error('Cannot update an unmounted root.');
- }
- {
- if (typeof arguments[1] === 'function') {
- error('render(...): does not support the second callback argument. ' + 'To execute a side effect after rendering, declare it in a component body with useEffect().');
- } else if (isValidContainer(arguments[1])) {
- error('You passed a container to the second argument of root.render(...). ' + "You don't need to pass it again since you already passed it to create the root.");
- } else if (typeof arguments[1] !== 'undefined') {
- error('You passed a second argument to root.render(...) but it only accepts ' + 'one argument.');
- }
- var container = root.containerInfo;
- if (container.nodeType !== COMMENT_NODE) {
- var hostInstance = findHostInstanceWithNoPortals(root.current);
- if (hostInstance) {
- if (hostInstance.parentNode !== container) {
- error('render(...): It looks like the React-rendered content of the ' + 'root container was removed without using React. This is not ' + 'supported and will cause errors. Instead, call ' + "root.unmount() to empty a root's container.");
- }
- }
- }
- }
- updateContainer(children, root, null, null);
- };
- ReactDOMHydrationRoot.prototype.unmount = ReactDOMRoot.prototype.unmount = function () {
- {
- if (typeof arguments[0] === 'function') {
- error('unmount(...): does not support a callback argument. ' + 'To execute a side effect after rendering, declare it in a component body with useEffect().');
- }
- }
- var root = this._internalRoot;
- if (root !== null) {
- this._internalRoot = null;
- var container = root.containerInfo;
- {
- if (isAlreadyRendering()) {
- error('Attempted to synchronously unmount a root while React was already ' + 'rendering. React cannot finish unmounting the root until the ' + 'current render has completed, which may lead to a race condition.');
- }
- }
- flushSync(function () {
- updateContainer(null, root, null, null);
- });
- unmarkContainerAsRoot(container);
- }
- };
- function createRoot(container, options) {
- if (!isValidContainer(container)) {
- throw new Error('createRoot(...): Target container is not a DOM element.');
- }
- warnIfReactDOMContainerInDEV(container);
- var isStrictMode = false;
- var concurrentUpdatesByDefaultOverride = false;
- var identifierPrefix = '';
- var onRecoverableError = defaultOnRecoverableError;
- var transitionCallbacks = null;
- if (options !== null && options !== undefined) {
- {
- if (options.hydrate) {
- warn('hydrate through createRoot is deprecated. Use ReactDOMClient.hydrateRoot(container, <App />) instead.');
- } else {
- if (typeof options === 'object' && options !== null && options.$$typeof === REACT_ELEMENT_TYPE) {
- error('You passed a JSX element to createRoot. You probably meant to ' + 'call root.render instead. ' + 'Example usage:\n\n' + ' let root = createRoot(domContainer);\n' + ' root.render(<App />);');
- }
- }
- }
- if (options.unstable_strictMode === true) {
- isStrictMode = true;
- }
- if (options.identifierPrefix !== undefined) {
- identifierPrefix = options.identifierPrefix;
- }
- if (options.onRecoverableError !== undefined) {
- onRecoverableError = options.onRecoverableError;
- }
- if (options.transitionCallbacks !== undefined) {
- transitionCallbacks = options.transitionCallbacks;
- }
- }
- var root = createContainer(container, ConcurrentRoot, null, isStrictMode, concurrentUpdatesByDefaultOverride, identifierPrefix, onRecoverableError);
- markContainerAsRoot(root.current, container);
- var rootContainerElement = container.nodeType === COMMENT_NODE ? container.parentNode : container;
- listenToAllSupportedEvents(rootContainerElement);
- return new ReactDOMRoot(root);
- }
- function ReactDOMHydrationRoot(internalRoot) {
- this._internalRoot = internalRoot;
- }
- function scheduleHydration(target) {
- if (target) {
- queueExplicitHydrationTarget(target);
- }
- }
- ReactDOMHydrationRoot.prototype.unstable_scheduleHydration = scheduleHydration;
- function hydrateRoot(container, initialChildren, options) {
- if (!isValidContainer(container)) {
- throw new Error('hydrateRoot(...): Target container is not a DOM element.');
- }
- warnIfReactDOMContainerInDEV(container);
- {
- if (initialChildren === undefined) {
- error('Must provide initial children as second argument to hydrateRoot. ' + 'Example usage: hydrateRoot(domContainer, <App />)');
- }
- } // For now we reuse the whole bag of options since they contain
- // the hydration callbacks.
- var hydrationCallbacks = options != null ? options : null; // TODO: Delete this option
- var mutableSources = options != null && options.hydratedSources || null;
- var isStrictMode = false;
- var concurrentUpdatesByDefaultOverride = false;
- var identifierPrefix = '';
- var onRecoverableError = defaultOnRecoverableError;
- if (options !== null && options !== undefined) {
- if (options.unstable_strictMode === true) {
- isStrictMode = true;
- }
- if (options.identifierPrefix !== undefined) {
- identifierPrefix = options.identifierPrefix;
- }
- if (options.onRecoverableError !== undefined) {
- onRecoverableError = options.onRecoverableError;
- }
- }
- var root = createHydrationContainer(initialChildren, null, container, ConcurrentRoot, hydrationCallbacks, isStrictMode, concurrentUpdatesByDefaultOverride, identifierPrefix, onRecoverableError);
- markContainerAsRoot(root.current, container); // This can't be a comment node since hydration doesn't work on comment nodes anyway.
- listenToAllSupportedEvents(container);
- if (mutableSources) {
- for (var i = 0; i < mutableSources.length; i++) {
- var mutableSource = mutableSources[i];
- registerMutableSourceForHydration(root, mutableSource);
- }
- }
- return new ReactDOMHydrationRoot(root);
- }
- function isValidContainer(node) {
- return !!(node && (node.nodeType === ELEMENT_NODE || node.nodeType === DOCUMENT_NODE || node.nodeType === DOCUMENT_FRAGMENT_NODE || !disableCommentsAsDOMContainers));
- } // TODO: Remove this function which also includes comment nodes.
- // We only use it in places that are currently more relaxed.
- function isValidContainerLegacy(node) {
- return !!(node && (node.nodeType === ELEMENT_NODE || node.nodeType === DOCUMENT_NODE || node.nodeType === DOCUMENT_FRAGMENT_NODE || node.nodeType === COMMENT_NODE && node.nodeValue === ' react-mount-point-unstable '));
- }
- function warnIfReactDOMContainerInDEV(container) {
- {
- if (container.nodeType === ELEMENT_NODE && container.tagName && container.tagName.toUpperCase() === 'BODY') {
- error('createRoot(): Creating roots directly with document.body is ' + 'discouraged, since its children are often manipulated by third-party ' + 'scripts and browser extensions. This may lead to subtle ' + 'reconciliation issues. Try using a container element created ' + 'for your app.');
- }
- if (isContainerMarkedAsRoot(container)) {
- if (container._reactRootContainer) {
- error('You are calling ReactDOMClient.createRoot() on a container that was previously ' + 'passed to ReactDOM.render(). This is not supported.');
- } else {
- error('You are calling ReactDOMClient.createRoot() on a container that ' + 'has already been passed to createRoot() before. Instead, call ' + 'root.render() on the existing root instead if you want to update it.');
- }
- }
- }
- }
- var ReactCurrentOwner$3 = ReactSharedInternals.ReactCurrentOwner;
- var topLevelUpdateWarnings;
- {
- topLevelUpdateWarnings = function (container) {
- if (container._reactRootContainer && container.nodeType !== COMMENT_NODE) {
- var hostInstance = findHostInstanceWithNoPortals(container._reactRootContainer.current);
- if (hostInstance) {
- if (hostInstance.parentNode !== container) {
- error('render(...): It looks like the React-rendered content of this ' + 'container was removed without using React. This is not ' + 'supported and will cause errors. Instead, call ' + 'ReactDOM.unmountComponentAtNode to empty a container.');
- }
- }
- }
- var isRootRenderedBySomeReact = !!container._reactRootContainer;
- var rootEl = getReactRootElementInContainer(container);
- var hasNonRootReactChild = !!(rootEl && getInstanceFromNode(rootEl));
- if (hasNonRootReactChild && !isRootRenderedBySomeReact) {
- error('render(...): Replacing React-rendered children with a new root ' + 'component. If you intended to update the children of this node, ' + 'you should instead have the existing children update their state ' + 'and render the new components instead of calling ReactDOM.render.');
- }
- if (container.nodeType === ELEMENT_NODE && container.tagName && container.tagName.toUpperCase() === 'BODY') {
- error('render(): Rendering components directly into document.body is ' + 'discouraged, since its children are often manipulated by third-party ' + 'scripts and browser extensions. This may lead to subtle ' + 'reconciliation issues. Try rendering into a container element created ' + 'for your app.');
- }
- };
- }
- function getReactRootElementInContainer(container) {
- if (!container) {
- return null;
- }
- if (container.nodeType === DOCUMENT_NODE) {
- return container.documentElement;
- } else {
- return container.firstChild;
- }
- }
- function noopOnRecoverableError() {// This isn't reachable because onRecoverableError isn't called in the
- // legacy API.
- }
- function legacyCreateRootFromDOMContainer(container, initialChildren, parentComponent, callback, isHydrationContainer) {
- if (isHydrationContainer) {
- if (typeof callback === 'function') {
- var originalCallback = callback;
- callback = function () {
- var instance = getPublicRootInstance(root);
- originalCallback.call(instance);
- };
- }
- var root = createHydrationContainer(initialChildren, callback, container, LegacyRoot, null, // hydrationCallbacks
- false, // isStrictMode
- false, // concurrentUpdatesByDefaultOverride,
- '', // identifierPrefix
- noopOnRecoverableError);
- container._reactRootContainer = root;
- markContainerAsRoot(root.current, container);
- var rootContainerElement = container.nodeType === COMMENT_NODE ? container.parentNode : container;
- listenToAllSupportedEvents(rootContainerElement);
- flushSync();
- return root;
- } else {
- // First clear any existing content.
- var rootSibling;
- while (rootSibling = container.lastChild) {
- container.removeChild(rootSibling);
- }
- if (typeof callback === 'function') {
- var _originalCallback = callback;
- callback = function () {
- var instance = getPublicRootInstance(_root);
- _originalCallback.call(instance);
- };
- }
- var _root = createContainer(container, LegacyRoot, null, // hydrationCallbacks
- false, // isStrictMode
- false, // concurrentUpdatesByDefaultOverride,
- '', // identifierPrefix
- noopOnRecoverableError);
- container._reactRootContainer = _root;
- markContainerAsRoot(_root.current, container);
- var _rootContainerElement = container.nodeType === COMMENT_NODE ? container.parentNode : container;
- listenToAllSupportedEvents(_rootContainerElement); // Initial mount should not be batched.
- flushSync(function () {
- updateContainer(initialChildren, _root, parentComponent, callback);
- });
- return _root;
- }
- }
- function warnOnInvalidCallback$1(callback, callerName) {
- {
- if (callback !== null && typeof callback !== 'function') {
- error('%s(...): Expected the last optional `callback` argument to be a ' + 'function. Instead received: %s.', callerName, callback);
- }
- }
- }
- function legacyRenderSubtreeIntoContainer(parentComponent, children, container, forceHydrate, callback) {
- {
- topLevelUpdateWarnings(container);
- warnOnInvalidCallback$1(callback === undefined ? null : callback, 'render');
- }
- var maybeRoot = container._reactRootContainer;
- var root;
- if (!maybeRoot) {
- // Initial mount
- root = legacyCreateRootFromDOMContainer(container, children, parentComponent, callback, forceHydrate);
- } else {
- root = maybeRoot;
- if (typeof callback === 'function') {
- var originalCallback = callback;
- callback = function () {
- var instance = getPublicRootInstance(root);
- originalCallback.call(instance);
- };
- } // Update
- updateContainer(children, root, parentComponent, callback);
- }
- return getPublicRootInstance(root);
- }
- function findDOMNode(componentOrElement) {
- {
- var owner = ReactCurrentOwner$3.current;
- if (owner !== null && owner.stateNode !== null) {
- var warnedAboutRefsInRender = owner.stateNode._warnedAboutRefsInRender;
- if (!warnedAboutRefsInRender) {
- error('%s is accessing findDOMNode inside its render(). ' + 'render() should be a pure function of props and state. It should ' + 'never access something that requires stale data from the previous ' + 'render, such as refs. Move this logic to componentDidMount and ' + 'componentDidUpdate instead.', getComponentNameFromType(owner.type) || 'A component');
- }
- owner.stateNode._warnedAboutRefsInRender = true;
- }
- }
- if (componentOrElement == null) {
- return null;
- }
- if (componentOrElement.nodeType === ELEMENT_NODE) {
- return componentOrElement;
- }
- {
- return findHostInstanceWithWarning(componentOrElement, 'findDOMNode');
- }
- }
- function hydrate(element, container, callback) {
- {
- error('ReactDOM.hydrate is no longer supported in React 18. Use hydrateRoot ' + 'instead. Until you switch to the new API, your app will behave as ' + "if it's running React 17. Learn " + 'more: https://reactjs.org/link/switch-to-createroot');
- }
- if (!isValidContainerLegacy(container)) {
- throw new Error('Target container is not a DOM element.');
- }
- {
- var isModernRoot = isContainerMarkedAsRoot(container) && container._reactRootContainer === undefined;
- if (isModernRoot) {
- error('You are calling ReactDOM.hydrate() on a container that was previously ' + 'passed to ReactDOMClient.createRoot(). This is not supported. ' + 'Did you mean to call hydrateRoot(container, element)?');
- }
- } // TODO: throw or warn if we couldn't hydrate?
- return legacyRenderSubtreeIntoContainer(null, element, container, true, callback);
- }
- function render(element, container, callback) {
- {
- error('ReactDOM.render is no longer supported in React 18. Use createRoot ' + 'instead. Until you switch to the new API, your app will behave as ' + "if it's running React 17. Learn " + 'more: https://reactjs.org/link/switch-to-createroot');
- }
- if (!isValidContainerLegacy(container)) {
- throw new Error('Target container is not a DOM element.');
- }
- {
- var isModernRoot = isContainerMarkedAsRoot(container) && container._reactRootContainer === undefined;
- if (isModernRoot) {
- error('You are calling ReactDOM.render() on a container that was previously ' + 'passed to ReactDOMClient.createRoot(). This is not supported. ' + 'Did you mean to call root.render(element)?');
- }
- }
- return legacyRenderSubtreeIntoContainer(null, element, container, false, callback);
- }
- function unstable_renderSubtreeIntoContainer(parentComponent, element, containerNode, callback) {
- {
- error('ReactDOM.unstable_renderSubtreeIntoContainer() is no longer supported ' + 'in React 18. Consider using a portal instead. Until you switch to ' + "the createRoot API, your app will behave as if it's running React " + '17. Learn more: https://reactjs.org/link/switch-to-createroot');
- }
- if (!isValidContainerLegacy(containerNode)) {
- throw new Error('Target container is not a DOM element.');
- }
- if (parentComponent == null || !has(parentComponent)) {
- throw new Error('parentComponent must be a valid React Component');
- }
- return legacyRenderSubtreeIntoContainer(parentComponent, element, containerNode, false, callback);
- }
- function unmountComponentAtNode(container) {
- if (!isValidContainerLegacy(container)) {
- throw new Error('unmountComponentAtNode(...): Target container is not a DOM element.');
- }
- {
- var isModernRoot = isContainerMarkedAsRoot(container) && container._reactRootContainer === undefined;
- if (isModernRoot) {
- error('You are calling ReactDOM.unmountComponentAtNode() on a container that was previously ' + 'passed to ReactDOMClient.createRoot(). This is not supported. Did you mean to call root.unmount()?');
- }
- }
- if (container._reactRootContainer) {
- {
- var rootEl = getReactRootElementInContainer(container);
- var renderedByDifferentReact = rootEl && !getInstanceFromNode(rootEl);
- if (renderedByDifferentReact) {
- error("unmountComponentAtNode(): The node you're attempting to unmount " + 'was rendered by another copy of React.');
- }
- } // Unmount should not be batched.
- flushSync(function () {
- legacyRenderSubtreeIntoContainer(null, null, container, false, function () {
- // $FlowFixMe This should probably use `delete container._reactRootContainer`
- container._reactRootContainer = null;
- unmarkContainerAsRoot(container);
- });
- }); // If you call unmountComponentAtNode twice in quick succession, you'll
- // get `true` twice. That's probably fine?
- return true;
- } else {
- {
- var _rootEl = getReactRootElementInContainer(container);
- var hasNonRootReactChild = !!(_rootEl && getInstanceFromNode(_rootEl)); // Check if the container itself is a React root node.
- var isContainerReactRoot = container.nodeType === ELEMENT_NODE && isValidContainerLegacy(container.parentNode) && !!container.parentNode._reactRootContainer;
- if (hasNonRootReactChild) {
- error("unmountComponentAtNode(): The node you're attempting to unmount " + 'was rendered by React and is not a top-level container. %s', isContainerReactRoot ? 'You may have accidentally passed in a React root node instead ' + 'of its container.' : 'Instead, have the parent component update its state and ' + 'rerender in order to remove this component.');
- }
- }
- return false;
- }
- }
- setAttemptSynchronousHydration(attemptSynchronousHydration$1);
- setAttemptContinuousHydration(attemptContinuousHydration$1);
- setAttemptHydrationAtCurrentPriority(attemptHydrationAtCurrentPriority$1);
- setGetCurrentUpdatePriority(getCurrentUpdatePriority);
- setAttemptHydrationAtPriority(runWithPriority);
- {
- if (typeof Map !== 'function' || // $FlowIssue Flow incorrectly thinks Map has no prototype
- Map.prototype == null || typeof Map.prototype.forEach !== 'function' || typeof Set !== 'function' || // $FlowIssue Flow incorrectly thinks Set has no prototype
- Set.prototype == null || typeof Set.prototype.clear !== 'function' || typeof Set.prototype.forEach !== 'function') {
- error('React depends on Map and Set built-in types. Make sure that you load a ' + 'polyfill in older browsers. https://reactjs.org/link/react-polyfills');
- }
- }
- setRestoreImplementation(restoreControlledState$3);
- setBatchingImplementation(batchedUpdates$1, discreteUpdates, flushSync);
- function createPortal$1(children, container) {
- var key = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
- if (!isValidContainer(container)) {
- throw new Error('Target container is not a DOM element.');
- } // TODO: pass ReactDOM portal implementation as third argument
- // $FlowFixMe The Flow type is opaque but there's no way to actually create it.
- return createPortal(children, container, null, key);
- }
- function renderSubtreeIntoContainer(parentComponent, element, containerNode, callback) {
- return unstable_renderSubtreeIntoContainer(parentComponent, element, containerNode, callback);
- }
- var Internals = {
- usingClientEntryPoint: false,
- // Keep in sync with ReactTestUtils.js.
- // This is an array for better minification.
- Events: [getInstanceFromNode, getNodeFromInstance, getFiberCurrentPropsFromNode, enqueueStateRestore, restoreStateIfNeeded, batchedUpdates$1]
- };
- function createRoot$1(container, options) {
- {
- if (!Internals.usingClientEntryPoint && !true) {
- error('You are importing createRoot from "react-dom" which is not supported. ' + 'You should instead import it from "react-dom/client".');
- }
- }
- return createRoot(container, options);
- }
- function hydrateRoot$1(container, initialChildren, options) {
- {
- if (!Internals.usingClientEntryPoint && !true) {
- error('You are importing hydrateRoot from "react-dom" which is not supported. ' + 'You should instead import it from "react-dom/client".');
- }
- }
- return hydrateRoot(container, initialChildren, options);
- } // Overload the definition to the two valid signatures.
- // Warning, this opts-out of checking the function body.
- // eslint-disable-next-line no-redeclare
- function flushSync$1(fn) {
- {
- if (isAlreadyRendering()) {
- error('flushSync was called from inside a lifecycle method. React cannot ' + 'flush when React is already rendering. Consider moving this call to ' + 'a scheduler task or micro task.');
- }
- }
- return flushSync(fn);
- }
- var foundDevTools = injectIntoDevTools({
- findFiberByHostInstance: getClosestInstanceFromNode,
- bundleType: 1,
- version: ReactVersion,
- rendererPackageName: 'react-dom'
- });
- {
- if (!foundDevTools && canUseDOM && window.top === window.self) {
- // If we're in Chrome or Firefox, provide a download link if not installed.
- if (navigator.userAgent.indexOf('Chrome') > -1 && navigator.userAgent.indexOf('Edge') === -1 || navigator.userAgent.indexOf('Firefox') > -1) {
- var protocol = window.location.protocol; // Don't warn in exotic cases like chrome-extension://.
- if (/^(https?|file):$/.test(protocol)) {
- // eslint-disable-next-line react-internal/no-production-logging
- console.info('%cDownload the React DevTools ' + 'for a better development experience: ' + 'https://reactjs.org/link/react-devtools' + (protocol === 'file:' ? '\nYou might need to use a local HTTP server (instead of file://): ' + 'https://reactjs.org/link/react-devtools-faq' : ''), 'font-weight:bold');
- }
- }
- }
- }
- exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = Internals;
- exports.createPortal = createPortal$1;
- exports.createRoot = createRoot$1;
- exports.findDOMNode = findDOMNode;
- exports.flushSync = flushSync$1;
- exports.hydrate = hydrate;
- exports.hydrateRoot = hydrateRoot$1;
- exports.render = render;
- exports.unmountComponentAtNode = unmountComponentAtNode;
- exports.unstable_batchedUpdates = batchedUpdates$1;
- exports.unstable_renderSubtreeIntoContainer = renderSubtreeIntoContainer;
- exports.version = ReactVersion;
- })));
|