router.js 220 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961
  1. /**
  2. * @license Angular v7.0.3
  3. * (c) 2010-2018 Google, Inc. https://angular.io/
  4. * License: MIT
  5. */
  6. import { Component, ɵisObservable, ɵisPromise, NgModuleRef, InjectionToken, NgModuleFactory, NgZone, isDevMode, ɵConsole, Attribute, Directive, ElementRef, HostBinding, HostListener, Input, Renderer2, ChangeDetectorRef, ContentChildren, ComponentFactoryResolver, EventEmitter, Output, ViewContainerRef, Compiler, Injectable, Injector, NgModuleFactoryLoader, ANALYZE_FOR_ENTRY_COMPONENTS, APP_BOOTSTRAP_LISTENER, APP_INITIALIZER, ApplicationRef, Inject, NgModule, NgProbeToken, Optional, SkipSelf, SystemJsNgModuleLoader, Version } from '@angular/core';
  7. import { from, of, BehaviorSubject, EmptyError, Observable, EMPTY, Subject } from 'rxjs';
  8. import { concatAll, every, last, map, mergeAll, catchError, first, mergeMap, switchMap, concatMap, reduce, filter, finalize, tap } from 'rxjs/operators';
  9. import { LocationStrategy, APP_BASE_HREF, HashLocationStrategy, LOCATION_INITIALIZED, Location, PathLocationStrategy, PlatformLocation, ViewportScroller } from '@angular/common';
  10. import { ɵgetDOM } from '@angular/platform-browser';
  11. /**
  12. * @fileoverview added by tsickle
  13. * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
  14. */
  15. /**
  16. * \@description
  17. *
  18. * Base for events the Router goes through, as opposed to events tied to a specific
  19. * Route. `RouterEvent`s will only be fired one time for any given navigation.
  20. *
  21. * Example:
  22. *
  23. * ```
  24. * class MyService {
  25. * constructor(public router: Router, logger: Logger) {
  26. * router.events.filter(e => e instanceof RouterEvent).subscribe(e => {
  27. * logger.log(e.id, e.url);
  28. * });
  29. * }
  30. * }
  31. * ```
  32. *
  33. * \@publicApi
  34. */
  35. class RouterEvent {
  36. /**
  37. * @param {?} id
  38. * @param {?} url
  39. */
  40. constructor(id, url) {
  41. this.id = id;
  42. this.url = url;
  43. }
  44. }
  45. /**
  46. * \@description
  47. *
  48. * Represents an event triggered when a navigation starts.
  49. *
  50. * \@publicApi
  51. */
  52. class NavigationStart extends RouterEvent {
  53. /**
  54. * @param {?} id
  55. * @param {?} url
  56. * @param {?=} navigationTrigger
  57. * @param {?=} restoredState
  58. */
  59. constructor(/** @docsNotRequired */
  60. id, /** @docsNotRequired */
  61. url, /** @docsNotRequired */
  62. navigationTrigger = 'imperative', /** @docsNotRequired */
  63. restoredState = null) {
  64. super(id, url);
  65. this.navigationTrigger = navigationTrigger;
  66. this.restoredState = restoredState;
  67. }
  68. /**
  69. * \@docsNotRequired
  70. * @return {?}
  71. */
  72. toString() { return `NavigationStart(id: ${this.id}, url: '${this.url}')`; }
  73. }
  74. /**
  75. * \@description
  76. *
  77. * Represents an event triggered when a navigation ends successfully.
  78. *
  79. * \@publicApi
  80. */
  81. class NavigationEnd extends RouterEvent {
  82. /**
  83. * @param {?} id
  84. * @param {?} url
  85. * @param {?} urlAfterRedirects
  86. */
  87. constructor(/** @docsNotRequired */
  88. id, /** @docsNotRequired */
  89. url, urlAfterRedirects) {
  90. super(id, url);
  91. this.urlAfterRedirects = urlAfterRedirects;
  92. }
  93. /**
  94. * \@docsNotRequired
  95. * @return {?}
  96. */
  97. toString() {
  98. return `NavigationEnd(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}')`;
  99. }
  100. }
  101. /**
  102. * \@description
  103. *
  104. * Represents an event triggered when a navigation is canceled.
  105. *
  106. * \@publicApi
  107. */
  108. class NavigationCancel extends RouterEvent {
  109. /**
  110. * @param {?} id
  111. * @param {?} url
  112. * @param {?} reason
  113. */
  114. constructor(/** @docsNotRequired */
  115. id, /** @docsNotRequired */
  116. url, reason) {
  117. super(id, url);
  118. this.reason = reason;
  119. }
  120. /**
  121. * \@docsNotRequired
  122. * @return {?}
  123. */
  124. toString() { return `NavigationCancel(id: ${this.id}, url: '${this.url}')`; }
  125. }
  126. /**
  127. * \@description
  128. *
  129. * Represents an event triggered when a navigation fails due to an unexpected error.
  130. *
  131. * \@publicApi
  132. */
  133. class NavigationError extends RouterEvent {
  134. /**
  135. * @param {?} id
  136. * @param {?} url
  137. * @param {?} error
  138. */
  139. constructor(/** @docsNotRequired */
  140. id, /** @docsNotRequired */
  141. url, error) {
  142. super(id, url);
  143. this.error = error;
  144. }
  145. /**
  146. * \@docsNotRequired
  147. * @return {?}
  148. */
  149. toString() {
  150. return `NavigationError(id: ${this.id}, url: '${this.url}', error: ${this.error})`;
  151. }
  152. }
  153. /**
  154. * \@description
  155. *
  156. * Represents an event triggered when routes are recognized.
  157. *
  158. * \@publicApi
  159. */
  160. class RoutesRecognized extends RouterEvent {
  161. /**
  162. * @param {?} id
  163. * @param {?} url
  164. * @param {?} urlAfterRedirects
  165. * @param {?} state
  166. */
  167. constructor(/** @docsNotRequired */
  168. id, /** @docsNotRequired */
  169. url, urlAfterRedirects, state) {
  170. super(id, url);
  171. this.urlAfterRedirects = urlAfterRedirects;
  172. this.state = state;
  173. }
  174. /**
  175. * \@docsNotRequired
  176. * @return {?}
  177. */
  178. toString() {
  179. return `RoutesRecognized(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`;
  180. }
  181. }
  182. /**
  183. * \@description
  184. *
  185. * Represents the start of the Guard phase of routing.
  186. *
  187. * \@publicApi
  188. */
  189. class GuardsCheckStart extends RouterEvent {
  190. /**
  191. * @param {?} id
  192. * @param {?} url
  193. * @param {?} urlAfterRedirects
  194. * @param {?} state
  195. */
  196. constructor(/** @docsNotRequired */
  197. id, /** @docsNotRequired */
  198. url, urlAfterRedirects, state) {
  199. super(id, url);
  200. this.urlAfterRedirects = urlAfterRedirects;
  201. this.state = state;
  202. }
  203. /**
  204. * @return {?}
  205. */
  206. toString() {
  207. return `GuardsCheckStart(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`;
  208. }
  209. }
  210. /**
  211. * \@description
  212. *
  213. * Represents the end of the Guard phase of routing.
  214. *
  215. * \@publicApi
  216. */
  217. class GuardsCheckEnd extends RouterEvent {
  218. /**
  219. * @param {?} id
  220. * @param {?} url
  221. * @param {?} urlAfterRedirects
  222. * @param {?} state
  223. * @param {?} shouldActivate
  224. */
  225. constructor(/** @docsNotRequired */
  226. id, /** @docsNotRequired */
  227. url, urlAfterRedirects, state, shouldActivate) {
  228. super(id, url);
  229. this.urlAfterRedirects = urlAfterRedirects;
  230. this.state = state;
  231. this.shouldActivate = shouldActivate;
  232. }
  233. /**
  234. * @return {?}
  235. */
  236. toString() {
  237. return `GuardsCheckEnd(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state}, shouldActivate: ${this.shouldActivate})`;
  238. }
  239. }
  240. /**
  241. * \@description
  242. *
  243. * Represents the start of the Resolve phase of routing. The timing of this
  244. * event may change, thus it's experimental. In the current iteration it will run
  245. * in the "resolve" phase whether there's things to resolve or not. In the future this
  246. * behavior may change to only run when there are things to be resolved.
  247. *
  248. * \@publicApi
  249. */
  250. class ResolveStart extends RouterEvent {
  251. /**
  252. * @param {?} id
  253. * @param {?} url
  254. * @param {?} urlAfterRedirects
  255. * @param {?} state
  256. */
  257. constructor(/** @docsNotRequired */
  258. id, /** @docsNotRequired */
  259. url, urlAfterRedirects, state) {
  260. super(id, url);
  261. this.urlAfterRedirects = urlAfterRedirects;
  262. this.state = state;
  263. }
  264. /**
  265. * @return {?}
  266. */
  267. toString() {
  268. return `ResolveStart(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`;
  269. }
  270. }
  271. /**
  272. * \@description
  273. *
  274. * Represents the end of the Resolve phase of routing. See note on
  275. * `ResolveStart` for use of this experimental API.
  276. *
  277. * \@publicApi
  278. */
  279. class ResolveEnd extends RouterEvent {
  280. /**
  281. * @param {?} id
  282. * @param {?} url
  283. * @param {?} urlAfterRedirects
  284. * @param {?} state
  285. */
  286. constructor(/** @docsNotRequired */
  287. id, /** @docsNotRequired */
  288. url, urlAfterRedirects, state) {
  289. super(id, url);
  290. this.urlAfterRedirects = urlAfterRedirects;
  291. this.state = state;
  292. }
  293. /**
  294. * @return {?}
  295. */
  296. toString() {
  297. return `ResolveEnd(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`;
  298. }
  299. }
  300. /**
  301. * \@description
  302. *
  303. * Represents an event triggered before lazy loading a route config.
  304. *
  305. * \@publicApi
  306. */
  307. class RouteConfigLoadStart {
  308. /**
  309. * @param {?} route
  310. */
  311. constructor(route) {
  312. this.route = route;
  313. }
  314. /**
  315. * @return {?}
  316. */
  317. toString() { return `RouteConfigLoadStart(path: ${this.route.path})`; }
  318. }
  319. /**
  320. * \@description
  321. *
  322. * Represents an event triggered when a route has been lazy loaded.
  323. *
  324. * \@publicApi
  325. */
  326. class RouteConfigLoadEnd {
  327. /**
  328. * @param {?} route
  329. */
  330. constructor(route) {
  331. this.route = route;
  332. }
  333. /**
  334. * @return {?}
  335. */
  336. toString() { return `RouteConfigLoadEnd(path: ${this.route.path})`; }
  337. }
  338. /**
  339. * \@description
  340. *
  341. * Represents the start of end of the Resolve phase of routing. See note on
  342. * `ChildActivationEnd` for use of this experimental API.
  343. *
  344. * \@publicApi
  345. */
  346. class ChildActivationStart {
  347. /**
  348. * @param {?} snapshot
  349. */
  350. constructor(snapshot) {
  351. this.snapshot = snapshot;
  352. }
  353. /**
  354. * @return {?}
  355. */
  356. toString() {
  357. /** @type {?} */
  358. const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || '';
  359. return `ChildActivationStart(path: '${path}')`;
  360. }
  361. }
  362. /**
  363. * \@description
  364. *
  365. * Represents the start of end of the Resolve phase of routing. See note on
  366. * `ChildActivationStart` for use of this experimental API.
  367. *
  368. * \@publicApi
  369. */
  370. class ChildActivationEnd {
  371. /**
  372. * @param {?} snapshot
  373. */
  374. constructor(snapshot) {
  375. this.snapshot = snapshot;
  376. }
  377. /**
  378. * @return {?}
  379. */
  380. toString() {
  381. /** @type {?} */
  382. const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || '';
  383. return `ChildActivationEnd(path: '${path}')`;
  384. }
  385. }
  386. /**
  387. * \@description
  388. *
  389. * Represents the start of end of the Resolve phase of routing. See note on
  390. * `ActivationEnd` for use of this experimental API.
  391. *
  392. * \@publicApi
  393. */
  394. class ActivationStart {
  395. /**
  396. * @param {?} snapshot
  397. */
  398. constructor(snapshot) {
  399. this.snapshot = snapshot;
  400. }
  401. /**
  402. * @return {?}
  403. */
  404. toString() {
  405. /** @type {?} */
  406. const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || '';
  407. return `ActivationStart(path: '${path}')`;
  408. }
  409. }
  410. /**
  411. * \@description
  412. *
  413. * Represents the start of end of the Resolve phase of routing. See note on
  414. * `ActivationStart` for use of this experimental API.
  415. *
  416. * \@publicApi
  417. */
  418. class ActivationEnd {
  419. /**
  420. * @param {?} snapshot
  421. */
  422. constructor(snapshot) {
  423. this.snapshot = snapshot;
  424. }
  425. /**
  426. * @return {?}
  427. */
  428. toString() {
  429. /** @type {?} */
  430. const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || '';
  431. return `ActivationEnd(path: '${path}')`;
  432. }
  433. }
  434. /**
  435. * \@description
  436. *
  437. * Represents a scrolling event.
  438. *
  439. * \@publicApi
  440. */
  441. class Scroll {
  442. /**
  443. * @param {?} routerEvent
  444. * @param {?} position
  445. * @param {?} anchor
  446. */
  447. constructor(/** @docsNotRequired */
  448. routerEvent, /** @docsNotRequired */
  449. position, /** @docsNotRequired */
  450. anchor) {
  451. this.routerEvent = routerEvent;
  452. this.position = position;
  453. this.anchor = anchor;
  454. }
  455. /**
  456. * @return {?}
  457. */
  458. toString() {
  459. /** @type {?} */
  460. const pos = this.position ? `${this.position[0]}, ${this.position[1]}` : null;
  461. return `Scroll(anchor: '${this.anchor}', position: '${pos}')`;
  462. }
  463. }
  464. /**
  465. * @fileoverview added by tsickle
  466. * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
  467. */
  468. /**
  469. * This component is used internally within the router to be a placeholder when an empty
  470. * router-outlet is needed. For example, with a config such as:
  471. *
  472. * `{path: 'parent', outlet: 'nav', children: [...]}`
  473. *
  474. * In order to render, there needs to be a component on this config, which will default
  475. * to this `EmptyOutletComponent`.
  476. */
  477. class EmptyOutletComponent {
  478. }
  479. EmptyOutletComponent.decorators = [
  480. { type: Component, args: [{ template: `<router-outlet></router-outlet>` }] }
  481. ];
  482. /**
  483. * @fileoverview added by tsickle
  484. * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
  485. */
  486. /**
  487. * @license
  488. * Copyright Google Inc. All Rights Reserved.
  489. *
  490. * Use of this source code is governed by an MIT-style license that can be
  491. * found in the LICENSE file at https://angular.io/license
  492. */
  493. /** *
  494. * \@description
  495. *
  496. * Name of the primary outlet.
  497. *
  498. * \@publicApi
  499. @type {?} */
  500. const PRIMARY_OUTLET = 'primary';
  501. class ParamsAsMap {
  502. /**
  503. * @param {?} params
  504. */
  505. constructor(params) { this.params = params || {}; }
  506. /**
  507. * @param {?} name
  508. * @return {?}
  509. */
  510. has(name) { return this.params.hasOwnProperty(name); }
  511. /**
  512. * @param {?} name
  513. * @return {?}
  514. */
  515. get(name) {
  516. if (this.has(name)) {
  517. /** @type {?} */
  518. const v = this.params[name];
  519. return Array.isArray(v) ? v[0] : v;
  520. }
  521. return null;
  522. }
  523. /**
  524. * @param {?} name
  525. * @return {?}
  526. */
  527. getAll(name) {
  528. if (this.has(name)) {
  529. /** @type {?} */
  530. const v = this.params[name];
  531. return Array.isArray(v) ? v : [v];
  532. }
  533. return [];
  534. }
  535. /**
  536. * @return {?}
  537. */
  538. get keys() { return Object.keys(this.params); }
  539. }
  540. /**
  541. * Convert a `Params` instance to a `ParamMap`.
  542. *
  543. * \@publicApi
  544. * @param {?} params
  545. * @return {?}
  546. */
  547. function convertToParamMap(params) {
  548. return new ParamsAsMap(params);
  549. }
  550. /** @type {?} */
  551. const NAVIGATION_CANCELING_ERROR = 'ngNavigationCancelingError';
  552. /**
  553. * @param {?} message
  554. * @return {?}
  555. */
  556. function navigationCancelingError(message) {
  557. /** @type {?} */
  558. const error = Error('NavigationCancelingError: ' + message);
  559. (/** @type {?} */ (error))[NAVIGATION_CANCELING_ERROR] = true;
  560. return error;
  561. }
  562. /**
  563. * @param {?} error
  564. * @return {?}
  565. */
  566. function isNavigationCancelingError(error) {
  567. return error && (/** @type {?} */ (error))[NAVIGATION_CANCELING_ERROR];
  568. }
  569. /**
  570. * @param {?} segments
  571. * @param {?} segmentGroup
  572. * @param {?} route
  573. * @return {?}
  574. */
  575. function defaultUrlMatcher(segments, segmentGroup, route) {
  576. /** @type {?} */
  577. const parts = /** @type {?} */ ((route.path)).split('/');
  578. if (parts.length > segments.length) {
  579. // The actual URL is shorter than the config, no match
  580. return null;
  581. }
  582. if (route.pathMatch === 'full' &&
  583. (segmentGroup.hasChildren() || parts.length < segments.length)) {
  584. // The config is longer than the actual URL but we are looking for a full match, return null
  585. return null;
  586. }
  587. /** @type {?} */
  588. const posParams = {};
  589. // Check each config part against the actual URL
  590. for (let index = 0; index < parts.length; index++) {
  591. /** @type {?} */
  592. const part = parts[index];
  593. /** @type {?} */
  594. const segment = segments[index];
  595. /** @type {?} */
  596. const isParameter = part.startsWith(':');
  597. if (isParameter) {
  598. posParams[part.substring(1)] = segment;
  599. }
  600. else if (part !== segment.path) {
  601. // The actual URL part does not match the config, no match
  602. return null;
  603. }
  604. }
  605. return { consumed: segments.slice(0, parts.length), posParams };
  606. }
  607. /**
  608. * @fileoverview added by tsickle
  609. * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
  610. */
  611. class LoadedRouterConfig {
  612. /**
  613. * @param {?} routes
  614. * @param {?} module
  615. */
  616. constructor(routes, module) {
  617. this.routes = routes;
  618. this.module = module;
  619. }
  620. }
  621. /**
  622. * @param {?} config
  623. * @param {?=} parentPath
  624. * @return {?}
  625. */
  626. function validateConfig(config, parentPath = '') {
  627. // forEach doesn't iterate undefined values
  628. for (let i = 0; i < config.length; i++) {
  629. /** @type {?} */
  630. const route = config[i];
  631. /** @type {?} */
  632. const fullPath = getFullPath(parentPath, route);
  633. validateNode(route, fullPath);
  634. }
  635. }
  636. /**
  637. * @param {?} route
  638. * @param {?} fullPath
  639. * @return {?}
  640. */
  641. function validateNode(route, fullPath) {
  642. if (!route) {
  643. throw new Error(`
  644. Invalid configuration of route '${fullPath}': Encountered undefined route.
  645. The reason might be an extra comma.
  646. Example:
  647. const routes: Routes = [
  648. { path: '', redirectTo: '/dashboard', pathMatch: 'full' },
  649. { path: 'dashboard', component: DashboardComponent },, << two commas
  650. { path: 'detail/:id', component: HeroDetailComponent }
  651. ];
  652. `);
  653. }
  654. if (Array.isArray(route)) {
  655. throw new Error(`Invalid configuration of route '${fullPath}': Array cannot be specified`);
  656. }
  657. if (!route.component && !route.children && !route.loadChildren &&
  658. (route.outlet && route.outlet !== PRIMARY_OUTLET)) {
  659. throw new Error(`Invalid configuration of route '${fullPath}': a componentless route without children or loadChildren cannot have a named outlet set`);
  660. }
  661. if (route.redirectTo && route.children) {
  662. throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and children cannot be used together`);
  663. }
  664. if (route.redirectTo && route.loadChildren) {
  665. throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and loadChildren cannot be used together`);
  666. }
  667. if (route.children && route.loadChildren) {
  668. throw new Error(`Invalid configuration of route '${fullPath}': children and loadChildren cannot be used together`);
  669. }
  670. if (route.redirectTo && route.component) {
  671. throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and component cannot be used together`);
  672. }
  673. if (route.path && route.matcher) {
  674. throw new Error(`Invalid configuration of route '${fullPath}': path and matcher cannot be used together`);
  675. }
  676. if (route.redirectTo === void 0 && !route.component && !route.children && !route.loadChildren) {
  677. throw new Error(`Invalid configuration of route '${fullPath}'. One of the following must be provided: component, redirectTo, children or loadChildren`);
  678. }
  679. if (route.path === void 0 && route.matcher === void 0) {
  680. throw new Error(`Invalid configuration of route '${fullPath}': routes must have either a path or a matcher specified`);
  681. }
  682. if (typeof route.path === 'string' && route.path.charAt(0) === '/') {
  683. throw new Error(`Invalid configuration of route '${fullPath}': path cannot start with a slash`);
  684. }
  685. if (route.path === '' && route.redirectTo !== void 0 && route.pathMatch === void 0) {
  686. /** @type {?} */
  687. const exp = `The default value of 'pathMatch' is 'prefix', but often the intent is to use 'full'.`;
  688. throw new Error(`Invalid configuration of route '{path: "${fullPath}", redirectTo: "${route.redirectTo}"}': please provide 'pathMatch'. ${exp}`);
  689. }
  690. if (route.pathMatch !== void 0 && route.pathMatch !== 'full' && route.pathMatch !== 'prefix') {
  691. throw new Error(`Invalid configuration of route '${fullPath}': pathMatch can only be set to 'prefix' or 'full'`);
  692. }
  693. if (route.children) {
  694. validateConfig(route.children, fullPath);
  695. }
  696. }
  697. /**
  698. * @param {?} parentPath
  699. * @param {?} currentRoute
  700. * @return {?}
  701. */
  702. function getFullPath(parentPath, currentRoute) {
  703. if (!currentRoute) {
  704. return parentPath;
  705. }
  706. if (!parentPath && !currentRoute.path) {
  707. return '';
  708. }
  709. else if (parentPath && !currentRoute.path) {
  710. return `${parentPath}/`;
  711. }
  712. else if (!parentPath && currentRoute.path) {
  713. return currentRoute.path;
  714. }
  715. else {
  716. return `${parentPath}/${currentRoute.path}`;
  717. }
  718. }
  719. /**
  720. * Makes a copy of the config and adds any default required properties.
  721. * @param {?} r
  722. * @return {?}
  723. */
  724. function standardizeConfig(r) {
  725. /** @type {?} */
  726. const children = r.children && r.children.map(standardizeConfig);
  727. /** @type {?} */
  728. const c = children ? Object.assign({}, r, { children }) : Object.assign({}, r);
  729. if (!c.component && (children || c.loadChildren) && (c.outlet && c.outlet !== PRIMARY_OUTLET)) {
  730. c.component = EmptyOutletComponent;
  731. }
  732. return c;
  733. }
  734. /**
  735. * @fileoverview added by tsickle
  736. * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
  737. */
  738. /**
  739. * @param {?} a
  740. * @param {?} b
  741. * @return {?}
  742. */
  743. function shallowEqualArrays(a, b) {
  744. if (a.length !== b.length)
  745. return false;
  746. for (let i = 0; i < a.length; ++i) {
  747. if (!shallowEqual(a[i], b[i]))
  748. return false;
  749. }
  750. return true;
  751. }
  752. /**
  753. * @param {?} a
  754. * @param {?} b
  755. * @return {?}
  756. */
  757. function shallowEqual(a, b) {
  758. /** @type {?} */
  759. const k1 = Object.keys(a);
  760. /** @type {?} */
  761. const k2 = Object.keys(b);
  762. if (k1.length != k2.length) {
  763. return false;
  764. }
  765. /** @type {?} */
  766. let key;
  767. for (let i = 0; i < k1.length; i++) {
  768. key = k1[i];
  769. if (a[key] !== b[key]) {
  770. return false;
  771. }
  772. }
  773. return true;
  774. }
  775. /**
  776. * Flattens single-level nested arrays.
  777. * @template T
  778. * @param {?} arr
  779. * @return {?}
  780. */
  781. function flatten(arr) {
  782. return Array.prototype.concat.apply([], arr);
  783. }
  784. /**
  785. * Return the last element of an array.
  786. * @template T
  787. * @param {?} a
  788. * @return {?}
  789. */
  790. function last$1(a) {
  791. return a.length > 0 ? a[a.length - 1] : null;
  792. }
  793. /**
  794. * @template K, V
  795. * @param {?} map
  796. * @param {?} callback
  797. * @return {?}
  798. */
  799. function forEach(map$$1, callback) {
  800. for (const prop in map$$1) {
  801. if (map$$1.hasOwnProperty(prop)) {
  802. callback(map$$1[prop], prop);
  803. }
  804. }
  805. }
  806. /**
  807. * @template A, B
  808. * @param {?} obj
  809. * @param {?} fn
  810. * @return {?}
  811. */
  812. function waitForMap(obj, fn) {
  813. if (Object.keys(obj).length === 0) {
  814. return of({});
  815. }
  816. /** @type {?} */
  817. const waitHead = [];
  818. /** @type {?} */
  819. const waitTail = [];
  820. /** @type {?} */
  821. const res = {};
  822. forEach(obj, (a, k) => {
  823. /** @type {?} */
  824. const mapped = fn(k, a).pipe(map((r) => res[k] = r));
  825. if (k === PRIMARY_OUTLET) {
  826. waitHead.push(mapped);
  827. }
  828. else {
  829. waitTail.push(mapped);
  830. }
  831. });
  832. // Closure compiler has problem with using spread operator here. So just using Array.concat.
  833. return of.apply(null, waitHead.concat(waitTail)).pipe(concatAll(), last(), map(() => res));
  834. }
  835. /**
  836. * ANDs Observables by merging all input observables, reducing to an Observable verifying all
  837. * input Observables return `true`.
  838. * @param {?} observables
  839. * @return {?}
  840. */
  841. function andObservables(observables) {
  842. return observables.pipe(mergeAll(), every((result) => result === true));
  843. }
  844. /**
  845. * @template T
  846. * @param {?} value
  847. * @return {?}
  848. */
  849. function wrapIntoObservable(value) {
  850. if (ɵisObservable(value)) {
  851. return value;
  852. }
  853. if (ɵisPromise(value)) {
  854. // Use `Promise.resolve()` to wrap promise-like instances.
  855. // Required ie when a Resolver returns a AngularJS `$q` promise to correctly trigger the
  856. // change detection.
  857. return from(Promise.resolve(value));
  858. }
  859. return of(/** @type {?} */ (value));
  860. }
  861. /**
  862. * @fileoverview added by tsickle
  863. * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
  864. */
  865. /**
  866. * @return {?}
  867. */
  868. function createEmptyUrlTree() {
  869. return new UrlTree(new UrlSegmentGroup([], {}), {}, null);
  870. }
  871. /**
  872. * @param {?} container
  873. * @param {?} containee
  874. * @param {?} exact
  875. * @return {?}
  876. */
  877. function containsTree(container, containee, exact) {
  878. if (exact) {
  879. return equalQueryParams(container.queryParams, containee.queryParams) &&
  880. equalSegmentGroups(container.root, containee.root);
  881. }
  882. return containsQueryParams(container.queryParams, containee.queryParams) &&
  883. containsSegmentGroup(container.root, containee.root);
  884. }
  885. /**
  886. * @param {?} container
  887. * @param {?} containee
  888. * @return {?}
  889. */
  890. function equalQueryParams(container, containee) {
  891. // TODO: This does not handle array params correctly.
  892. return shallowEqual(container, containee);
  893. }
  894. /**
  895. * @param {?} container
  896. * @param {?} containee
  897. * @return {?}
  898. */
  899. function equalSegmentGroups(container, containee) {
  900. if (!equalPath(container.segments, containee.segments))
  901. return false;
  902. if (container.numberOfChildren !== containee.numberOfChildren)
  903. return false;
  904. for (const c in containee.children) {
  905. if (!container.children[c])
  906. return false;
  907. if (!equalSegmentGroups(container.children[c], containee.children[c]))
  908. return false;
  909. }
  910. return true;
  911. }
  912. /**
  913. * @param {?} container
  914. * @param {?} containee
  915. * @return {?}
  916. */
  917. function containsQueryParams(container, containee) {
  918. // TODO: This does not handle array params correctly.
  919. return Object.keys(containee).length <= Object.keys(container).length &&
  920. Object.keys(containee).every(key => containee[key] === container[key]);
  921. }
  922. /**
  923. * @param {?} container
  924. * @param {?} containee
  925. * @return {?}
  926. */
  927. function containsSegmentGroup(container, containee) {
  928. return containsSegmentGroupHelper(container, containee, containee.segments);
  929. }
  930. /**
  931. * @param {?} container
  932. * @param {?} containee
  933. * @param {?} containeePaths
  934. * @return {?}
  935. */
  936. function containsSegmentGroupHelper(container, containee, containeePaths) {
  937. if (container.segments.length > containeePaths.length) {
  938. /** @type {?} */
  939. const current = container.segments.slice(0, containeePaths.length);
  940. if (!equalPath(current, containeePaths))
  941. return false;
  942. if (containee.hasChildren())
  943. return false;
  944. return true;
  945. }
  946. else if (container.segments.length === containeePaths.length) {
  947. if (!equalPath(container.segments, containeePaths))
  948. return false;
  949. for (const c in containee.children) {
  950. if (!container.children[c])
  951. return false;
  952. if (!containsSegmentGroup(container.children[c], containee.children[c]))
  953. return false;
  954. }
  955. return true;
  956. }
  957. else {
  958. /** @type {?} */
  959. const current = containeePaths.slice(0, container.segments.length);
  960. /** @type {?} */
  961. const next = containeePaths.slice(container.segments.length);
  962. if (!equalPath(container.segments, current))
  963. return false;
  964. if (!container.children[PRIMARY_OUTLET])
  965. return false;
  966. return containsSegmentGroupHelper(container.children[PRIMARY_OUTLET], containee, next);
  967. }
  968. }
  969. /**
  970. * \@description
  971. *
  972. * Represents the parsed URL.
  973. *
  974. * Since a router state is a tree, and the URL is nothing but a serialized state, the URL is a
  975. * serialized tree.
  976. * UrlTree is a data structure that provides a lot of affordances in dealing with URLs
  977. *
  978. * \@usageNotes
  979. * ### Example
  980. *
  981. * ```
  982. * \@Component({templateUrl:'template.html'})
  983. * class MyComponent {
  984. * constructor(router: Router) {
  985. * const tree: UrlTree =
  986. * router.parseUrl('/team/33/(user/victor//support:help)?debug=true#fragment');
  987. * const f = tree.fragment; // return 'fragment'
  988. * const q = tree.queryParams; // returns {debug: 'true'}
  989. * const g: UrlSegmentGroup = tree.root.children[PRIMARY_OUTLET];
  990. * const s: UrlSegment[] = g.segments; // returns 2 segments 'team' and '33'
  991. * g.children[PRIMARY_OUTLET].segments; // returns 2 segments 'user' and 'victor'
  992. * g.children['support'].segments; // return 1 segment 'help'
  993. * }
  994. * }
  995. * ```
  996. *
  997. * \@publicApi
  998. */
  999. class UrlTree {
  1000. /**
  1001. * \@internal
  1002. * @param {?} root
  1003. * @param {?} queryParams
  1004. * @param {?} fragment
  1005. */
  1006. constructor(root, queryParams, fragment) {
  1007. this.root = root;
  1008. this.queryParams = queryParams;
  1009. this.fragment = fragment;
  1010. }
  1011. /**
  1012. * @return {?}
  1013. */
  1014. get queryParamMap() {
  1015. if (!this._queryParamMap) {
  1016. this._queryParamMap = convertToParamMap(this.queryParams);
  1017. }
  1018. return this._queryParamMap;
  1019. }
  1020. /**
  1021. * \@docsNotRequired
  1022. * @return {?}
  1023. */
  1024. toString() { return DEFAULT_SERIALIZER.serialize(this); }
  1025. }
  1026. /**
  1027. * \@description
  1028. *
  1029. * Represents the parsed URL segment group.
  1030. *
  1031. * See `UrlTree` for more information.
  1032. *
  1033. * \@publicApi
  1034. */
  1035. class UrlSegmentGroup {
  1036. /**
  1037. * @param {?} segments
  1038. * @param {?} children
  1039. */
  1040. constructor(segments, children) {
  1041. this.segments = segments;
  1042. this.children = children;
  1043. /**
  1044. * The parent node in the url tree
  1045. */
  1046. this.parent = null;
  1047. forEach(children, (v, k) => v.parent = this);
  1048. }
  1049. /**
  1050. * Whether the segment has child segments
  1051. * @return {?}
  1052. */
  1053. hasChildren() { return this.numberOfChildren > 0; }
  1054. /**
  1055. * Number of child segments
  1056. * @return {?}
  1057. */
  1058. get numberOfChildren() { return Object.keys(this.children).length; }
  1059. /**
  1060. * \@docsNotRequired
  1061. * @return {?}
  1062. */
  1063. toString() { return serializePaths(this); }
  1064. }
  1065. /**
  1066. * \@description
  1067. *
  1068. * Represents a single URL segment.
  1069. *
  1070. * A UrlSegment is a part of a URL between the two slashes. It contains a path and the matrix
  1071. * parameters associated with the segment.
  1072. *
  1073. * \@usageNotes
  1074. *  ### Example
  1075. *
  1076. * ```
  1077. * \@Component({templateUrl:'template.html'})
  1078. * class MyComponent {
  1079. * constructor(router: Router) {
  1080. * const tree: UrlTree = router.parseUrl('/team;id=33');
  1081. * const g: UrlSegmentGroup = tree.root.children[PRIMARY_OUTLET];
  1082. * const s: UrlSegment[] = g.segments;
  1083. * s[0].path; // returns 'team'
  1084. * s[0].parameters; // returns {id: 33}
  1085. * }
  1086. * }
  1087. * ```
  1088. *
  1089. * \@publicApi
  1090. */
  1091. class UrlSegment {
  1092. /**
  1093. * @param {?} path
  1094. * @param {?} parameters
  1095. */
  1096. constructor(path, parameters) {
  1097. this.path = path;
  1098. this.parameters = parameters;
  1099. }
  1100. /**
  1101. * @return {?}
  1102. */
  1103. get parameterMap() {
  1104. if (!this._parameterMap) {
  1105. this._parameterMap = convertToParamMap(this.parameters);
  1106. }
  1107. return this._parameterMap;
  1108. }
  1109. /**
  1110. * \@docsNotRequired
  1111. * @return {?}
  1112. */
  1113. toString() { return serializePath(this); }
  1114. }
  1115. /**
  1116. * @param {?} as
  1117. * @param {?} bs
  1118. * @return {?}
  1119. */
  1120. function equalSegments(as, bs) {
  1121. return equalPath(as, bs) && as.every((a, i) => shallowEqual(a.parameters, bs[i].parameters));
  1122. }
  1123. /**
  1124. * @param {?} as
  1125. * @param {?} bs
  1126. * @return {?}
  1127. */
  1128. function equalPath(as, bs) {
  1129. if (as.length !== bs.length)
  1130. return false;
  1131. return as.every((a, i) => a.path === bs[i].path);
  1132. }
  1133. /**
  1134. * @template T
  1135. * @param {?} segment
  1136. * @param {?} fn
  1137. * @return {?}
  1138. */
  1139. function mapChildrenIntoArray(segment, fn) {
  1140. /** @type {?} */
  1141. let res = [];
  1142. forEach(segment.children, (child, childOutlet) => {
  1143. if (childOutlet === PRIMARY_OUTLET) {
  1144. res = res.concat(fn(child, childOutlet));
  1145. }
  1146. });
  1147. forEach(segment.children, (child, childOutlet) => {
  1148. if (childOutlet !== PRIMARY_OUTLET) {
  1149. res = res.concat(fn(child, childOutlet));
  1150. }
  1151. });
  1152. return res;
  1153. }
  1154. /**
  1155. * \@description
  1156. *
  1157. * Serializes and deserializes a URL string into a URL tree.
  1158. *
  1159. * The url serialization strategy is customizable. You can
  1160. * make all URLs case insensitive by providing a custom UrlSerializer.
  1161. *
  1162. * See `DefaultUrlSerializer` for an example of a URL serializer.
  1163. *
  1164. * \@publicApi
  1165. * @abstract
  1166. */
  1167. class UrlSerializer {
  1168. }
  1169. /**
  1170. * \@description
  1171. *
  1172. * A default implementation of the `UrlSerializer`.
  1173. *
  1174. * Example URLs:
  1175. *
  1176. * ```
  1177. * /inbox/33(popup:compose)
  1178. * /inbox/33;open=true/messages/44
  1179. * ```
  1180. *
  1181. * DefaultUrlSerializer uses parentheses to serialize secondary segments (e.g., popup:compose), the
  1182. * colon syntax to specify the outlet, and the ';parameter=value' syntax (e.g., open=true) to
  1183. * specify route specific parameters.
  1184. *
  1185. * \@publicApi
  1186. */
  1187. class DefaultUrlSerializer {
  1188. /**
  1189. * Parses a url into a `UrlTree`
  1190. * @param {?} url
  1191. * @return {?}
  1192. */
  1193. parse(url) {
  1194. /** @type {?} */
  1195. const p = new UrlParser(url);
  1196. return new UrlTree(p.parseRootSegment(), p.parseQueryParams(), p.parseFragment());
  1197. }
  1198. /**
  1199. * Converts a `UrlTree` into a url
  1200. * @param {?} tree
  1201. * @return {?}
  1202. */
  1203. serialize(tree) {
  1204. /** @type {?} */
  1205. const segment = `/${serializeSegment(tree.root, true)}`;
  1206. /** @type {?} */
  1207. const query = serializeQueryParams(tree.queryParams);
  1208. /** @type {?} */
  1209. const fragment = typeof tree.fragment === `string` ? `#${encodeUriFragment((/** @type {?} */ ((tree.fragment))))}` : '';
  1210. return `${segment}${query}${fragment}`;
  1211. }
  1212. }
  1213. /** @type {?} */
  1214. const DEFAULT_SERIALIZER = new DefaultUrlSerializer();
  1215. /**
  1216. * @param {?} segment
  1217. * @return {?}
  1218. */
  1219. function serializePaths(segment) {
  1220. return segment.segments.map(p => serializePath(p)).join('/');
  1221. }
  1222. /**
  1223. * @param {?} segment
  1224. * @param {?} root
  1225. * @return {?}
  1226. */
  1227. function serializeSegment(segment, root) {
  1228. if (!segment.hasChildren()) {
  1229. return serializePaths(segment);
  1230. }
  1231. if (root) {
  1232. /** @type {?} */
  1233. const primary = segment.children[PRIMARY_OUTLET] ?
  1234. serializeSegment(segment.children[PRIMARY_OUTLET], false) :
  1235. '';
  1236. /** @type {?} */
  1237. const children = [];
  1238. forEach(segment.children, (v, k) => {
  1239. if (k !== PRIMARY_OUTLET) {
  1240. children.push(`${k}:${serializeSegment(v, false)}`);
  1241. }
  1242. });
  1243. return children.length > 0 ? `${primary}(${children.join('//')})` : primary;
  1244. }
  1245. else {
  1246. /** @type {?} */
  1247. const children = mapChildrenIntoArray(segment, (v, k) => {
  1248. if (k === PRIMARY_OUTLET) {
  1249. return [serializeSegment(segment.children[PRIMARY_OUTLET], false)];
  1250. }
  1251. return [`${k}:${serializeSegment(v, false)}`];
  1252. });
  1253. return `${serializePaths(segment)}/(${children.join('//')})`;
  1254. }
  1255. }
  1256. /**
  1257. * Encodes a URI string with the default encoding. This function will only ever be called from
  1258. * `encodeUriQuery` or `encodeUriSegment` as it's the base set of encodings to be used. We need
  1259. * a custom encoding because encodeURIComponent is too aggressive and encodes stuff that doesn't
  1260. * have to be encoded per https://url.spec.whatwg.org.
  1261. * @param {?} s
  1262. * @return {?}
  1263. */
  1264. function encodeUriString(s) {
  1265. return encodeURIComponent(s)
  1266. .replace(/%40/g, '@')
  1267. .replace(/%3A/gi, ':')
  1268. .replace(/%24/g, '$')
  1269. .replace(/%2C/gi, ',');
  1270. }
  1271. /**
  1272. * This function should be used to encode both keys and values in a query string key/value. In
  1273. * the following URL, you need to call encodeUriQuery on "k" and "v":
  1274. *
  1275. * http://www.site.org/html;mk=mv?k=v#f
  1276. * @param {?} s
  1277. * @return {?}
  1278. */
  1279. function encodeUriQuery(s) {
  1280. return encodeUriString(s).replace(/%3B/gi, ';');
  1281. }
  1282. /**
  1283. * This function should be used to encode a URL fragment. In the following URL, you need to call
  1284. * encodeUriFragment on "f":
  1285. *
  1286. * http://www.site.org/html;mk=mv?k=v#f
  1287. * @param {?} s
  1288. * @return {?}
  1289. */
  1290. function encodeUriFragment(s) {
  1291. return encodeURI(s);
  1292. }
  1293. /**
  1294. * This function should be run on any URI segment as well as the key and value in a key/value
  1295. * pair for matrix params. In the following URL, you need to call encodeUriSegment on "html",
  1296. * "mk", and "mv":
  1297. *
  1298. * http://www.site.org/html;mk=mv?k=v#f
  1299. * @param {?} s
  1300. * @return {?}
  1301. */
  1302. function encodeUriSegment(s) {
  1303. return encodeUriString(s).replace(/\(/g, '%28').replace(/\)/g, '%29').replace(/%26/gi, '&');
  1304. }
  1305. /**
  1306. * @param {?} s
  1307. * @return {?}
  1308. */
  1309. function decode(s) {
  1310. return decodeURIComponent(s);
  1311. }
  1312. /**
  1313. * @param {?} s
  1314. * @return {?}
  1315. */
  1316. function decodeQuery(s) {
  1317. return decode(s.replace(/\+/g, '%20'));
  1318. }
  1319. /**
  1320. * @param {?} path
  1321. * @return {?}
  1322. */
  1323. function serializePath(path) {
  1324. return `${encodeUriSegment(path.path)}${serializeMatrixParams(path.parameters)}`;
  1325. }
  1326. /**
  1327. * @param {?} params
  1328. * @return {?}
  1329. */
  1330. function serializeMatrixParams(params) {
  1331. return Object.keys(params)
  1332. .map(key => `;${encodeUriSegment(key)}=${encodeUriSegment(params[key])}`)
  1333. .join('');
  1334. }
  1335. /**
  1336. * @param {?} params
  1337. * @return {?}
  1338. */
  1339. function serializeQueryParams(params) {
  1340. /** @type {?} */
  1341. const strParams = Object.keys(params).map((name) => {
  1342. /** @type {?} */
  1343. const value = params[name];
  1344. return Array.isArray(value) ?
  1345. value.map(v => `${encodeUriQuery(name)}=${encodeUriQuery(v)}`).join('&') :
  1346. `${encodeUriQuery(name)}=${encodeUriQuery(value)}`;
  1347. });
  1348. return strParams.length ? `?${strParams.join("&")}` : '';
  1349. }
  1350. /** @type {?} */
  1351. const SEGMENT_RE = /^[^\/()?;=#]+/;
  1352. /**
  1353. * @param {?} str
  1354. * @return {?}
  1355. */
  1356. function matchSegments(str) {
  1357. /** @type {?} */
  1358. const match = str.match(SEGMENT_RE);
  1359. return match ? match[0] : '';
  1360. }
  1361. /** @type {?} */
  1362. const QUERY_PARAM_RE = /^[^=?&#]+/;
  1363. /**
  1364. * @param {?} str
  1365. * @return {?}
  1366. */
  1367. function matchQueryParams(str) {
  1368. /** @type {?} */
  1369. const match = str.match(QUERY_PARAM_RE);
  1370. return match ? match[0] : '';
  1371. }
  1372. /** @type {?} */
  1373. const QUERY_PARAM_VALUE_RE = /^[^?&#]+/;
  1374. /**
  1375. * @param {?} str
  1376. * @return {?}
  1377. */
  1378. function matchUrlQueryParamValue(str) {
  1379. /** @type {?} */
  1380. const match = str.match(QUERY_PARAM_VALUE_RE);
  1381. return match ? match[0] : '';
  1382. }
  1383. class UrlParser {
  1384. /**
  1385. * @param {?} url
  1386. */
  1387. constructor(url) {
  1388. this.url = url;
  1389. this.remaining = url;
  1390. }
  1391. /**
  1392. * @return {?}
  1393. */
  1394. parseRootSegment() {
  1395. this.consumeOptional('/');
  1396. if (this.remaining === '' || this.peekStartsWith('?') || this.peekStartsWith('#')) {
  1397. return new UrlSegmentGroup([], {});
  1398. }
  1399. // The root segment group never has segments
  1400. return new UrlSegmentGroup([], this.parseChildren());
  1401. }
  1402. /**
  1403. * @return {?}
  1404. */
  1405. parseQueryParams() {
  1406. /** @type {?} */
  1407. const params = {};
  1408. if (this.consumeOptional('?')) {
  1409. do {
  1410. this.parseQueryParam(params);
  1411. } while (this.consumeOptional('&'));
  1412. }
  1413. return params;
  1414. }
  1415. /**
  1416. * @return {?}
  1417. */
  1418. parseFragment() {
  1419. return this.consumeOptional('#') ? decodeURIComponent(this.remaining) : null;
  1420. }
  1421. /**
  1422. * @return {?}
  1423. */
  1424. parseChildren() {
  1425. if (this.remaining === '') {
  1426. return {};
  1427. }
  1428. this.consumeOptional('/');
  1429. /** @type {?} */
  1430. const segments = [];
  1431. if (!this.peekStartsWith('(')) {
  1432. segments.push(this.parseSegment());
  1433. }
  1434. while (this.peekStartsWith('/') && !this.peekStartsWith('//') && !this.peekStartsWith('/(')) {
  1435. this.capture('/');
  1436. segments.push(this.parseSegment());
  1437. }
  1438. /** @type {?} */
  1439. let children = {};
  1440. if (this.peekStartsWith('/(')) {
  1441. this.capture('/');
  1442. children = this.parseParens(true);
  1443. }
  1444. /** @type {?} */
  1445. let res = {};
  1446. if (this.peekStartsWith('(')) {
  1447. res = this.parseParens(false);
  1448. }
  1449. if (segments.length > 0 || Object.keys(children).length > 0) {
  1450. res[PRIMARY_OUTLET] = new UrlSegmentGroup(segments, children);
  1451. }
  1452. return res;
  1453. }
  1454. /**
  1455. * @return {?}
  1456. */
  1457. parseSegment() {
  1458. /** @type {?} */
  1459. const path = matchSegments(this.remaining);
  1460. if (path === '' && this.peekStartsWith(';')) {
  1461. throw new Error(`Empty path url segment cannot have parameters: '${this.remaining}'.`);
  1462. }
  1463. this.capture(path);
  1464. return new UrlSegment(decode(path), this.parseMatrixParams());
  1465. }
  1466. /**
  1467. * @return {?}
  1468. */
  1469. parseMatrixParams() {
  1470. /** @type {?} */
  1471. const params = {};
  1472. while (this.consumeOptional(';')) {
  1473. this.parseParam(params);
  1474. }
  1475. return params;
  1476. }
  1477. /**
  1478. * @param {?} params
  1479. * @return {?}
  1480. */
  1481. parseParam(params) {
  1482. /** @type {?} */
  1483. const key = matchSegments(this.remaining);
  1484. if (!key) {
  1485. return;
  1486. }
  1487. this.capture(key);
  1488. /** @type {?} */
  1489. let value = '';
  1490. if (this.consumeOptional('=')) {
  1491. /** @type {?} */
  1492. const valueMatch = matchSegments(this.remaining);
  1493. if (valueMatch) {
  1494. value = valueMatch;
  1495. this.capture(value);
  1496. }
  1497. }
  1498. params[decode(key)] = decode(value);
  1499. }
  1500. /**
  1501. * @param {?} params
  1502. * @return {?}
  1503. */
  1504. parseQueryParam(params) {
  1505. /** @type {?} */
  1506. const key = matchQueryParams(this.remaining);
  1507. if (!key) {
  1508. return;
  1509. }
  1510. this.capture(key);
  1511. /** @type {?} */
  1512. let value = '';
  1513. if (this.consumeOptional('=')) {
  1514. /** @type {?} */
  1515. const valueMatch = matchUrlQueryParamValue(this.remaining);
  1516. if (valueMatch) {
  1517. value = valueMatch;
  1518. this.capture(value);
  1519. }
  1520. }
  1521. /** @type {?} */
  1522. const decodedKey = decodeQuery(key);
  1523. /** @type {?} */
  1524. const decodedVal = decodeQuery(value);
  1525. if (params.hasOwnProperty(decodedKey)) {
  1526. /** @type {?} */
  1527. let currentVal = params[decodedKey];
  1528. if (!Array.isArray(currentVal)) {
  1529. currentVal = [currentVal];
  1530. params[decodedKey] = currentVal;
  1531. }
  1532. currentVal.push(decodedVal);
  1533. }
  1534. else {
  1535. // Create a new value
  1536. params[decodedKey] = decodedVal;
  1537. }
  1538. }
  1539. /**
  1540. * @param {?} allowPrimary
  1541. * @return {?}
  1542. */
  1543. parseParens(allowPrimary) {
  1544. /** @type {?} */
  1545. const segments = {};
  1546. this.capture('(');
  1547. while (!this.consumeOptional(')') && this.remaining.length > 0) {
  1548. /** @type {?} */
  1549. const path = matchSegments(this.remaining);
  1550. /** @type {?} */
  1551. const next = this.remaining[path.length];
  1552. // if is is not one of these characters, then the segment was unescaped
  1553. // or the group was not closed
  1554. if (next !== '/' && next !== ')' && next !== ';') {
  1555. throw new Error(`Cannot parse url '${this.url}'`);
  1556. }
  1557. /** @type {?} */
  1558. let outletName = /** @type {?} */ ((undefined));
  1559. if (path.indexOf(':') > -1) {
  1560. outletName = path.substr(0, path.indexOf(':'));
  1561. this.capture(outletName);
  1562. this.capture(':');
  1563. }
  1564. else if (allowPrimary) {
  1565. outletName = PRIMARY_OUTLET;
  1566. }
  1567. /** @type {?} */
  1568. const children = this.parseChildren();
  1569. segments[outletName] = Object.keys(children).length === 1 ? children[PRIMARY_OUTLET] :
  1570. new UrlSegmentGroup([], children);
  1571. this.consumeOptional('//');
  1572. }
  1573. return segments;
  1574. }
  1575. /**
  1576. * @param {?} str
  1577. * @return {?}
  1578. */
  1579. peekStartsWith(str) { return this.remaining.startsWith(str); }
  1580. /**
  1581. * @param {?} str
  1582. * @return {?}
  1583. */
  1584. consumeOptional(str) {
  1585. if (this.peekStartsWith(str)) {
  1586. this.remaining = this.remaining.substring(str.length);
  1587. return true;
  1588. }
  1589. return false;
  1590. }
  1591. /**
  1592. * @param {?} str
  1593. * @return {?}
  1594. */
  1595. capture(str) {
  1596. if (!this.consumeOptional(str)) {
  1597. throw new Error(`Expected "${str}".`);
  1598. }
  1599. }
  1600. }
  1601. /**
  1602. * @fileoverview added by tsickle
  1603. * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
  1604. */
  1605. /**
  1606. * @license
  1607. * Copyright Google Inc. All Rights Reserved.
  1608. *
  1609. * Use of this source code is governed by an MIT-style license that can be
  1610. * found in the LICENSE file at https://angular.io/license
  1611. */
  1612. /**
  1613. * @template T
  1614. */
  1615. class Tree {
  1616. /**
  1617. * @param {?} root
  1618. */
  1619. constructor(root) { this._root = root; }
  1620. /**
  1621. * @return {?}
  1622. */
  1623. get root() { return this._root.value; }
  1624. /**
  1625. * \@internal
  1626. * @param {?} t
  1627. * @return {?}
  1628. */
  1629. parent(t) {
  1630. /** @type {?} */
  1631. const p = this.pathFromRoot(t);
  1632. return p.length > 1 ? p[p.length - 2] : null;
  1633. }
  1634. /**
  1635. * \@internal
  1636. * @param {?} t
  1637. * @return {?}
  1638. */
  1639. children(t) {
  1640. /** @type {?} */
  1641. const n = findNode(t, this._root);
  1642. return n ? n.children.map(t => t.value) : [];
  1643. }
  1644. /**
  1645. * \@internal
  1646. * @param {?} t
  1647. * @return {?}
  1648. */
  1649. firstChild(t) {
  1650. /** @type {?} */
  1651. const n = findNode(t, this._root);
  1652. return n && n.children.length > 0 ? n.children[0].value : null;
  1653. }
  1654. /**
  1655. * \@internal
  1656. * @param {?} t
  1657. * @return {?}
  1658. */
  1659. siblings(t) {
  1660. /** @type {?} */
  1661. const p = findPath(t, this._root);
  1662. if (p.length < 2)
  1663. return [];
  1664. /** @type {?} */
  1665. const c = p[p.length - 2].children.map(c => c.value);
  1666. return c.filter(cc => cc !== t);
  1667. }
  1668. /**
  1669. * \@internal
  1670. * @param {?} t
  1671. * @return {?}
  1672. */
  1673. pathFromRoot(t) { return findPath(t, this._root).map(s => s.value); }
  1674. }
  1675. /**
  1676. * @template T
  1677. * @param {?} value
  1678. * @param {?} node
  1679. * @return {?}
  1680. */
  1681. function findNode(value, node) {
  1682. if (value === node.value)
  1683. return node;
  1684. for (const child of node.children) {
  1685. /** @type {?} */
  1686. const node = findNode(value, child);
  1687. if (node)
  1688. return node;
  1689. }
  1690. return null;
  1691. }
  1692. /**
  1693. * @template T
  1694. * @param {?} value
  1695. * @param {?} node
  1696. * @return {?}
  1697. */
  1698. function findPath(value, node) {
  1699. if (value === node.value)
  1700. return [node];
  1701. for (const child of node.children) {
  1702. /** @type {?} */
  1703. const path = findPath(value, child);
  1704. if (path.length) {
  1705. path.unshift(node);
  1706. return path;
  1707. }
  1708. }
  1709. return [];
  1710. }
  1711. /**
  1712. * @template T
  1713. */
  1714. class TreeNode {
  1715. /**
  1716. * @param {?} value
  1717. * @param {?} children
  1718. */
  1719. constructor(value, children) {
  1720. this.value = value;
  1721. this.children = children;
  1722. }
  1723. /**
  1724. * @return {?}
  1725. */
  1726. toString() { return `TreeNode(${this.value})`; }
  1727. }
  1728. /**
  1729. * @template T
  1730. * @param {?} node
  1731. * @return {?}
  1732. */
  1733. function nodeChildrenAsMap(node) {
  1734. /** @type {?} */
  1735. const map$$1 = {};
  1736. if (node) {
  1737. node.children.forEach(child => map$$1[child.value.outlet] = child);
  1738. }
  1739. return map$$1;
  1740. }
  1741. /**
  1742. * @fileoverview added by tsickle
  1743. * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
  1744. */
  1745. /**
  1746. * \@description
  1747. *
  1748. * Represents the state of the router.
  1749. *
  1750. * RouterState is a tree of activated routes. Every node in this tree knows about the "consumed" URL
  1751. * segments, the extracted parameters, and the resolved data.
  1752. *
  1753. * \@usageNotes
  1754. * ### Example
  1755. *
  1756. * ```
  1757. * \@Component({templateUrl:'template.html'})
  1758. * class MyComponent {
  1759. * constructor(router: Router) {
  1760. * const state: RouterState = router.routerState;
  1761. * const root: ActivatedRoute = state.root;
  1762. * const child = root.firstChild;
  1763. * const id: Observable<string> = child.params.map(p => p.id);
  1764. * //...
  1765. * }
  1766. * }
  1767. * ```
  1768. *
  1769. * See `ActivatedRoute` for more information.
  1770. *
  1771. * \@publicApi
  1772. */
  1773. class RouterState extends Tree {
  1774. /**
  1775. * \@internal
  1776. * @param {?} root
  1777. * @param {?} snapshot
  1778. */
  1779. constructor(root, snapshot) {
  1780. super(root);
  1781. this.snapshot = snapshot;
  1782. setRouterState(/** @type {?} */ (this), root);
  1783. }
  1784. /**
  1785. * @return {?}
  1786. */
  1787. toString() { return this.snapshot.toString(); }
  1788. }
  1789. /**
  1790. * @param {?} urlTree
  1791. * @param {?} rootComponent
  1792. * @return {?}
  1793. */
  1794. function createEmptyState(urlTree, rootComponent) {
  1795. /** @type {?} */
  1796. const snapshot = createEmptyStateSnapshot(urlTree, rootComponent);
  1797. /** @type {?} */
  1798. const emptyUrl = new BehaviorSubject([new UrlSegment('', {})]);
  1799. /** @type {?} */
  1800. const emptyParams = new BehaviorSubject({});
  1801. /** @type {?} */
  1802. const emptyData = new BehaviorSubject({});
  1803. /** @type {?} */
  1804. const emptyQueryParams = new BehaviorSubject({});
  1805. /** @type {?} */
  1806. const fragment = new BehaviorSubject('');
  1807. /** @type {?} */
  1808. const activated = new ActivatedRoute(emptyUrl, emptyParams, emptyQueryParams, fragment, emptyData, PRIMARY_OUTLET, rootComponent, snapshot.root);
  1809. activated.snapshot = snapshot.root;
  1810. return new RouterState(new TreeNode(activated, []), snapshot);
  1811. }
  1812. /**
  1813. * @param {?} urlTree
  1814. * @param {?} rootComponent
  1815. * @return {?}
  1816. */
  1817. function createEmptyStateSnapshot(urlTree, rootComponent) {
  1818. /** @type {?} */
  1819. const emptyParams = {};
  1820. /** @type {?} */
  1821. const emptyData = {};
  1822. /** @type {?} */
  1823. const emptyQueryParams = {};
  1824. /** @type {?} */
  1825. const fragment = '';
  1826. /** @type {?} */
  1827. const activated = new ActivatedRouteSnapshot([], emptyParams, emptyQueryParams, fragment, emptyData, PRIMARY_OUTLET, rootComponent, null, urlTree.root, -1, {});
  1828. return new RouterStateSnapshot('', new TreeNode(activated, []));
  1829. }
  1830. /**
  1831. * \@description
  1832. *
  1833. * Contains the information about a route associated with a component loaded in an
  1834. * outlet. An `ActivatedRoute` can also be used to traverse the router state tree.
  1835. *
  1836. * ```
  1837. * \@Component({...})
  1838. * class MyComponent {
  1839. * constructor(route: ActivatedRoute) {
  1840. * const id: Observable<string> = route.params.map(p => p.id);
  1841. * const url: Observable<string> = route.url.map(segments => segments.join(''));
  1842. * // route.data includes both `data` and `resolve`
  1843. * const user = route.data.map(d => d.user);
  1844. * }
  1845. * }
  1846. * ```
  1847. *
  1848. * \@publicApi
  1849. */
  1850. class ActivatedRoute {
  1851. /**
  1852. * \@internal
  1853. * @param {?} url
  1854. * @param {?} params
  1855. * @param {?} queryParams
  1856. * @param {?} fragment
  1857. * @param {?} data
  1858. * @param {?} outlet
  1859. * @param {?} component
  1860. * @param {?} futureSnapshot
  1861. */
  1862. constructor(url, params, queryParams, fragment, data, outlet, component, futureSnapshot) {
  1863. this.url = url;
  1864. this.params = params;
  1865. this.queryParams = queryParams;
  1866. this.fragment = fragment;
  1867. this.data = data;
  1868. this.outlet = outlet;
  1869. this.component = component;
  1870. this._futureSnapshot = futureSnapshot;
  1871. }
  1872. /**
  1873. * The configuration used to match this route
  1874. * @return {?}
  1875. */
  1876. get routeConfig() { return this._futureSnapshot.routeConfig; }
  1877. /**
  1878. * The root of the router state
  1879. * @return {?}
  1880. */
  1881. get root() { return this._routerState.root; }
  1882. /**
  1883. * The parent of this route in the router state tree
  1884. * @return {?}
  1885. */
  1886. get parent() { return this._routerState.parent(this); }
  1887. /**
  1888. * The first child of this route in the router state tree
  1889. * @return {?}
  1890. */
  1891. get firstChild() { return this._routerState.firstChild(this); }
  1892. /**
  1893. * The children of this route in the router state tree
  1894. * @return {?}
  1895. */
  1896. get children() { return this._routerState.children(this); }
  1897. /**
  1898. * The path from the root of the router state tree to this route
  1899. * @return {?}
  1900. */
  1901. get pathFromRoot() { return this._routerState.pathFromRoot(this); }
  1902. /**
  1903. * @return {?}
  1904. */
  1905. get paramMap() {
  1906. if (!this._paramMap) {
  1907. this._paramMap = this.params.pipe(map((p) => convertToParamMap(p)));
  1908. }
  1909. return this._paramMap;
  1910. }
  1911. /**
  1912. * @return {?}
  1913. */
  1914. get queryParamMap() {
  1915. if (!this._queryParamMap) {
  1916. this._queryParamMap =
  1917. this.queryParams.pipe(map((p) => convertToParamMap(p)));
  1918. }
  1919. return this._queryParamMap;
  1920. }
  1921. /**
  1922. * @return {?}
  1923. */
  1924. toString() {
  1925. return this.snapshot ? this.snapshot.toString() : `Future(${this._futureSnapshot})`;
  1926. }
  1927. }
  1928. /**
  1929. * Returns the inherited params, data, and resolve for a given route.
  1930. * By default, this only inherits values up to the nearest path-less or component-less route.
  1931. * \@internal
  1932. * @param {?} route
  1933. * @param {?=} paramsInheritanceStrategy
  1934. * @return {?}
  1935. */
  1936. function inheritedParamsDataResolve(route, paramsInheritanceStrategy = 'emptyOnly') {
  1937. /** @type {?} */
  1938. const pathFromRoot = route.pathFromRoot;
  1939. /** @type {?} */
  1940. let inheritingStartingFrom = 0;
  1941. if (paramsInheritanceStrategy !== 'always') {
  1942. inheritingStartingFrom = pathFromRoot.length - 1;
  1943. while (inheritingStartingFrom >= 1) {
  1944. /** @type {?} */
  1945. const current = pathFromRoot[inheritingStartingFrom];
  1946. /** @type {?} */
  1947. const parent = pathFromRoot[inheritingStartingFrom - 1];
  1948. // current route is an empty path => inherits its parent's params and data
  1949. if (current.routeConfig && current.routeConfig.path === '') {
  1950. inheritingStartingFrom--;
  1951. // parent is componentless => current route should inherit its params and data
  1952. }
  1953. else if (!parent.component) {
  1954. inheritingStartingFrom--;
  1955. }
  1956. else {
  1957. break;
  1958. }
  1959. }
  1960. }
  1961. return flattenInherited(pathFromRoot.slice(inheritingStartingFrom));
  1962. }
  1963. /**
  1964. * \@internal
  1965. * @param {?} pathFromRoot
  1966. * @return {?}
  1967. */
  1968. function flattenInherited(pathFromRoot) {
  1969. return pathFromRoot.reduce((res, curr) => {
  1970. /** @type {?} */
  1971. const params = Object.assign({}, res.params, curr.params);
  1972. /** @type {?} */
  1973. const data = Object.assign({}, res.data, curr.data);
  1974. /** @type {?} */
  1975. const resolve = Object.assign({}, res.resolve, curr._resolvedData);
  1976. return { params, data, resolve };
  1977. }, /** @type {?} */ ({ params: {}, data: {}, resolve: {} }));
  1978. }
  1979. /**
  1980. * \@description
  1981. *
  1982. * Contains the information about a route associated with a component loaded in an
  1983. * outlet at a particular moment in time. ActivatedRouteSnapshot can also be used to
  1984. * traverse the router state tree.
  1985. *
  1986. * ```
  1987. * \@Component({templateUrl:'./my-component.html'})
  1988. * class MyComponent {
  1989. * constructor(route: ActivatedRoute) {
  1990. * const id: string = route.snapshot.params.id;
  1991. * const url: string = route.snapshot.url.join('');
  1992. * const user = route.snapshot.data.user;
  1993. * }
  1994. * }
  1995. * ```
  1996. *
  1997. * \@publicApi
  1998. */
  1999. class ActivatedRouteSnapshot {
  2000. /**
  2001. * \@internal
  2002. * @param {?} url
  2003. * @param {?} params
  2004. * @param {?} queryParams
  2005. * @param {?} fragment
  2006. * @param {?} data
  2007. * @param {?} outlet
  2008. * @param {?} component
  2009. * @param {?} routeConfig
  2010. * @param {?} urlSegment
  2011. * @param {?} lastPathIndex
  2012. * @param {?} resolve
  2013. */
  2014. constructor(url, params, queryParams, fragment, data, outlet, component, routeConfig, urlSegment, lastPathIndex, resolve) {
  2015. this.url = url;
  2016. this.params = params;
  2017. this.queryParams = queryParams;
  2018. this.fragment = fragment;
  2019. this.data = data;
  2020. this.outlet = outlet;
  2021. this.component = component;
  2022. this.routeConfig = routeConfig;
  2023. this._urlSegment = urlSegment;
  2024. this._lastPathIndex = lastPathIndex;
  2025. this._resolve = resolve;
  2026. }
  2027. /**
  2028. * The root of the router state
  2029. * @return {?}
  2030. */
  2031. get root() { return this._routerState.root; }
  2032. /**
  2033. * The parent of this route in the router state tree
  2034. * @return {?}
  2035. */
  2036. get parent() { return this._routerState.parent(this); }
  2037. /**
  2038. * The first child of this route in the router state tree
  2039. * @return {?}
  2040. */
  2041. get firstChild() { return this._routerState.firstChild(this); }
  2042. /**
  2043. * The children of this route in the router state tree
  2044. * @return {?}
  2045. */
  2046. get children() { return this._routerState.children(this); }
  2047. /**
  2048. * The path from the root of the router state tree to this route
  2049. * @return {?}
  2050. */
  2051. get pathFromRoot() { return this._routerState.pathFromRoot(this); }
  2052. /**
  2053. * @return {?}
  2054. */
  2055. get paramMap() {
  2056. if (!this._paramMap) {
  2057. this._paramMap = convertToParamMap(this.params);
  2058. }
  2059. return this._paramMap;
  2060. }
  2061. /**
  2062. * @return {?}
  2063. */
  2064. get queryParamMap() {
  2065. if (!this._queryParamMap) {
  2066. this._queryParamMap = convertToParamMap(this.queryParams);
  2067. }
  2068. return this._queryParamMap;
  2069. }
  2070. /**
  2071. * @return {?}
  2072. */
  2073. toString() {
  2074. /** @type {?} */
  2075. const url = this.url.map(segment => segment.toString()).join('/');
  2076. /** @type {?} */
  2077. const matched = this.routeConfig ? this.routeConfig.path : '';
  2078. return `Route(url:'${url}', path:'${matched}')`;
  2079. }
  2080. }
  2081. /**
  2082. * \@description
  2083. *
  2084. * Represents the state of the router at a moment in time.
  2085. *
  2086. * This is a tree of activated route snapshots. Every node in this tree knows about
  2087. * the "consumed" URL segments, the extracted parameters, and the resolved data.
  2088. *
  2089. * \@usageNotes
  2090. * ### Example
  2091. *
  2092. * ```
  2093. * \@Component({templateUrl:'template.html'})
  2094. * class MyComponent {
  2095. * constructor(router: Router) {
  2096. * const state: RouterState = router.routerState;
  2097. * const snapshot: RouterStateSnapshot = state.snapshot;
  2098. * const root: ActivatedRouteSnapshot = snapshot.root;
  2099. * const child = root.firstChild;
  2100. * const id: Observable<string> = child.params.map(p => p.id);
  2101. * //...
  2102. * }
  2103. * }
  2104. * ```
  2105. *
  2106. * \@publicApi
  2107. */
  2108. class RouterStateSnapshot extends Tree {
  2109. /**
  2110. * \@internal
  2111. * @param {?} url
  2112. * @param {?} root
  2113. */
  2114. constructor(url, root) {
  2115. super(root);
  2116. this.url = url;
  2117. setRouterState(/** @type {?} */ (this), root);
  2118. }
  2119. /**
  2120. * @return {?}
  2121. */
  2122. toString() { return serializeNode(this._root); }
  2123. }
  2124. /**
  2125. * @template U, T
  2126. * @param {?} state
  2127. * @param {?} node
  2128. * @return {?}
  2129. */
  2130. function setRouterState(state, node) {
  2131. node.value._routerState = state;
  2132. node.children.forEach(c => setRouterState(state, c));
  2133. }
  2134. /**
  2135. * @param {?} node
  2136. * @return {?}
  2137. */
  2138. function serializeNode(node) {
  2139. /** @type {?} */
  2140. const c = node.children.length > 0 ? ` { ${node.children.map(serializeNode).join(', ')} } ` : '';
  2141. return `${node.value}${c}`;
  2142. }
  2143. /**
  2144. * The expectation is that the activate route is created with the right set of parameters.
  2145. * So we push new values into the observables only when they are not the initial values.
  2146. * And we detect that by checking if the snapshot field is set.
  2147. * @param {?} route
  2148. * @return {?}
  2149. */
  2150. function advanceActivatedRoute(route) {
  2151. if (route.snapshot) {
  2152. /** @type {?} */
  2153. const currentSnapshot = route.snapshot;
  2154. /** @type {?} */
  2155. const nextSnapshot = route._futureSnapshot;
  2156. route.snapshot = nextSnapshot;
  2157. if (!shallowEqual(currentSnapshot.queryParams, nextSnapshot.queryParams)) {
  2158. (/** @type {?} */ (route.queryParams)).next(nextSnapshot.queryParams);
  2159. }
  2160. if (currentSnapshot.fragment !== nextSnapshot.fragment) {
  2161. (/** @type {?} */ (route.fragment)).next(nextSnapshot.fragment);
  2162. }
  2163. if (!shallowEqual(currentSnapshot.params, nextSnapshot.params)) {
  2164. (/** @type {?} */ (route.params)).next(nextSnapshot.params);
  2165. }
  2166. if (!shallowEqualArrays(currentSnapshot.url, nextSnapshot.url)) {
  2167. (/** @type {?} */ (route.url)).next(nextSnapshot.url);
  2168. }
  2169. if (!shallowEqual(currentSnapshot.data, nextSnapshot.data)) {
  2170. (/** @type {?} */ (route.data)).next(nextSnapshot.data);
  2171. }
  2172. }
  2173. else {
  2174. route.snapshot = route._futureSnapshot;
  2175. // this is for resolved data
  2176. (/** @type {?} */ (route.data)).next(route._futureSnapshot.data);
  2177. }
  2178. }
  2179. /**
  2180. * @param {?} a
  2181. * @param {?} b
  2182. * @return {?}
  2183. */
  2184. function equalParamsAndUrlSegments(a, b) {
  2185. /** @type {?} */
  2186. const equalUrlParams = shallowEqual(a.params, b.params) && equalSegments(a.url, b.url);
  2187. /** @type {?} */
  2188. const parentsMismatch = !a.parent !== !b.parent;
  2189. return equalUrlParams && !parentsMismatch &&
  2190. (!a.parent || equalParamsAndUrlSegments(a.parent, /** @type {?} */ ((b.parent))));
  2191. }
  2192. /**
  2193. * @fileoverview added by tsickle
  2194. * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
  2195. */
  2196. /**
  2197. * @param {?} routeReuseStrategy
  2198. * @param {?} curr
  2199. * @param {?} prevState
  2200. * @return {?}
  2201. */
  2202. function createRouterState(routeReuseStrategy, curr, prevState) {
  2203. /** @type {?} */
  2204. const root = createNode(routeReuseStrategy, curr._root, prevState ? prevState._root : undefined);
  2205. return new RouterState(root, curr);
  2206. }
  2207. /**
  2208. * @param {?} routeReuseStrategy
  2209. * @param {?} curr
  2210. * @param {?=} prevState
  2211. * @return {?}
  2212. */
  2213. function createNode(routeReuseStrategy, curr, prevState) {
  2214. // reuse an activated route that is currently displayed on the screen
  2215. if (prevState && routeReuseStrategy.shouldReuseRoute(curr.value, prevState.value.snapshot)) {
  2216. /** @type {?} */
  2217. const value = prevState.value;
  2218. value._futureSnapshot = curr.value;
  2219. /** @type {?} */
  2220. const children = createOrReuseChildren(routeReuseStrategy, curr, prevState);
  2221. return new TreeNode(value, children);
  2222. // retrieve an activated route that is used to be displayed, but is not currently displayed
  2223. }
  2224. else {
  2225. /** @type {?} */
  2226. const detachedRouteHandle = /** @type {?} */ (routeReuseStrategy.retrieve(curr.value));
  2227. if (detachedRouteHandle) {
  2228. /** @type {?} */
  2229. const tree = detachedRouteHandle.route;
  2230. setFutureSnapshotsOfActivatedRoutes(curr, tree);
  2231. return tree;
  2232. }
  2233. else {
  2234. /** @type {?} */
  2235. const value = createActivatedRoute(curr.value);
  2236. /** @type {?} */
  2237. const children = curr.children.map(c => createNode(routeReuseStrategy, c));
  2238. return new TreeNode(value, children);
  2239. }
  2240. }
  2241. }
  2242. /**
  2243. * @param {?} curr
  2244. * @param {?} result
  2245. * @return {?}
  2246. */
  2247. function setFutureSnapshotsOfActivatedRoutes(curr, result) {
  2248. if (curr.value.routeConfig !== result.value.routeConfig) {
  2249. throw new Error('Cannot reattach ActivatedRouteSnapshot created from a different route');
  2250. }
  2251. if (curr.children.length !== result.children.length) {
  2252. throw new Error('Cannot reattach ActivatedRouteSnapshot with a different number of children');
  2253. }
  2254. result.value._futureSnapshot = curr.value;
  2255. for (let i = 0; i < curr.children.length; ++i) {
  2256. setFutureSnapshotsOfActivatedRoutes(curr.children[i], result.children[i]);
  2257. }
  2258. }
  2259. /**
  2260. * @param {?} routeReuseStrategy
  2261. * @param {?} curr
  2262. * @param {?} prevState
  2263. * @return {?}
  2264. */
  2265. function createOrReuseChildren(routeReuseStrategy, curr, prevState) {
  2266. return curr.children.map(child => {
  2267. for (const p of prevState.children) {
  2268. if (routeReuseStrategy.shouldReuseRoute(p.value.snapshot, child.value)) {
  2269. return createNode(routeReuseStrategy, child, p);
  2270. }
  2271. }
  2272. return createNode(routeReuseStrategy, child);
  2273. });
  2274. }
  2275. /**
  2276. * @param {?} c
  2277. * @return {?}
  2278. */
  2279. function createActivatedRoute(c) {
  2280. return new ActivatedRoute(new BehaviorSubject(c.url), new BehaviorSubject(c.params), new BehaviorSubject(c.queryParams), new BehaviorSubject(c.fragment), new BehaviorSubject(c.data), c.outlet, c.component, c);
  2281. }
  2282. /**
  2283. * @fileoverview added by tsickle
  2284. * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
  2285. */
  2286. /**
  2287. * @param {?} route
  2288. * @param {?} urlTree
  2289. * @param {?} commands
  2290. * @param {?} queryParams
  2291. * @param {?} fragment
  2292. * @return {?}
  2293. */
  2294. function createUrlTree(route, urlTree, commands, queryParams, fragment) {
  2295. if (commands.length === 0) {
  2296. return tree(urlTree.root, urlTree.root, urlTree, queryParams, fragment);
  2297. }
  2298. /** @type {?} */
  2299. const nav = computeNavigation(commands);
  2300. if (nav.toRoot()) {
  2301. return tree(urlTree.root, new UrlSegmentGroup([], {}), urlTree, queryParams, fragment);
  2302. }
  2303. /** @type {?} */
  2304. const startingPosition = findStartingPosition(nav, urlTree, route);
  2305. /** @type {?} */
  2306. const segmentGroup = startingPosition.processChildren ?
  2307. updateSegmentGroupChildren(startingPosition.segmentGroup, startingPosition.index, nav.commands) :
  2308. updateSegmentGroup(startingPosition.segmentGroup, startingPosition.index, nav.commands);
  2309. return tree(startingPosition.segmentGroup, segmentGroup, urlTree, queryParams, fragment);
  2310. }
  2311. /**
  2312. * @param {?} command
  2313. * @return {?}
  2314. */
  2315. function isMatrixParams(command) {
  2316. return typeof command === 'object' && command != null && !command.outlets && !command.segmentPath;
  2317. }
  2318. /**
  2319. * @param {?} oldSegmentGroup
  2320. * @param {?} newSegmentGroup
  2321. * @param {?} urlTree
  2322. * @param {?} queryParams
  2323. * @param {?} fragment
  2324. * @return {?}
  2325. */
  2326. function tree(oldSegmentGroup, newSegmentGroup, urlTree, queryParams, fragment) {
  2327. /** @type {?} */
  2328. let qp = {};
  2329. if (queryParams) {
  2330. forEach(queryParams, (value, name) => {
  2331. qp[name] = Array.isArray(value) ? value.map((v) => `${v}`) : `${value}`;
  2332. });
  2333. }
  2334. if (urlTree.root === oldSegmentGroup) {
  2335. return new UrlTree(newSegmentGroup, qp, fragment);
  2336. }
  2337. return new UrlTree(replaceSegment(urlTree.root, oldSegmentGroup, newSegmentGroup), qp, fragment);
  2338. }
  2339. /**
  2340. * @param {?} current
  2341. * @param {?} oldSegment
  2342. * @param {?} newSegment
  2343. * @return {?}
  2344. */
  2345. function replaceSegment(current, oldSegment, newSegment) {
  2346. /** @type {?} */
  2347. const children = {};
  2348. forEach(current.children, (c, outletName) => {
  2349. if (c === oldSegment) {
  2350. children[outletName] = newSegment;
  2351. }
  2352. else {
  2353. children[outletName] = replaceSegment(c, oldSegment, newSegment);
  2354. }
  2355. });
  2356. return new UrlSegmentGroup(current.segments, children);
  2357. }
  2358. class Navigation {
  2359. /**
  2360. * @param {?} isAbsolute
  2361. * @param {?} numberOfDoubleDots
  2362. * @param {?} commands
  2363. */
  2364. constructor(isAbsolute, numberOfDoubleDots, commands) {
  2365. this.isAbsolute = isAbsolute;
  2366. this.numberOfDoubleDots = numberOfDoubleDots;
  2367. this.commands = commands;
  2368. if (isAbsolute && commands.length > 0 && isMatrixParams(commands[0])) {
  2369. throw new Error('Root segment cannot have matrix parameters');
  2370. }
  2371. /** @type {?} */
  2372. const cmdWithOutlet = commands.find(c => typeof c === 'object' && c != null && c.outlets);
  2373. if (cmdWithOutlet && cmdWithOutlet !== last$1(commands)) {
  2374. throw new Error('{outlets:{}} has to be the last command');
  2375. }
  2376. }
  2377. /**
  2378. * @return {?}
  2379. */
  2380. toRoot() {
  2381. return this.isAbsolute && this.commands.length === 1 && this.commands[0] == '/';
  2382. }
  2383. }
  2384. /**
  2385. * Transforms commands to a normalized `Navigation`
  2386. * @param {?} commands
  2387. * @return {?}
  2388. */
  2389. function computeNavigation(commands) {
  2390. if ((typeof commands[0] === 'string') && commands.length === 1 && commands[0] === '/') {
  2391. return new Navigation(true, 0, commands);
  2392. }
  2393. /** @type {?} */
  2394. let numberOfDoubleDots = 0;
  2395. /** @type {?} */
  2396. let isAbsolute = false;
  2397. /** @type {?} */
  2398. const res = commands.reduce((res, cmd, cmdIdx) => {
  2399. if (typeof cmd === 'object' && cmd != null) {
  2400. if (cmd.outlets) {
  2401. /** @type {?} */
  2402. const outlets = {};
  2403. forEach(cmd.outlets, (commands, name) => {
  2404. outlets[name] = typeof commands === 'string' ? commands.split('/') : commands;
  2405. });
  2406. return [...res, { outlets }];
  2407. }
  2408. if (cmd.segmentPath) {
  2409. return [...res, cmd.segmentPath];
  2410. }
  2411. }
  2412. if (!(typeof cmd === 'string')) {
  2413. return [...res, cmd];
  2414. }
  2415. if (cmdIdx === 0) {
  2416. cmd.split('/').forEach((urlPart, partIndex) => {
  2417. if (partIndex == 0 && urlPart === '.') ;
  2418. else if (partIndex == 0 && urlPart === '') { // '/a'
  2419. // '/a'
  2420. isAbsolute = true;
  2421. }
  2422. else if (urlPart === '..') { // '../a'
  2423. // '../a'
  2424. numberOfDoubleDots++;
  2425. }
  2426. else if (urlPart != '') {
  2427. res.push(urlPart);
  2428. }
  2429. });
  2430. return res;
  2431. }
  2432. return [...res, cmd];
  2433. }, []);
  2434. return new Navigation(isAbsolute, numberOfDoubleDots, res);
  2435. }
  2436. class Position {
  2437. /**
  2438. * @param {?} segmentGroup
  2439. * @param {?} processChildren
  2440. * @param {?} index
  2441. */
  2442. constructor(segmentGroup, processChildren, index) {
  2443. this.segmentGroup = segmentGroup;
  2444. this.processChildren = processChildren;
  2445. this.index = index;
  2446. }
  2447. }
  2448. /**
  2449. * @param {?} nav
  2450. * @param {?} tree
  2451. * @param {?} route
  2452. * @return {?}
  2453. */
  2454. function findStartingPosition(nav, tree, route) {
  2455. if (nav.isAbsolute) {
  2456. return new Position(tree.root, true, 0);
  2457. }
  2458. if (route.snapshot._lastPathIndex === -1) {
  2459. return new Position(route.snapshot._urlSegment, true, 0);
  2460. }
  2461. /** @type {?} */
  2462. const modifier = isMatrixParams(nav.commands[0]) ? 0 : 1;
  2463. /** @type {?} */
  2464. const index = route.snapshot._lastPathIndex + modifier;
  2465. return createPositionApplyingDoubleDots(route.snapshot._urlSegment, index, nav.numberOfDoubleDots);
  2466. }
  2467. /**
  2468. * @param {?} group
  2469. * @param {?} index
  2470. * @param {?} numberOfDoubleDots
  2471. * @return {?}
  2472. */
  2473. function createPositionApplyingDoubleDots(group, index, numberOfDoubleDots) {
  2474. /** @type {?} */
  2475. let g = group;
  2476. /** @type {?} */
  2477. let ci = index;
  2478. /** @type {?} */
  2479. let dd = numberOfDoubleDots;
  2480. while (dd > ci) {
  2481. dd -= ci;
  2482. g = /** @type {?} */ ((g.parent));
  2483. if (!g) {
  2484. throw new Error('Invalid number of \'../\'');
  2485. }
  2486. ci = g.segments.length;
  2487. }
  2488. return new Position(g, false, ci - dd);
  2489. }
  2490. /**
  2491. * @param {?} command
  2492. * @return {?}
  2493. */
  2494. function getPath(command) {
  2495. if (typeof command === 'object' && command != null && command.outlets) {
  2496. return command.outlets[PRIMARY_OUTLET];
  2497. }
  2498. return `${command}`;
  2499. }
  2500. /**
  2501. * @param {?} commands
  2502. * @return {?}
  2503. */
  2504. function getOutlets(commands) {
  2505. if (!(typeof commands[0] === 'object'))
  2506. return { [PRIMARY_OUTLET]: commands };
  2507. if (commands[0].outlets === undefined)
  2508. return { [PRIMARY_OUTLET]: commands };
  2509. return commands[0].outlets;
  2510. }
  2511. /**
  2512. * @param {?} segmentGroup
  2513. * @param {?} startIndex
  2514. * @param {?} commands
  2515. * @return {?}
  2516. */
  2517. function updateSegmentGroup(segmentGroup, startIndex, commands) {
  2518. if (!segmentGroup) {
  2519. segmentGroup = new UrlSegmentGroup([], {});
  2520. }
  2521. if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) {
  2522. return updateSegmentGroupChildren(segmentGroup, startIndex, commands);
  2523. }
  2524. /** @type {?} */
  2525. const m = prefixedWith(segmentGroup, startIndex, commands);
  2526. /** @type {?} */
  2527. const slicedCommands = commands.slice(m.commandIndex);
  2528. if (m.match && m.pathIndex < segmentGroup.segments.length) {
  2529. /** @type {?} */
  2530. const g = new UrlSegmentGroup(segmentGroup.segments.slice(0, m.pathIndex), {});
  2531. g.children[PRIMARY_OUTLET] =
  2532. new UrlSegmentGroup(segmentGroup.segments.slice(m.pathIndex), segmentGroup.children);
  2533. return updateSegmentGroupChildren(g, 0, slicedCommands);
  2534. }
  2535. else if (m.match && slicedCommands.length === 0) {
  2536. return new UrlSegmentGroup(segmentGroup.segments, {});
  2537. }
  2538. else if (m.match && !segmentGroup.hasChildren()) {
  2539. return createNewSegmentGroup(segmentGroup, startIndex, commands);
  2540. }
  2541. else if (m.match) {
  2542. return updateSegmentGroupChildren(segmentGroup, 0, slicedCommands);
  2543. }
  2544. else {
  2545. return createNewSegmentGroup(segmentGroup, startIndex, commands);
  2546. }
  2547. }
  2548. /**
  2549. * @param {?} segmentGroup
  2550. * @param {?} startIndex
  2551. * @param {?} commands
  2552. * @return {?}
  2553. */
  2554. function updateSegmentGroupChildren(segmentGroup, startIndex, commands) {
  2555. if (commands.length === 0) {
  2556. return new UrlSegmentGroup(segmentGroup.segments, {});
  2557. }
  2558. else {
  2559. /** @type {?} */
  2560. const outlets = getOutlets(commands);
  2561. /** @type {?} */
  2562. const children = {};
  2563. forEach(outlets, (commands, outlet) => {
  2564. if (commands !== null) {
  2565. children[outlet] = updateSegmentGroup(segmentGroup.children[outlet], startIndex, commands);
  2566. }
  2567. });
  2568. forEach(segmentGroup.children, (child, childOutlet) => {
  2569. if (outlets[childOutlet] === undefined) {
  2570. children[childOutlet] = child;
  2571. }
  2572. });
  2573. return new UrlSegmentGroup(segmentGroup.segments, children);
  2574. }
  2575. }
  2576. /**
  2577. * @param {?} segmentGroup
  2578. * @param {?} startIndex
  2579. * @param {?} commands
  2580. * @return {?}
  2581. */
  2582. function prefixedWith(segmentGroup, startIndex, commands) {
  2583. /** @type {?} */
  2584. let currentCommandIndex = 0;
  2585. /** @type {?} */
  2586. let currentPathIndex = startIndex;
  2587. /** @type {?} */
  2588. const noMatch = { match: false, pathIndex: 0, commandIndex: 0 };
  2589. while (currentPathIndex < segmentGroup.segments.length) {
  2590. if (currentCommandIndex >= commands.length)
  2591. return noMatch;
  2592. /** @type {?} */
  2593. const path = segmentGroup.segments[currentPathIndex];
  2594. /** @type {?} */
  2595. const curr = getPath(commands[currentCommandIndex]);
  2596. /** @type {?} */
  2597. const next = currentCommandIndex < commands.length - 1 ? commands[currentCommandIndex + 1] : null;
  2598. if (currentPathIndex > 0 && curr === undefined)
  2599. break;
  2600. if (curr && next && (typeof next === 'object') && next.outlets === undefined) {
  2601. if (!compare(curr, next, path))
  2602. return noMatch;
  2603. currentCommandIndex += 2;
  2604. }
  2605. else {
  2606. if (!compare(curr, {}, path))
  2607. return noMatch;
  2608. currentCommandIndex++;
  2609. }
  2610. currentPathIndex++;
  2611. }
  2612. return { match: true, pathIndex: currentPathIndex, commandIndex: currentCommandIndex };
  2613. }
  2614. /**
  2615. * @param {?} segmentGroup
  2616. * @param {?} startIndex
  2617. * @param {?} commands
  2618. * @return {?}
  2619. */
  2620. function createNewSegmentGroup(segmentGroup, startIndex, commands) {
  2621. /** @type {?} */
  2622. const paths = segmentGroup.segments.slice(0, startIndex);
  2623. /** @type {?} */
  2624. let i = 0;
  2625. while (i < commands.length) {
  2626. if (typeof commands[i] === 'object' && commands[i].outlets !== undefined) {
  2627. /** @type {?} */
  2628. const children = createNewSegmentChildren(commands[i].outlets);
  2629. return new UrlSegmentGroup(paths, children);
  2630. }
  2631. // if we start with an object literal, we need to reuse the path part from the segment
  2632. if (i === 0 && isMatrixParams(commands[0])) {
  2633. /** @type {?} */
  2634. const p = segmentGroup.segments[startIndex];
  2635. paths.push(new UrlSegment(p.path, commands[0]));
  2636. i++;
  2637. continue;
  2638. }
  2639. /** @type {?} */
  2640. const curr = getPath(commands[i]);
  2641. /** @type {?} */
  2642. const next = (i < commands.length - 1) ? commands[i + 1] : null;
  2643. if (curr && next && isMatrixParams(next)) {
  2644. paths.push(new UrlSegment(curr, stringify(next)));
  2645. i += 2;
  2646. }
  2647. else {
  2648. paths.push(new UrlSegment(curr, {}));
  2649. i++;
  2650. }
  2651. }
  2652. return new UrlSegmentGroup(paths, {});
  2653. }
  2654. /**
  2655. * @param {?} outlets
  2656. * @return {?}
  2657. */
  2658. function createNewSegmentChildren(outlets) {
  2659. /** @type {?} */
  2660. const children = {};
  2661. forEach(outlets, (commands, outlet) => {
  2662. if (commands !== null) {
  2663. children[outlet] = createNewSegmentGroup(new UrlSegmentGroup([], {}), 0, commands);
  2664. }
  2665. });
  2666. return children;
  2667. }
  2668. /**
  2669. * @param {?} params
  2670. * @return {?}
  2671. */
  2672. function stringify(params) {
  2673. /** @type {?} */
  2674. const res = {};
  2675. forEach(params, (v, k) => res[k] = `${v}`);
  2676. return res;
  2677. }
  2678. /**
  2679. * @param {?} path
  2680. * @param {?} params
  2681. * @param {?} segment
  2682. * @return {?}
  2683. */
  2684. function compare(path, params, segment) {
  2685. return path == segment.path && shallowEqual(params, segment.parameters);
  2686. }
  2687. /**
  2688. * @fileoverview added by tsickle
  2689. * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
  2690. */
  2691. /** @type {?} */
  2692. const activateRoutes = (rootContexts, routeReuseStrategy, forwardEvent) => map(t => {
  2693. new ActivateRoutes(routeReuseStrategy, /** @type {?} */ ((t.targetRouterState)), t.currentRouterState, forwardEvent)
  2694. .activate(rootContexts);
  2695. return t;
  2696. });
  2697. class ActivateRoutes {
  2698. /**
  2699. * @param {?} routeReuseStrategy
  2700. * @param {?} futureState
  2701. * @param {?} currState
  2702. * @param {?} forwardEvent
  2703. */
  2704. constructor(routeReuseStrategy, futureState, currState, forwardEvent) {
  2705. this.routeReuseStrategy = routeReuseStrategy;
  2706. this.futureState = futureState;
  2707. this.currState = currState;
  2708. this.forwardEvent = forwardEvent;
  2709. }
  2710. /**
  2711. * @param {?} parentContexts
  2712. * @return {?}
  2713. */
  2714. activate(parentContexts) {
  2715. /** @type {?} */
  2716. const futureRoot = this.futureState._root;
  2717. /** @type {?} */
  2718. const currRoot = this.currState ? this.currState._root : null;
  2719. this.deactivateChildRoutes(futureRoot, currRoot, parentContexts);
  2720. advanceActivatedRoute(this.futureState.root);
  2721. this.activateChildRoutes(futureRoot, currRoot, parentContexts);
  2722. }
  2723. /**
  2724. * @param {?} futureNode
  2725. * @param {?} currNode
  2726. * @param {?} contexts
  2727. * @return {?}
  2728. */
  2729. deactivateChildRoutes(futureNode, currNode, contexts) {
  2730. /** @type {?} */
  2731. const children = nodeChildrenAsMap(currNode);
  2732. // Recurse on the routes active in the future state to de-activate deeper children
  2733. futureNode.children.forEach(futureChild => {
  2734. /** @type {?} */
  2735. const childOutletName = futureChild.value.outlet;
  2736. this.deactivateRoutes(futureChild, children[childOutletName], contexts);
  2737. delete children[childOutletName];
  2738. });
  2739. // De-activate the routes that will not be re-used
  2740. forEach(children, (v, childName) => {
  2741. this.deactivateRouteAndItsChildren(v, contexts);
  2742. });
  2743. }
  2744. /**
  2745. * @param {?} futureNode
  2746. * @param {?} currNode
  2747. * @param {?} parentContext
  2748. * @return {?}
  2749. */
  2750. deactivateRoutes(futureNode, currNode, parentContext) {
  2751. /** @type {?} */
  2752. const future = futureNode.value;
  2753. /** @type {?} */
  2754. const curr = currNode ? currNode.value : null;
  2755. if (future === curr) {
  2756. // Reusing the node, check to see if the children need to be de-activated
  2757. if (future.component) {
  2758. /** @type {?} */
  2759. const context = parentContext.getContext(future.outlet);
  2760. if (context) {
  2761. this.deactivateChildRoutes(futureNode, currNode, context.children);
  2762. }
  2763. }
  2764. else {
  2765. // if we have a componentless route, we recurse but keep the same outlet map.
  2766. this.deactivateChildRoutes(futureNode, currNode, parentContext);
  2767. }
  2768. }
  2769. else {
  2770. if (curr) {
  2771. // Deactivate the current route which will not be re-used
  2772. this.deactivateRouteAndItsChildren(currNode, parentContext);
  2773. }
  2774. }
  2775. }
  2776. /**
  2777. * @param {?} route
  2778. * @param {?} parentContexts
  2779. * @return {?}
  2780. */
  2781. deactivateRouteAndItsChildren(route, parentContexts) {
  2782. if (this.routeReuseStrategy.shouldDetach(route.value.snapshot)) {
  2783. this.detachAndStoreRouteSubtree(route, parentContexts);
  2784. }
  2785. else {
  2786. this.deactivateRouteAndOutlet(route, parentContexts);
  2787. }
  2788. }
  2789. /**
  2790. * @param {?} route
  2791. * @param {?} parentContexts
  2792. * @return {?}
  2793. */
  2794. detachAndStoreRouteSubtree(route, parentContexts) {
  2795. /** @type {?} */
  2796. const context = parentContexts.getContext(route.value.outlet);
  2797. if (context && context.outlet) {
  2798. /** @type {?} */
  2799. const componentRef = context.outlet.detach();
  2800. /** @type {?} */
  2801. const contexts = context.children.onOutletDeactivated();
  2802. this.routeReuseStrategy.store(route.value.snapshot, { componentRef, route, contexts });
  2803. }
  2804. }
  2805. /**
  2806. * @param {?} route
  2807. * @param {?} parentContexts
  2808. * @return {?}
  2809. */
  2810. deactivateRouteAndOutlet(route, parentContexts) {
  2811. /** @type {?} */
  2812. const context = parentContexts.getContext(route.value.outlet);
  2813. if (context) {
  2814. /** @type {?} */
  2815. const children = nodeChildrenAsMap(route);
  2816. /** @type {?} */
  2817. const contexts = route.value.component ? context.children : parentContexts;
  2818. forEach(children, (v, k) => this.deactivateRouteAndItsChildren(v, contexts));
  2819. if (context.outlet) {
  2820. // Destroy the component
  2821. context.outlet.deactivate();
  2822. // Destroy the contexts for all the outlets that were in the component
  2823. context.children.onOutletDeactivated();
  2824. }
  2825. }
  2826. }
  2827. /**
  2828. * @param {?} futureNode
  2829. * @param {?} currNode
  2830. * @param {?} contexts
  2831. * @return {?}
  2832. */
  2833. activateChildRoutes(futureNode, currNode, contexts) {
  2834. /** @type {?} */
  2835. const children = nodeChildrenAsMap(currNode);
  2836. futureNode.children.forEach(c => {
  2837. this.activateRoutes(c, children[c.value.outlet], contexts);
  2838. this.forwardEvent(new ActivationEnd(c.value.snapshot));
  2839. });
  2840. if (futureNode.children.length) {
  2841. this.forwardEvent(new ChildActivationEnd(futureNode.value.snapshot));
  2842. }
  2843. }
  2844. /**
  2845. * @param {?} futureNode
  2846. * @param {?} currNode
  2847. * @param {?} parentContexts
  2848. * @return {?}
  2849. */
  2850. activateRoutes(futureNode, currNode, parentContexts) {
  2851. /** @type {?} */
  2852. const future = futureNode.value;
  2853. /** @type {?} */
  2854. const curr = currNode ? currNode.value : null;
  2855. advanceActivatedRoute(future);
  2856. // reusing the node
  2857. if (future === curr) {
  2858. if (future.component) {
  2859. /** @type {?} */
  2860. const context = parentContexts.getOrCreateContext(future.outlet);
  2861. this.activateChildRoutes(futureNode, currNode, context.children);
  2862. }
  2863. else {
  2864. // if we have a componentless route, we recurse but keep the same outlet map.
  2865. this.activateChildRoutes(futureNode, currNode, parentContexts);
  2866. }
  2867. }
  2868. else {
  2869. if (future.component) {
  2870. /** @type {?} */
  2871. const context = parentContexts.getOrCreateContext(future.outlet);
  2872. if (this.routeReuseStrategy.shouldAttach(future.snapshot)) {
  2873. /** @type {?} */
  2874. const stored = (/** @type {?} */ (this.routeReuseStrategy.retrieve(future.snapshot)));
  2875. this.routeReuseStrategy.store(future.snapshot, null);
  2876. context.children.onOutletReAttached(stored.contexts);
  2877. context.attachRef = stored.componentRef;
  2878. context.route = stored.route.value;
  2879. if (context.outlet) {
  2880. // Attach right away when the outlet has already been instantiated
  2881. // Otherwise attach from `RouterOutlet.ngOnInit` when it is instantiated
  2882. context.outlet.attach(stored.componentRef, stored.route.value);
  2883. }
  2884. if(context.children.contexts != null && context.children.contexts.size > 0){
  2885. this.activateChildRoutes(futureNode, null, context.children);
  2886. advanceActivatedRoute(stored.route.value);
  2887. }else{
  2888. advanceActivatedRouteNodeAndItsChildren(stored.route);
  2889. }
  2890. }
  2891. else {
  2892. /** @type {?} */
  2893. const config = parentLoadedConfig(future.snapshot);
  2894. /** @type {?} */
  2895. const cmpFactoryResolver = config ? config.module.componentFactoryResolver : null;
  2896. context.attachRef = null;
  2897. context.route = future;
  2898. context.resolver = cmpFactoryResolver;
  2899. if (context.outlet) {
  2900. // Activate the outlet when it has already been instantiated
  2901. // Otherwise it will get activated from its `ngOnInit` when instantiated
  2902. context.outlet.activateWith(future, cmpFactoryResolver);
  2903. }
  2904. this.activateChildRoutes(futureNode, null, context.children);
  2905. }
  2906. }
  2907. else {
  2908. // if we have a componentless route, we recurse but keep the same outlet map.
  2909. this.activateChildRoutes(futureNode, null, parentContexts);
  2910. }
  2911. }
  2912. }
  2913. }
  2914. /**
  2915. * @param {?} node
  2916. * @return {?}
  2917. */
  2918. function advanceActivatedRouteNodeAndItsChildren(node) {
  2919. advanceActivatedRoute(node.value);
  2920. node.children.forEach(advanceActivatedRouteNodeAndItsChildren);
  2921. }
  2922. /**
  2923. * @param {?} snapshot
  2924. * @return {?}
  2925. */
  2926. function parentLoadedConfig(snapshot) {
  2927. for (let s = snapshot.parent; s; s = s.parent) {
  2928. /** @type {?} */
  2929. const route = s.routeConfig;
  2930. if (route && route._loadedConfig)
  2931. return route._loadedConfig;
  2932. if (route && route.component)
  2933. return null;
  2934. }
  2935. return null;
  2936. }
  2937. /**
  2938. * @fileoverview added by tsickle
  2939. * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
  2940. */
  2941. class NoMatch {
  2942. /**
  2943. * @param {?=} segmentGroup
  2944. */
  2945. constructor(segmentGroup) { this.segmentGroup = segmentGroup || null; }
  2946. }
  2947. class AbsoluteRedirect {
  2948. /**
  2949. * @param {?} urlTree
  2950. */
  2951. constructor(urlTree) {
  2952. this.urlTree = urlTree;
  2953. }
  2954. }
  2955. /**
  2956. * @param {?} segmentGroup
  2957. * @return {?}
  2958. */
  2959. function noMatch(segmentGroup) {
  2960. return new Observable((obs) => obs.error(new NoMatch(segmentGroup)));
  2961. }
  2962. /**
  2963. * @param {?} newTree
  2964. * @return {?}
  2965. */
  2966. function absoluteRedirect(newTree) {
  2967. return new Observable((obs) => obs.error(new AbsoluteRedirect(newTree)));
  2968. }
  2969. /**
  2970. * @param {?} redirectTo
  2971. * @return {?}
  2972. */
  2973. function namedOutletsRedirect(redirectTo) {
  2974. return new Observable((obs) => obs.error(new Error(`Only absolute redirects can have named outlets. redirectTo: '${redirectTo}'`)));
  2975. }
  2976. /**
  2977. * @param {?} route
  2978. * @return {?}
  2979. */
  2980. function canLoadFails(route) {
  2981. return new Observable((obs) => obs.error(navigationCancelingError(`Cannot load children because the guard of the route "path: '${route.path}'" returned false`)));
  2982. }
  2983. /**
  2984. * Returns the `UrlTree` with the redirection applied.
  2985. *
  2986. * Lazy modules are loaded along the way.
  2987. * @param {?} moduleInjector
  2988. * @param {?} configLoader
  2989. * @param {?} urlSerializer
  2990. * @param {?} urlTree
  2991. * @param {?} config
  2992. * @return {?}
  2993. */
  2994. function applyRedirects(moduleInjector, configLoader, urlSerializer, urlTree, config) {
  2995. return new ApplyRedirects(moduleInjector, configLoader, urlSerializer, urlTree, config).apply();
  2996. }
  2997. class ApplyRedirects {
  2998. /**
  2999. * @param {?} moduleInjector
  3000. * @param {?} configLoader
  3001. * @param {?} urlSerializer
  3002. * @param {?} urlTree
  3003. * @param {?} config
  3004. */
  3005. constructor(moduleInjector, configLoader, urlSerializer, urlTree, config) {
  3006. this.configLoader = configLoader;
  3007. this.urlSerializer = urlSerializer;
  3008. this.urlTree = urlTree;
  3009. this.config = config;
  3010. this.allowRedirects = true;
  3011. this.ngModule = moduleInjector.get(NgModuleRef);
  3012. }
  3013. /**
  3014. * @return {?}
  3015. */
  3016. apply() {
  3017. /** @type {?} */
  3018. const expanded$ = this.expandSegmentGroup(this.ngModule, this.config, this.urlTree.root, PRIMARY_OUTLET);
  3019. /** @type {?} */
  3020. const urlTrees$ = expanded$.pipe(map((rootSegmentGroup) => this.createUrlTree(rootSegmentGroup, this.urlTree.queryParams, /** @type {?} */ ((this.urlTree.fragment)))));
  3021. return urlTrees$.pipe(catchError((e) => {
  3022. if (e instanceof AbsoluteRedirect) {
  3023. // after an absolute redirect we do not apply any more redirects!
  3024. this.allowRedirects = false;
  3025. // we need to run matching, so we can fetch all lazy-loaded modules
  3026. return this.match(e.urlTree);
  3027. }
  3028. if (e instanceof NoMatch) {
  3029. throw this.noMatchError(e);
  3030. }
  3031. throw e;
  3032. }));
  3033. }
  3034. /**
  3035. * @param {?} tree
  3036. * @return {?}
  3037. */
  3038. match(tree) {
  3039. /** @type {?} */
  3040. const expanded$ = this.expandSegmentGroup(this.ngModule, this.config, tree.root, PRIMARY_OUTLET);
  3041. /** @type {?} */
  3042. const mapped$ = expanded$.pipe(map((rootSegmentGroup) => this.createUrlTree(rootSegmentGroup, tree.queryParams, /** @type {?} */ ((tree.fragment)))));
  3043. return mapped$.pipe(catchError((e) => {
  3044. if (e instanceof NoMatch) {
  3045. throw this.noMatchError(e);
  3046. }
  3047. throw e;
  3048. }));
  3049. }
  3050. /**
  3051. * @param {?} e
  3052. * @return {?}
  3053. */
  3054. noMatchError(e) {
  3055. return new Error(`Cannot match any routes. URL Segment: '${e.segmentGroup}'`);
  3056. }
  3057. /**
  3058. * @param {?} rootCandidate
  3059. * @param {?} queryParams
  3060. * @param {?} fragment
  3061. * @return {?}
  3062. */
  3063. createUrlTree(rootCandidate, queryParams, fragment) {
  3064. /** @type {?} */
  3065. const root = rootCandidate.segments.length > 0 ?
  3066. new UrlSegmentGroup([], { [PRIMARY_OUTLET]: rootCandidate }) :
  3067. rootCandidate;
  3068. return new UrlTree(root, queryParams, fragment);
  3069. }
  3070. /**
  3071. * @param {?} ngModule
  3072. * @param {?} routes
  3073. * @param {?} segmentGroup
  3074. * @param {?} outlet
  3075. * @return {?}
  3076. */
  3077. expandSegmentGroup(ngModule, routes, segmentGroup, outlet) {
  3078. if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) {
  3079. return this.expandChildren(ngModule, routes, segmentGroup)
  3080. .pipe(map((children) => new UrlSegmentGroup([], children)));
  3081. }
  3082. return this.expandSegment(ngModule, segmentGroup, routes, segmentGroup.segments, outlet, true);
  3083. }
  3084. /**
  3085. * @param {?} ngModule
  3086. * @param {?} routes
  3087. * @param {?} segmentGroup
  3088. * @return {?}
  3089. */
  3090. expandChildren(ngModule, routes, segmentGroup) {
  3091. return waitForMap(segmentGroup.children, (childOutlet, child) => this.expandSegmentGroup(ngModule, routes, child, childOutlet));
  3092. }
  3093. /**
  3094. * @param {?} ngModule
  3095. * @param {?} segmentGroup
  3096. * @param {?} routes
  3097. * @param {?} segments
  3098. * @param {?} outlet
  3099. * @param {?} allowRedirects
  3100. * @return {?}
  3101. */
  3102. expandSegment(ngModule, segmentGroup, routes, segments, outlet, allowRedirects) {
  3103. return of(...routes).pipe(map((r) => {
  3104. /** @type {?} */
  3105. const expanded$ = this.expandSegmentAgainstRoute(ngModule, segmentGroup, routes, r, segments, outlet, allowRedirects);
  3106. return expanded$.pipe(catchError((e) => {
  3107. if (e instanceof NoMatch) {
  3108. // TODO(i): this return type doesn't match the declared Observable<UrlSegmentGroup> -
  3109. // talk to Jason
  3110. return /** @type {?} */ (of(null));
  3111. }
  3112. throw e;
  3113. }));
  3114. }), concatAll(), first((s) => !!s), catchError((e, _) => {
  3115. if (e instanceof EmptyError || e.name === 'EmptyError') {
  3116. if (this.noLeftoversInUrl(segmentGroup, segments, outlet)) {
  3117. return of(new UrlSegmentGroup([], {}));
  3118. }
  3119. throw new NoMatch(segmentGroup);
  3120. }
  3121. throw e;
  3122. }));
  3123. }
  3124. /**
  3125. * @param {?} segmentGroup
  3126. * @param {?} segments
  3127. * @param {?} outlet
  3128. * @return {?}
  3129. */
  3130. noLeftoversInUrl(segmentGroup, segments, outlet) {
  3131. return segments.length === 0 && !segmentGroup.children[outlet];
  3132. }
  3133. /**
  3134. * @param {?} ngModule
  3135. * @param {?} segmentGroup
  3136. * @param {?} routes
  3137. * @param {?} route
  3138. * @param {?} paths
  3139. * @param {?} outlet
  3140. * @param {?} allowRedirects
  3141. * @return {?}
  3142. */
  3143. expandSegmentAgainstRoute(ngModule, segmentGroup, routes, route, paths, outlet, allowRedirects) {
  3144. if (getOutlet(route) !== outlet) {
  3145. return noMatch(segmentGroup);
  3146. }
  3147. if (route.redirectTo === undefined) {
  3148. return this.matchSegmentAgainstRoute(ngModule, segmentGroup, route, paths);
  3149. }
  3150. if (allowRedirects && this.allowRedirects) {
  3151. return this.expandSegmentAgainstRouteUsingRedirect(ngModule, segmentGroup, routes, route, paths, outlet);
  3152. }
  3153. return noMatch(segmentGroup);
  3154. }
  3155. /**
  3156. * @param {?} ngModule
  3157. * @param {?} segmentGroup
  3158. * @param {?} routes
  3159. * @param {?} route
  3160. * @param {?} segments
  3161. * @param {?} outlet
  3162. * @return {?}
  3163. */
  3164. expandSegmentAgainstRouteUsingRedirect(ngModule, segmentGroup, routes, route, segments, outlet) {
  3165. if (route.path === '**') {
  3166. return this.expandWildCardWithParamsAgainstRouteUsingRedirect(ngModule, routes, route, outlet);
  3167. }
  3168. return this.expandRegularSegmentAgainstRouteUsingRedirect(ngModule, segmentGroup, routes, route, segments, outlet);
  3169. }
  3170. /**
  3171. * @param {?} ngModule
  3172. * @param {?} routes
  3173. * @param {?} route
  3174. * @param {?} outlet
  3175. * @return {?}
  3176. */
  3177. expandWildCardWithParamsAgainstRouteUsingRedirect(ngModule, routes, route, outlet) {
  3178. /** @type {?} */
  3179. const newTree = this.applyRedirectCommands([], /** @type {?} */ ((route.redirectTo)), {});
  3180. if (/** @type {?} */ ((route.redirectTo)).startsWith('/')) {
  3181. return absoluteRedirect(newTree);
  3182. }
  3183. return this.lineralizeSegments(route, newTree).pipe(mergeMap((newSegments) => {
  3184. /** @type {?} */
  3185. const group = new UrlSegmentGroup(newSegments, {});
  3186. return this.expandSegment(ngModule, group, routes, newSegments, outlet, false);
  3187. }));
  3188. }
  3189. /**
  3190. * @param {?} ngModule
  3191. * @param {?} segmentGroup
  3192. * @param {?} routes
  3193. * @param {?} route
  3194. * @param {?} segments
  3195. * @param {?} outlet
  3196. * @return {?}
  3197. */
  3198. expandRegularSegmentAgainstRouteUsingRedirect(ngModule, segmentGroup, routes, route, segments, outlet) {
  3199. const { matched, consumedSegments, lastChild, positionalParamSegments } = match(segmentGroup, route, segments);
  3200. if (!matched)
  3201. return noMatch(segmentGroup);
  3202. /** @type {?} */
  3203. const newTree = this.applyRedirectCommands(consumedSegments, /** @type {?} */ ((route.redirectTo)), /** @type {?} */ (positionalParamSegments));
  3204. if (/** @type {?} */ ((route.redirectTo)).startsWith('/')) {
  3205. return absoluteRedirect(newTree);
  3206. }
  3207. return this.lineralizeSegments(route, newTree).pipe(mergeMap((newSegments) => {
  3208. return this.expandSegment(ngModule, segmentGroup, routes, newSegments.concat(segments.slice(lastChild)), outlet, false);
  3209. }));
  3210. }
  3211. /**
  3212. * @param {?} ngModule
  3213. * @param {?} rawSegmentGroup
  3214. * @param {?} route
  3215. * @param {?} segments
  3216. * @return {?}
  3217. */
  3218. matchSegmentAgainstRoute(ngModule, rawSegmentGroup, route, segments) {
  3219. if (route.path === '**') {
  3220. if (route.loadChildren) {
  3221. return this.configLoader.load(ngModule.injector, route)
  3222. .pipe(map((cfg) => {
  3223. route._loadedConfig = cfg;
  3224. return new UrlSegmentGroup(segments, {});
  3225. }));
  3226. }
  3227. return of(new UrlSegmentGroup(segments, {}));
  3228. }
  3229. const { matched, consumedSegments, lastChild } = match(rawSegmentGroup, route, segments);
  3230. if (!matched)
  3231. return noMatch(rawSegmentGroup);
  3232. /** @type {?} */
  3233. const rawSlicedSegments = segments.slice(lastChild);
  3234. /** @type {?} */
  3235. const childConfig$ = this.getChildConfig(ngModule, route, segments);
  3236. return childConfig$.pipe(mergeMap((routerConfig) => {
  3237. /** @type {?} */
  3238. const childModule = routerConfig.module;
  3239. /** @type {?} */
  3240. const childConfig = routerConfig.routes;
  3241. const { segmentGroup, slicedSegments } = split(rawSegmentGroup, consumedSegments, rawSlicedSegments, childConfig);
  3242. if (slicedSegments.length === 0 && segmentGroup.hasChildren()) {
  3243. /** @type {?} */
  3244. const expanded$ = this.expandChildren(childModule, childConfig, segmentGroup);
  3245. return expanded$.pipe(map((children) => new UrlSegmentGroup(consumedSegments, children)));
  3246. }
  3247. if (childConfig.length === 0 && slicedSegments.length === 0) {
  3248. return of(new UrlSegmentGroup(consumedSegments, {}));
  3249. }
  3250. /** @type {?} */
  3251. const expanded$ = this.expandSegment(childModule, segmentGroup, childConfig, slicedSegments, PRIMARY_OUTLET, true);
  3252. return expanded$.pipe(map((cs) => new UrlSegmentGroup(consumedSegments.concat(cs.segments), cs.children)));
  3253. }));
  3254. }
  3255. /**
  3256. * @param {?} ngModule
  3257. * @param {?} route
  3258. * @param {?} segments
  3259. * @return {?}
  3260. */
  3261. getChildConfig(ngModule, route, segments) {
  3262. if (route.children) {
  3263. // The children belong to the same module
  3264. return of(new LoadedRouterConfig(route.children, ngModule));
  3265. }
  3266. if (route.loadChildren) {
  3267. // lazy children belong to the loaded module
  3268. if (route._loadedConfig !== undefined) {
  3269. return of(route._loadedConfig);
  3270. }
  3271. return runCanLoadGuard(ngModule.injector, route, segments)
  3272. .pipe(mergeMap((shouldLoad) => {
  3273. if (shouldLoad) {
  3274. return this.configLoader.load(ngModule.injector, route)
  3275. .pipe(map((cfg) => {
  3276. route._loadedConfig = cfg;
  3277. return cfg;
  3278. }));
  3279. }
  3280. return canLoadFails(route);
  3281. }));
  3282. }
  3283. return of(new LoadedRouterConfig([], ngModule));
  3284. }
  3285. /**
  3286. * @param {?} route
  3287. * @param {?} urlTree
  3288. * @return {?}
  3289. */
  3290. lineralizeSegments(route, urlTree) {
  3291. /** @type {?} */
  3292. let res = [];
  3293. /** @type {?} */
  3294. let c = urlTree.root;
  3295. while (true) {
  3296. res = res.concat(c.segments);
  3297. if (c.numberOfChildren === 0) {
  3298. return of(res);
  3299. }
  3300. if (c.numberOfChildren > 1 || !c.children[PRIMARY_OUTLET]) {
  3301. return namedOutletsRedirect(/** @type {?} */ ((route.redirectTo)));
  3302. }
  3303. c = c.children[PRIMARY_OUTLET];
  3304. }
  3305. }
  3306. /**
  3307. * @param {?} segments
  3308. * @param {?} redirectTo
  3309. * @param {?} posParams
  3310. * @return {?}
  3311. */
  3312. applyRedirectCommands(segments, redirectTo, posParams) {
  3313. return this.applyRedirectCreatreUrlTree(redirectTo, this.urlSerializer.parse(redirectTo), segments, posParams);
  3314. }
  3315. /**
  3316. * @param {?} redirectTo
  3317. * @param {?} urlTree
  3318. * @param {?} segments
  3319. * @param {?} posParams
  3320. * @return {?}
  3321. */
  3322. applyRedirectCreatreUrlTree(redirectTo, urlTree, segments, posParams) {
  3323. /** @type {?} */
  3324. const newRoot = this.createSegmentGroup(redirectTo, urlTree.root, segments, posParams);
  3325. return new UrlTree(newRoot, this.createQueryParams(urlTree.queryParams, this.urlTree.queryParams), urlTree.fragment);
  3326. }
  3327. /**
  3328. * @param {?} redirectToParams
  3329. * @param {?} actualParams
  3330. * @return {?}
  3331. */
  3332. createQueryParams(redirectToParams, actualParams) {
  3333. /** @type {?} */
  3334. const res = {};
  3335. forEach(redirectToParams, (v, k) => {
  3336. /** @type {?} */
  3337. const copySourceValue = typeof v === 'string' && v.startsWith(':');
  3338. if (copySourceValue) {
  3339. /** @type {?} */
  3340. const sourceName = v.substring(1);
  3341. res[k] = actualParams[sourceName];
  3342. }
  3343. else {
  3344. res[k] = v;
  3345. }
  3346. });
  3347. return res;
  3348. }
  3349. /**
  3350. * @param {?} redirectTo
  3351. * @param {?} group
  3352. * @param {?} segments
  3353. * @param {?} posParams
  3354. * @return {?}
  3355. */
  3356. createSegmentGroup(redirectTo, group, segments, posParams) {
  3357. /** @type {?} */
  3358. const updatedSegments = this.createSegments(redirectTo, group.segments, segments, posParams);
  3359. /** @type {?} */
  3360. let children = {};
  3361. forEach(group.children, (child, name) => {
  3362. children[name] = this.createSegmentGroup(redirectTo, child, segments, posParams);
  3363. });
  3364. return new UrlSegmentGroup(updatedSegments, children);
  3365. }
  3366. /**
  3367. * @param {?} redirectTo
  3368. * @param {?} redirectToSegments
  3369. * @param {?} actualSegments
  3370. * @param {?} posParams
  3371. * @return {?}
  3372. */
  3373. createSegments(redirectTo, redirectToSegments, actualSegments, posParams) {
  3374. return redirectToSegments.map(s => s.path.startsWith(':') ? this.findPosParam(redirectTo, s, posParams) :
  3375. this.findOrReturn(s, actualSegments));
  3376. }
  3377. /**
  3378. * @param {?} redirectTo
  3379. * @param {?} redirectToUrlSegment
  3380. * @param {?} posParams
  3381. * @return {?}
  3382. */
  3383. findPosParam(redirectTo, redirectToUrlSegment, posParams) {
  3384. /** @type {?} */
  3385. const pos = posParams[redirectToUrlSegment.path.substring(1)];
  3386. if (!pos)
  3387. throw new Error(`Cannot redirect to '${redirectTo}'. Cannot find '${redirectToUrlSegment.path}'.`);
  3388. return pos;
  3389. }
  3390. /**
  3391. * @param {?} redirectToUrlSegment
  3392. * @param {?} actualSegments
  3393. * @return {?}
  3394. */
  3395. findOrReturn(redirectToUrlSegment, actualSegments) {
  3396. /** @type {?} */
  3397. let idx = 0;
  3398. for (const s of actualSegments) {
  3399. if (s.path === redirectToUrlSegment.path) {
  3400. actualSegments.splice(idx);
  3401. return s;
  3402. }
  3403. idx++;
  3404. }
  3405. return redirectToUrlSegment;
  3406. }
  3407. }
  3408. /**
  3409. * @param {?} moduleInjector
  3410. * @param {?} route
  3411. * @param {?} segments
  3412. * @return {?}
  3413. */
  3414. function runCanLoadGuard(moduleInjector, route, segments) {
  3415. /** @type {?} */
  3416. const canLoad = route.canLoad;
  3417. if (!canLoad || canLoad.length === 0)
  3418. return of(true);
  3419. /** @type {?} */
  3420. const obs = from(canLoad).pipe(map((injectionToken) => {
  3421. /** @type {?} */
  3422. const guard = moduleInjector.get(injectionToken);
  3423. return wrapIntoObservable(guard.canLoad ? guard.canLoad(route, segments) : guard(route, segments));
  3424. }));
  3425. return andObservables(obs);
  3426. }
  3427. /**
  3428. * @param {?} segmentGroup
  3429. * @param {?} route
  3430. * @param {?} segments
  3431. * @return {?}
  3432. */
  3433. function match(segmentGroup, route, segments) {
  3434. if (route.path === '') {
  3435. if ((route.pathMatch === 'full') && (segmentGroup.hasChildren() || segments.length > 0)) {
  3436. return { matched: false, consumedSegments: [], lastChild: 0, positionalParamSegments: {} };
  3437. }
  3438. return { matched: true, consumedSegments: [], lastChild: 0, positionalParamSegments: {} };
  3439. }
  3440. /** @type {?} */
  3441. const matcher = route.matcher || defaultUrlMatcher;
  3442. /** @type {?} */
  3443. const res = matcher(segments, segmentGroup, route);
  3444. if (!res) {
  3445. return {
  3446. matched: false,
  3447. consumedSegments: /** @type {?} */ ([]),
  3448. lastChild: 0,
  3449. positionalParamSegments: {},
  3450. };
  3451. }
  3452. return {
  3453. matched: true,
  3454. consumedSegments: /** @type {?} */ ((res.consumed)),
  3455. lastChild: /** @type {?} */ ((res.consumed.length)),
  3456. positionalParamSegments: /** @type {?} */ ((res.posParams)),
  3457. };
  3458. }
  3459. /**
  3460. * @param {?} segmentGroup
  3461. * @param {?} consumedSegments
  3462. * @param {?} slicedSegments
  3463. * @param {?} config
  3464. * @return {?}
  3465. */
  3466. function split(segmentGroup, consumedSegments, slicedSegments, config) {
  3467. if (slicedSegments.length > 0 &&
  3468. containsEmptyPathRedirectsWithNamedOutlets(segmentGroup, slicedSegments, config)) {
  3469. /** @type {?} */
  3470. const s = new UrlSegmentGroup(consumedSegments, createChildrenForEmptySegments(config, new UrlSegmentGroup(slicedSegments, segmentGroup.children)));
  3471. return { segmentGroup: mergeTrivialChildren(s), slicedSegments: [] };
  3472. }
  3473. if (slicedSegments.length === 0 &&
  3474. containsEmptyPathRedirects(segmentGroup, slicedSegments, config)) {
  3475. /** @type {?} */
  3476. const s = new UrlSegmentGroup(segmentGroup.segments, addEmptySegmentsToChildrenIfNeeded(segmentGroup, slicedSegments, config, segmentGroup.children));
  3477. return { segmentGroup: mergeTrivialChildren(s), slicedSegments };
  3478. }
  3479. return { segmentGroup, slicedSegments };
  3480. }
  3481. /**
  3482. * @param {?} s
  3483. * @return {?}
  3484. */
  3485. function mergeTrivialChildren(s) {
  3486. if (s.numberOfChildren === 1 && s.children[PRIMARY_OUTLET]) {
  3487. /** @type {?} */
  3488. const c = s.children[PRIMARY_OUTLET];
  3489. return new UrlSegmentGroup(s.segments.concat(c.segments), c.children);
  3490. }
  3491. return s;
  3492. }
  3493. /**
  3494. * @param {?} segmentGroup
  3495. * @param {?} slicedSegments
  3496. * @param {?} routes
  3497. * @param {?} children
  3498. * @return {?}
  3499. */
  3500. function addEmptySegmentsToChildrenIfNeeded(segmentGroup, slicedSegments, routes, children) {
  3501. /** @type {?} */
  3502. const res = {};
  3503. for (const r of routes) {
  3504. if (isEmptyPathRedirect(segmentGroup, slicedSegments, r) && !children[getOutlet(r)]) {
  3505. res[getOutlet(r)] = new UrlSegmentGroup([], {});
  3506. }
  3507. }
  3508. return Object.assign({}, children, res);
  3509. }
  3510. /**
  3511. * @param {?} routes
  3512. * @param {?} primarySegmentGroup
  3513. * @return {?}
  3514. */
  3515. function createChildrenForEmptySegments(routes, primarySegmentGroup) {
  3516. /** @type {?} */
  3517. const res = {};
  3518. res[PRIMARY_OUTLET] = primarySegmentGroup;
  3519. for (const r of routes) {
  3520. if (r.path === '' && getOutlet(r) !== PRIMARY_OUTLET) {
  3521. res[getOutlet(r)] = new UrlSegmentGroup([], {});
  3522. }
  3523. }
  3524. return res;
  3525. }
  3526. /**
  3527. * @param {?} segmentGroup
  3528. * @param {?} segments
  3529. * @param {?} routes
  3530. * @return {?}
  3531. */
  3532. function containsEmptyPathRedirectsWithNamedOutlets(segmentGroup, segments, routes) {
  3533. return routes.some(r => isEmptyPathRedirect(segmentGroup, segments, r) && getOutlet(r) !== PRIMARY_OUTLET);
  3534. }
  3535. /**
  3536. * @param {?} segmentGroup
  3537. * @param {?} segments
  3538. * @param {?} routes
  3539. * @return {?}
  3540. */
  3541. function containsEmptyPathRedirects(segmentGroup, segments, routes) {
  3542. return routes.some(r => isEmptyPathRedirect(segmentGroup, segments, r));
  3543. }
  3544. /**
  3545. * @param {?} segmentGroup
  3546. * @param {?} segments
  3547. * @param {?} r
  3548. * @return {?}
  3549. */
  3550. function isEmptyPathRedirect(segmentGroup, segments, r) {
  3551. if ((segmentGroup.hasChildren() || segments.length > 0) && r.pathMatch === 'full') {
  3552. return false;
  3553. }
  3554. return r.path === '' && r.redirectTo !== undefined;
  3555. }
  3556. /**
  3557. * @param {?} route
  3558. * @return {?}
  3559. */
  3560. function getOutlet(route) {
  3561. return route.outlet || PRIMARY_OUTLET;
  3562. }
  3563. /**
  3564. * @fileoverview added by tsickle
  3565. * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
  3566. */
  3567. /**
  3568. * @param {?} moduleInjector
  3569. * @param {?} configLoader
  3570. * @param {?} urlSerializer
  3571. * @param {?} config
  3572. * @return {?}
  3573. */
  3574. function applyRedirects$1(moduleInjector, configLoader, urlSerializer, config) {
  3575. return function (source) {
  3576. return source.pipe(switchMap(t => applyRedirects(moduleInjector, configLoader, urlSerializer, t.extractedUrl, config)
  3577. .pipe(map(urlAfterRedirects => (Object.assign({}, t, { urlAfterRedirects }))))));
  3578. };
  3579. }
  3580. /**
  3581. * @fileoverview added by tsickle
  3582. * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
  3583. */
  3584. class CanActivate {
  3585. /**
  3586. * @param {?} path
  3587. */
  3588. constructor(path) {
  3589. this.path = path;
  3590. this.route = this.path[this.path.length - 1];
  3591. }
  3592. }
  3593. class CanDeactivate {
  3594. /**
  3595. * @param {?} component
  3596. * @param {?} route
  3597. */
  3598. constructor(component, route) {
  3599. this.component = component;
  3600. this.route = route;
  3601. }
  3602. }
  3603. /**
  3604. * @param {?} future
  3605. * @param {?} curr
  3606. * @param {?} parentContexts
  3607. * @return {?}
  3608. */
  3609. function getAllRouteGuards(future, curr, parentContexts) {
  3610. /** @type {?} */
  3611. const futureRoot = future._root;
  3612. /** @type {?} */
  3613. const currRoot = curr ? curr._root : null;
  3614. return getChildRouteGuards(futureRoot, currRoot, parentContexts, [futureRoot.value]);
  3615. }
  3616. /**
  3617. * @param {?} p
  3618. * @return {?}
  3619. */
  3620. function getCanActivateChild(p) {
  3621. /** @type {?} */
  3622. const canActivateChild = p.routeConfig ? p.routeConfig.canActivateChild : null;
  3623. if (!canActivateChild || canActivateChild.length === 0)
  3624. return null;
  3625. return { node: p, guards: canActivateChild };
  3626. }
  3627. /**
  3628. * @param {?} token
  3629. * @param {?} snapshot
  3630. * @param {?} moduleInjector
  3631. * @return {?}
  3632. */
  3633. function getToken(token, snapshot, moduleInjector) {
  3634. /** @type {?} */
  3635. const config = getClosestLoadedConfig(snapshot);
  3636. /** @type {?} */
  3637. const injector = config ? config.module.injector : moduleInjector;
  3638. return injector.get(token);
  3639. }
  3640. /**
  3641. * @param {?} snapshot
  3642. * @return {?}
  3643. */
  3644. function getClosestLoadedConfig(snapshot) {
  3645. if (!snapshot)
  3646. return null;
  3647. for (let s = snapshot.parent; s; s = s.parent) {
  3648. /** @type {?} */
  3649. const route = s.routeConfig;
  3650. if (route && route._loadedConfig)
  3651. return route._loadedConfig;
  3652. }
  3653. return null;
  3654. }
  3655. /**
  3656. * @param {?} futureNode
  3657. * @param {?} currNode
  3658. * @param {?} contexts
  3659. * @param {?} futurePath
  3660. * @param {?=} checks
  3661. * @return {?}
  3662. */
  3663. function getChildRouteGuards(futureNode, currNode, contexts, futurePath, checks = {
  3664. canDeactivateChecks: [],
  3665. canActivateChecks: []
  3666. }) {
  3667. /** @type {?} */
  3668. const prevChildren = nodeChildrenAsMap(currNode);
  3669. // Process the children of the future route
  3670. futureNode.children.forEach(c => {
  3671. getRouteGuards(c, prevChildren[c.value.outlet], contexts, futurePath.concat([c.value]), checks);
  3672. delete prevChildren[c.value.outlet];
  3673. });
  3674. // Process any children left from the current route (not active for the future route)
  3675. forEach(prevChildren, (v, k) => deactivateRouteAndItsChildren(v, /** @type {?} */ ((contexts)).getContext(k), checks));
  3676. return checks;
  3677. }
  3678. /**
  3679. * @param {?} futureNode
  3680. * @param {?} currNode
  3681. * @param {?} parentContexts
  3682. * @param {?} futurePath
  3683. * @param {?=} checks
  3684. * @return {?}
  3685. */
  3686. function getRouteGuards(futureNode, currNode, parentContexts, futurePath, checks = {
  3687. canDeactivateChecks: [],
  3688. canActivateChecks: []
  3689. }) {
  3690. /** @type {?} */
  3691. const future = futureNode.value;
  3692. /** @type {?} */
  3693. const curr = currNode ? currNode.value : null;
  3694. /** @type {?} */
  3695. const context = parentContexts ? parentContexts.getContext(futureNode.value.outlet) : null;
  3696. // reusing the node
  3697. if (curr && future.routeConfig === curr.routeConfig) {
  3698. /** @type {?} */
  3699. const shouldRun = shouldRunGuardsAndResolvers(curr, future, /** @type {?} */ ((future.routeConfig)).runGuardsAndResolvers);
  3700. if (shouldRun) {
  3701. checks.canActivateChecks.push(new CanActivate(futurePath));
  3702. }
  3703. else {
  3704. // we need to set the data
  3705. future.data = curr.data;
  3706. future._resolvedData = curr._resolvedData;
  3707. }
  3708. // If we have a component, we need to go through an outlet.
  3709. if (future.component) {
  3710. getChildRouteGuards(futureNode, currNode, context ? context.children : null, futurePath, checks);
  3711. // if we have a componentless route, we recurse but keep the same outlet map.
  3712. }
  3713. else {
  3714. getChildRouteGuards(futureNode, currNode, parentContexts, futurePath, checks);
  3715. }
  3716. if (shouldRun) {
  3717. /** @type {?} */
  3718. const component = context && context.outlet && context.outlet.component || null;
  3719. checks.canDeactivateChecks.push(new CanDeactivate(component, curr));
  3720. }
  3721. }
  3722. else {
  3723. if (curr) {
  3724. deactivateRouteAndItsChildren(currNode, context, checks);
  3725. }
  3726. checks.canActivateChecks.push(new CanActivate(futurePath));
  3727. // If we have a component, we need to go through an outlet.
  3728. if (future.component) {
  3729. getChildRouteGuards(futureNode, null, context ? context.children : null, futurePath, checks);
  3730. // if we have a componentless route, we recurse but keep the same outlet map.
  3731. }
  3732. else {
  3733. getChildRouteGuards(futureNode, null, parentContexts, futurePath, checks);
  3734. }
  3735. }
  3736. return checks;
  3737. }
  3738. /**
  3739. * @param {?} curr
  3740. * @param {?} future
  3741. * @param {?} mode
  3742. * @return {?}
  3743. */
  3744. function shouldRunGuardsAndResolvers(curr, future, mode) {
  3745. switch (mode) {
  3746. case 'always':
  3747. return true;
  3748. case 'paramsOrQueryParamsChange':
  3749. return !equalParamsAndUrlSegments(curr, future) ||
  3750. !shallowEqual(curr.queryParams, future.queryParams);
  3751. case 'paramsChange':
  3752. default:
  3753. return !equalParamsAndUrlSegments(curr, future);
  3754. }
  3755. }
  3756. /**
  3757. * @param {?} route
  3758. * @param {?} context
  3759. * @param {?} checks
  3760. * @return {?}
  3761. */
  3762. function deactivateRouteAndItsChildren(route, context, checks) {
  3763. /** @type {?} */
  3764. const children = nodeChildrenAsMap(route);
  3765. /** @type {?} */
  3766. const r = route.value;
  3767. forEach(children, (node, childName) => {
  3768. if (!r.component) {
  3769. deactivateRouteAndItsChildren(node, context, checks);
  3770. }
  3771. else if (context) {
  3772. deactivateRouteAndItsChildren(node, context.children.getContext(childName), checks);
  3773. }
  3774. else {
  3775. deactivateRouteAndItsChildren(node, null, checks);
  3776. }
  3777. });
  3778. if (!r.component) {
  3779. checks.canDeactivateChecks.push(new CanDeactivate(null, r));
  3780. }
  3781. else if (context && context.outlet && context.outlet.isActivated) {
  3782. checks.canDeactivateChecks.push(new CanDeactivate(context.outlet.component, r));
  3783. }
  3784. else {
  3785. checks.canDeactivateChecks.push(new CanDeactivate(null, r));
  3786. }
  3787. }
  3788. /**
  3789. * @fileoverview added by tsickle
  3790. * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
  3791. */
  3792. /**
  3793. * @param {?} moduleInjector
  3794. * @param {?=} forwardEvent
  3795. * @return {?}
  3796. */
  3797. function checkGuards(moduleInjector, forwardEvent) {
  3798. return function (source) {
  3799. return source.pipe(mergeMap(t => {
  3800. const { targetSnapshot, currentSnapshot, guards: { canActivateChecks, canDeactivateChecks } } = t;
  3801. if (canDeactivateChecks.length === 0 && canActivateChecks.length === 0) {
  3802. return of(Object.assign({}, t, { guardsResult: true }));
  3803. }
  3804. return runCanDeactivateChecks(canDeactivateChecks, /** @type {?} */ ((targetSnapshot)), currentSnapshot, moduleInjector)
  3805. .pipe(mergeMap((canDeactivate) => {
  3806. return canDeactivate ?
  3807. runCanActivateChecks(/** @type {?} */ ((targetSnapshot)), canActivateChecks, moduleInjector, forwardEvent) :
  3808. of(false);
  3809. }), map(guardsResult => (Object.assign({}, t, { guardsResult }))));
  3810. }));
  3811. };
  3812. }
  3813. /**
  3814. * @param {?} checks
  3815. * @param {?} futureRSS
  3816. * @param {?} currRSS
  3817. * @param {?} moduleInjector
  3818. * @return {?}
  3819. */
  3820. function runCanDeactivateChecks(checks, futureRSS, currRSS, moduleInjector) {
  3821. return from(checks).pipe(mergeMap((check) => runCanDeactivate(check.component, check.route, currRSS, futureRSS, moduleInjector)), every((result) => result === true));
  3822. }
  3823. /**
  3824. * @param {?} futureSnapshot
  3825. * @param {?} checks
  3826. * @param {?} moduleInjector
  3827. * @param {?=} forwardEvent
  3828. * @return {?}
  3829. */
  3830. function runCanActivateChecks(futureSnapshot, checks, moduleInjector, forwardEvent) {
  3831. return from(checks).pipe(concatMap((check) => andObservables(from([
  3832. fireChildActivationStart(check.route.parent, forwardEvent),
  3833. fireActivationStart(check.route, forwardEvent),
  3834. runCanActivateChild(futureSnapshot, check.path, moduleInjector),
  3835. runCanActivate(futureSnapshot, check.route, moduleInjector)
  3836. ]))), every((result) => result === true));
  3837. }
  3838. /**
  3839. * This should fire off `ActivationStart` events for each route being activated at this
  3840. * level.
  3841. * In other words, if you're activating `a` and `b` below, `path` will contain the
  3842. * `ActivatedRouteSnapshot`s for both and we will fire `ActivationStart` for both. Always
  3843. * return
  3844. * `true` so checks continue to run.
  3845. * @param {?} snapshot
  3846. * @param {?=} forwardEvent
  3847. * @return {?}
  3848. */
  3849. function fireActivationStart(snapshot, forwardEvent) {
  3850. if (snapshot !== null && forwardEvent) {
  3851. forwardEvent(new ActivationStart(snapshot));
  3852. }
  3853. return of(true);
  3854. }
  3855. /**
  3856. * This should fire off `ChildActivationStart` events for each route being activated at this
  3857. * level.
  3858. * In other words, if you're activating `a` and `b` below, `path` will contain the
  3859. * `ActivatedRouteSnapshot`s for both and we will fire `ChildActivationStart` for both. Always
  3860. * return
  3861. * `true` so checks continue to run.
  3862. * @param {?} snapshot
  3863. * @param {?=} forwardEvent
  3864. * @return {?}
  3865. */
  3866. function fireChildActivationStart(snapshot, forwardEvent) {
  3867. if (snapshot !== null && forwardEvent) {
  3868. forwardEvent(new ChildActivationStart(snapshot));
  3869. }
  3870. return of(true);
  3871. }
  3872. /**
  3873. * @param {?} futureRSS
  3874. * @param {?} futureARS
  3875. * @param {?} moduleInjector
  3876. * @return {?}
  3877. */
  3878. function runCanActivate(futureRSS, futureARS, moduleInjector) {
  3879. /** @type {?} */
  3880. const canActivate = futureARS.routeConfig ? futureARS.routeConfig.canActivate : null;
  3881. if (!canActivate || canActivate.length === 0)
  3882. return of(true);
  3883. /** @type {?} */
  3884. const obs = from(canActivate).pipe(map((c) => {
  3885. /** @type {?} */
  3886. const guard = getToken(c, futureARS, moduleInjector);
  3887. /** @type {?} */
  3888. let observable;
  3889. if (guard.canActivate) {
  3890. observable = wrapIntoObservable(guard.canActivate(futureARS, futureRSS));
  3891. }
  3892. else {
  3893. observable = wrapIntoObservable(guard(futureARS, futureRSS));
  3894. }
  3895. return observable.pipe(first());
  3896. }));
  3897. return andObservables(obs);
  3898. }
  3899. /**
  3900. * @param {?} futureRSS
  3901. * @param {?} path
  3902. * @param {?} moduleInjector
  3903. * @return {?}
  3904. */
  3905. function runCanActivateChild(futureRSS, path, moduleInjector) {
  3906. /** @type {?} */
  3907. const futureARS = path[path.length - 1];
  3908. /** @type {?} */
  3909. const canActivateChildGuards = path.slice(0, path.length - 1)
  3910. .reverse()
  3911. .map(p => getCanActivateChild(p))
  3912. .filter(_ => _ !== null);
  3913. return andObservables(from(canActivateChildGuards).pipe(map((d) => {
  3914. /** @type {?} */
  3915. const obs = from(d.guards).pipe(map((c) => {
  3916. /** @type {?} */
  3917. const guard = getToken(c, d.node, moduleInjector);
  3918. /** @type {?} */
  3919. let observable;
  3920. if (guard.canActivateChild) {
  3921. observable = wrapIntoObservable(guard.canActivateChild(futureARS, futureRSS));
  3922. }
  3923. else {
  3924. observable = wrapIntoObservable(guard(futureARS, futureRSS));
  3925. }
  3926. return observable.pipe(first());
  3927. }));
  3928. return andObservables(obs);
  3929. })));
  3930. }
  3931. /**
  3932. * @param {?} component
  3933. * @param {?} currARS
  3934. * @param {?} currRSS
  3935. * @param {?} futureRSS
  3936. * @param {?} moduleInjector
  3937. * @return {?}
  3938. */
  3939. function runCanDeactivate(component, currARS, currRSS, futureRSS, moduleInjector) {
  3940. /** @type {?} */
  3941. const canDeactivate = currARS && currARS.routeConfig ? currARS.routeConfig.canDeactivate : null;
  3942. if (!canDeactivate || canDeactivate.length === 0)
  3943. return of(true);
  3944. /** @type {?} */
  3945. const canDeactivate$ = from(canDeactivate).pipe(mergeMap((c) => {
  3946. /** @type {?} */
  3947. const guard = getToken(c, currARS, moduleInjector);
  3948. /** @type {?} */
  3949. let observable;
  3950. if (guard.canDeactivate) {
  3951. observable = wrapIntoObservable(guard.canDeactivate(component, currARS, currRSS, futureRSS));
  3952. }
  3953. else {
  3954. observable = wrapIntoObservable(guard(component, currARS, currRSS, futureRSS));
  3955. }
  3956. return observable.pipe(first());
  3957. }));
  3958. return canDeactivate$.pipe(every((result) => result === true));
  3959. }
  3960. /**
  3961. * @fileoverview added by tsickle
  3962. * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
  3963. */
  3964. class NoMatch$1 {
  3965. }
  3966. /**
  3967. * @param {?} rootComponentType
  3968. * @param {?} config
  3969. * @param {?} urlTree
  3970. * @param {?} url
  3971. * @param {?=} paramsInheritanceStrategy
  3972. * @param {?=} relativeLinkResolution
  3973. * @return {?}
  3974. */
  3975. function recognize(rootComponentType, config, urlTree, url, paramsInheritanceStrategy = 'emptyOnly', relativeLinkResolution = 'legacy') {
  3976. return new Recognizer(rootComponentType, config, urlTree, url, paramsInheritanceStrategy, relativeLinkResolution)
  3977. .recognize();
  3978. }
  3979. class Recognizer {
  3980. /**
  3981. * @param {?} rootComponentType
  3982. * @param {?} config
  3983. * @param {?} urlTree
  3984. * @param {?} url
  3985. * @param {?} paramsInheritanceStrategy
  3986. * @param {?} relativeLinkResolution
  3987. */
  3988. constructor(rootComponentType, config, urlTree, url, paramsInheritanceStrategy, relativeLinkResolution) {
  3989. this.rootComponentType = rootComponentType;
  3990. this.config = config;
  3991. this.urlTree = urlTree;
  3992. this.url = url;
  3993. this.paramsInheritanceStrategy = paramsInheritanceStrategy;
  3994. this.relativeLinkResolution = relativeLinkResolution;
  3995. }
  3996. /**
  3997. * @return {?}
  3998. */
  3999. recognize() {
  4000. try {
  4001. /** @type {?} */
  4002. const rootSegmentGroup = split$1(this.urlTree.root, [], [], this.config, this.relativeLinkResolution).segmentGroup;
  4003. /** @type {?} */
  4004. const children = this.processSegmentGroup(this.config, rootSegmentGroup, PRIMARY_OUTLET);
  4005. /** @type {?} */
  4006. const root = new ActivatedRouteSnapshot([], Object.freeze({}), Object.freeze(Object.assign({}, this.urlTree.queryParams)), /** @type {?} */ ((this.urlTree.fragment)), {}, PRIMARY_OUTLET, this.rootComponentType, null, this.urlTree.root, -1, {});
  4007. /** @type {?} */
  4008. const rootNode = new TreeNode(root, children);
  4009. /** @type {?} */
  4010. const routeState = new RouterStateSnapshot(this.url, rootNode);
  4011. this.inheritParamsAndData(routeState._root);
  4012. return of(routeState);
  4013. }
  4014. catch (e) {
  4015. return new Observable((obs) => obs.error(e));
  4016. }
  4017. }
  4018. /**
  4019. * @param {?} routeNode
  4020. * @return {?}
  4021. */
  4022. inheritParamsAndData(routeNode) {
  4023. /** @type {?} */
  4024. const route = routeNode.value;
  4025. /** @type {?} */
  4026. const i = inheritedParamsDataResolve(route, this.paramsInheritanceStrategy);
  4027. route.params = Object.freeze(i.params);
  4028. route.data = Object.freeze(i.data);
  4029. routeNode.children.forEach(n => this.inheritParamsAndData(n));
  4030. }
  4031. /**
  4032. * @param {?} config
  4033. * @param {?} segmentGroup
  4034. * @param {?} outlet
  4035. * @return {?}
  4036. */
  4037. processSegmentGroup(config, segmentGroup, outlet) {
  4038. if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) {
  4039. return this.processChildren(config, segmentGroup);
  4040. }
  4041. return this.processSegment(config, segmentGroup, segmentGroup.segments, outlet);
  4042. }
  4043. /**
  4044. * @param {?} config
  4045. * @param {?} segmentGroup
  4046. * @return {?}
  4047. */
  4048. processChildren(config, segmentGroup) {
  4049. /** @type {?} */
  4050. const children = mapChildrenIntoArray(segmentGroup, (child, childOutlet) => this.processSegmentGroup(config, child, childOutlet));
  4051. checkOutletNameUniqueness(children);
  4052. sortActivatedRouteSnapshots(children);
  4053. return children;
  4054. }
  4055. /**
  4056. * @param {?} config
  4057. * @param {?} segmentGroup
  4058. * @param {?} segments
  4059. * @param {?} outlet
  4060. * @return {?}
  4061. */
  4062. processSegment(config, segmentGroup, segments, outlet) {
  4063. for (const r of config) {
  4064. try {
  4065. return this.processSegmentAgainstRoute(r, segmentGroup, segments, outlet);
  4066. }
  4067. catch (e) {
  4068. if (!(e instanceof NoMatch$1))
  4069. throw e;
  4070. }
  4071. }
  4072. if (this.noLeftoversInUrl(segmentGroup, segments, outlet)) {
  4073. return [];
  4074. }
  4075. throw new NoMatch$1();
  4076. }
  4077. /**
  4078. * @param {?} segmentGroup
  4079. * @param {?} segments
  4080. * @param {?} outlet
  4081. * @return {?}
  4082. */
  4083. noLeftoversInUrl(segmentGroup, segments, outlet) {
  4084. return segments.length === 0 && !segmentGroup.children[outlet];
  4085. }
  4086. /**
  4087. * @param {?} route
  4088. * @param {?} rawSegment
  4089. * @param {?} segments
  4090. * @param {?} outlet
  4091. * @return {?}
  4092. */
  4093. processSegmentAgainstRoute(route, rawSegment, segments, outlet) {
  4094. if (route.redirectTo)
  4095. throw new NoMatch$1();
  4096. if ((route.outlet || PRIMARY_OUTLET) !== outlet)
  4097. throw new NoMatch$1();
  4098. /** @type {?} */
  4099. let snapshot;
  4100. /** @type {?} */
  4101. let consumedSegments = [];
  4102. /** @type {?} */
  4103. let rawSlicedSegments = [];
  4104. if (route.path === '**') {
  4105. /** @type {?} */
  4106. const params = segments.length > 0 ? /** @type {?} */ ((last$1(segments))).parameters : {};
  4107. snapshot = new ActivatedRouteSnapshot(segments, params, Object.freeze(Object.assign({}, this.urlTree.queryParams)), /** @type {?} */ ((this.urlTree.fragment)), getData(route), outlet, /** @type {?} */ ((route.component)), route, getSourceSegmentGroup(rawSegment), getPathIndexShift(rawSegment) + segments.length, getResolve(route));
  4108. }
  4109. else {
  4110. /** @type {?} */
  4111. const result = match$1(rawSegment, route, segments);
  4112. consumedSegments = result.consumedSegments;
  4113. rawSlicedSegments = segments.slice(result.lastChild);
  4114. snapshot = new ActivatedRouteSnapshot(consumedSegments, result.parameters, Object.freeze(Object.assign({}, this.urlTree.queryParams)), /** @type {?} */ ((this.urlTree.fragment)), getData(route), outlet, /** @type {?} */ ((route.component)), route, getSourceSegmentGroup(rawSegment), getPathIndexShift(rawSegment) + consumedSegments.length, getResolve(route));
  4115. }
  4116. /** @type {?} */
  4117. const childConfig = getChildConfig(route);
  4118. const { segmentGroup, slicedSegments } = split$1(rawSegment, consumedSegments, rawSlicedSegments, childConfig, this.relativeLinkResolution);
  4119. if (slicedSegments.length === 0 && segmentGroup.hasChildren()) {
  4120. /** @type {?} */
  4121. const children = this.processChildren(childConfig, segmentGroup);
  4122. return [new TreeNode(snapshot, children)];
  4123. }
  4124. if (childConfig.length === 0 && slicedSegments.length === 0) {
  4125. return [new TreeNode(snapshot, [])];
  4126. }
  4127. /** @type {?} */
  4128. const children = this.processSegment(childConfig, segmentGroup, slicedSegments, PRIMARY_OUTLET);
  4129. return [new TreeNode(snapshot, children)];
  4130. }
  4131. }
  4132. /**
  4133. * @param {?} nodes
  4134. * @return {?}
  4135. */
  4136. function sortActivatedRouteSnapshots(nodes) {
  4137. nodes.sort((a, b) => {
  4138. if (a.value.outlet === PRIMARY_OUTLET)
  4139. return -1;
  4140. if (b.value.outlet === PRIMARY_OUTLET)
  4141. return 1;
  4142. return a.value.outlet.localeCompare(b.value.outlet);
  4143. });
  4144. }
  4145. /**
  4146. * @param {?} route
  4147. * @return {?}
  4148. */
  4149. function getChildConfig(route) {
  4150. if (route.children) {
  4151. return route.children;
  4152. }
  4153. if (route.loadChildren) {
  4154. return /** @type {?} */ ((route._loadedConfig)).routes;
  4155. }
  4156. return [];
  4157. }
  4158. /**
  4159. * @param {?} segmentGroup
  4160. * @param {?} route
  4161. * @param {?} segments
  4162. * @return {?}
  4163. */
  4164. function match$1(segmentGroup, route, segments) {
  4165. if (route.path === '') {
  4166. if (route.pathMatch === 'full' && (segmentGroup.hasChildren() || segments.length > 0)) {
  4167. throw new NoMatch$1();
  4168. }
  4169. return { consumedSegments: [], lastChild: 0, parameters: {} };
  4170. }
  4171. /** @type {?} */
  4172. const matcher = route.matcher || defaultUrlMatcher;
  4173. /** @type {?} */
  4174. const res = matcher(segments, segmentGroup, route);
  4175. if (!res)
  4176. throw new NoMatch$1();
  4177. /** @type {?} */
  4178. const posParams = {};
  4179. forEach(/** @type {?} */ ((res.posParams)), (v, k) => { posParams[k] = v.path; });
  4180. /** @type {?} */
  4181. const parameters = res.consumed.length > 0 ? Object.assign({}, posParams, res.consumed[res.consumed.length - 1].parameters) :
  4182. posParams;
  4183. return { consumedSegments: res.consumed, lastChild: res.consumed.length, parameters };
  4184. }
  4185. /**
  4186. * @param {?} nodes
  4187. * @return {?}
  4188. */
  4189. function checkOutletNameUniqueness(nodes) {
  4190. /** @type {?} */
  4191. const names = {};
  4192. nodes.forEach(n => {
  4193. /** @type {?} */
  4194. const routeWithSameOutletName = names[n.value.outlet];
  4195. if (routeWithSameOutletName) {
  4196. /** @type {?} */
  4197. const p = routeWithSameOutletName.url.map(s => s.toString()).join('/');
  4198. /** @type {?} */
  4199. const c = n.value.url.map(s => s.toString()).join('/');
  4200. throw new Error(`Two segments cannot have the same outlet name: '${p}' and '${c}'.`);
  4201. }
  4202. names[n.value.outlet] = n.value;
  4203. });
  4204. }
  4205. /**
  4206. * @param {?} segmentGroup
  4207. * @return {?}
  4208. */
  4209. function getSourceSegmentGroup(segmentGroup) {
  4210. /** @type {?} */
  4211. let s = segmentGroup;
  4212. while (s._sourceSegment) {
  4213. s = s._sourceSegment;
  4214. }
  4215. return s;
  4216. }
  4217. /**
  4218. * @param {?} segmentGroup
  4219. * @return {?}
  4220. */
  4221. function getPathIndexShift(segmentGroup) {
  4222. /** @type {?} */
  4223. let s = segmentGroup;
  4224. /** @type {?} */
  4225. let res = (s._segmentIndexShift ? s._segmentIndexShift : 0);
  4226. while (s._sourceSegment) {
  4227. s = s._sourceSegment;
  4228. res += (s._segmentIndexShift ? s._segmentIndexShift : 0);
  4229. }
  4230. return res - 1;
  4231. }
  4232. /**
  4233. * @param {?} segmentGroup
  4234. * @param {?} consumedSegments
  4235. * @param {?} slicedSegments
  4236. * @param {?} config
  4237. * @param {?} relativeLinkResolution
  4238. * @return {?}
  4239. */
  4240. function split$1(segmentGroup, consumedSegments, slicedSegments, config, relativeLinkResolution) {
  4241. if (slicedSegments.length > 0 &&
  4242. containsEmptyPathMatchesWithNamedOutlets(segmentGroup, slicedSegments, config)) {
  4243. /** @type {?} */
  4244. const s = new UrlSegmentGroup(consumedSegments, createChildrenForEmptyPaths(segmentGroup, consumedSegments, config, new UrlSegmentGroup(slicedSegments, segmentGroup.children)));
  4245. s._sourceSegment = segmentGroup;
  4246. s._segmentIndexShift = consumedSegments.length;
  4247. return { segmentGroup: s, slicedSegments: [] };
  4248. }
  4249. if (slicedSegments.length === 0 &&
  4250. containsEmptyPathMatches(segmentGroup, slicedSegments, config)) {
  4251. /** @type {?} */
  4252. const s = new UrlSegmentGroup(segmentGroup.segments, addEmptyPathsToChildrenIfNeeded(segmentGroup, consumedSegments, slicedSegments, config, segmentGroup.children, relativeLinkResolution));
  4253. s._sourceSegment = segmentGroup;
  4254. s._segmentIndexShift = consumedSegments.length;
  4255. return { segmentGroup: s, slicedSegments };
  4256. }
  4257. /** @type {?} */
  4258. const s = new UrlSegmentGroup(segmentGroup.segments, segmentGroup.children);
  4259. s._sourceSegment = segmentGroup;
  4260. s._segmentIndexShift = consumedSegments.length;
  4261. return { segmentGroup: s, slicedSegments };
  4262. }
  4263. /**
  4264. * @param {?} segmentGroup
  4265. * @param {?} consumedSegments
  4266. * @param {?} slicedSegments
  4267. * @param {?} routes
  4268. * @param {?} children
  4269. * @param {?} relativeLinkResolution
  4270. * @return {?}
  4271. */
  4272. function addEmptyPathsToChildrenIfNeeded(segmentGroup, consumedSegments, slicedSegments, routes, children, relativeLinkResolution) {
  4273. /** @type {?} */
  4274. const res = {};
  4275. for (const r of routes) {
  4276. if (emptyPathMatch(segmentGroup, slicedSegments, r) && !children[getOutlet$1(r)]) {
  4277. /** @type {?} */
  4278. const s = new UrlSegmentGroup([], {});
  4279. s._sourceSegment = segmentGroup;
  4280. if (relativeLinkResolution === 'legacy') {
  4281. s._segmentIndexShift = segmentGroup.segments.length;
  4282. }
  4283. else {
  4284. s._segmentIndexShift = consumedSegments.length;
  4285. }
  4286. res[getOutlet$1(r)] = s;
  4287. }
  4288. }
  4289. return Object.assign({}, children, res);
  4290. }
  4291. /**
  4292. * @param {?} segmentGroup
  4293. * @param {?} consumedSegments
  4294. * @param {?} routes
  4295. * @param {?} primarySegment
  4296. * @return {?}
  4297. */
  4298. function createChildrenForEmptyPaths(segmentGroup, consumedSegments, routes, primarySegment) {
  4299. /** @type {?} */
  4300. const res = {};
  4301. res[PRIMARY_OUTLET] = primarySegment;
  4302. primarySegment._sourceSegment = segmentGroup;
  4303. primarySegment._segmentIndexShift = consumedSegments.length;
  4304. for (const r of routes) {
  4305. if (r.path === '' && getOutlet$1(r) !== PRIMARY_OUTLET) {
  4306. /** @type {?} */
  4307. const s = new UrlSegmentGroup([], {});
  4308. s._sourceSegment = segmentGroup;
  4309. s._segmentIndexShift = consumedSegments.length;
  4310. res[getOutlet$1(r)] = s;
  4311. }
  4312. }
  4313. return res;
  4314. }
  4315. /**
  4316. * @param {?} segmentGroup
  4317. * @param {?} slicedSegments
  4318. * @param {?} routes
  4319. * @return {?}
  4320. */
  4321. function containsEmptyPathMatchesWithNamedOutlets(segmentGroup, slicedSegments, routes) {
  4322. return routes.some(r => emptyPathMatch(segmentGroup, slicedSegments, r) && getOutlet$1(r) !== PRIMARY_OUTLET);
  4323. }
  4324. /**
  4325. * @param {?} segmentGroup
  4326. * @param {?} slicedSegments
  4327. * @param {?} routes
  4328. * @return {?}
  4329. */
  4330. function containsEmptyPathMatches(segmentGroup, slicedSegments, routes) {
  4331. return routes.some(r => emptyPathMatch(segmentGroup, slicedSegments, r));
  4332. }
  4333. /**
  4334. * @param {?} segmentGroup
  4335. * @param {?} slicedSegments
  4336. * @param {?} r
  4337. * @return {?}
  4338. */
  4339. function emptyPathMatch(segmentGroup, slicedSegments, r) {
  4340. if ((segmentGroup.hasChildren() || slicedSegments.length > 0) && r.pathMatch === 'full') {
  4341. return false;
  4342. }
  4343. return r.path === '' && r.redirectTo === undefined;
  4344. }
  4345. /**
  4346. * @param {?} route
  4347. * @return {?}
  4348. */
  4349. function getOutlet$1(route) {
  4350. return route.outlet || PRIMARY_OUTLET;
  4351. }
  4352. /**
  4353. * @param {?} route
  4354. * @return {?}
  4355. */
  4356. function getData(route) {
  4357. return route.data || {};
  4358. }
  4359. /**
  4360. * @param {?} route
  4361. * @return {?}
  4362. */
  4363. function getResolve(route) {
  4364. return route.resolve || {};
  4365. }
  4366. /**
  4367. * @fileoverview added by tsickle
  4368. * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
  4369. */
  4370. /**
  4371. * @param {?} rootComponentType
  4372. * @param {?} config
  4373. * @param {?} serializer
  4374. * @param {?} paramsInheritanceStrategy
  4375. * @return {?}
  4376. */
  4377. function recognize$1(rootComponentType, config, serializer, paramsInheritanceStrategy) {
  4378. return function (source) {
  4379. return source.pipe(mergeMap(t => recognize(rootComponentType, config, t.urlAfterRedirects, serializer(t.urlAfterRedirects), paramsInheritanceStrategy)
  4380. .pipe(map(targetSnapshot => (Object.assign({}, t, { targetSnapshot }))))));
  4381. };
  4382. }
  4383. /**
  4384. * @fileoverview added by tsickle
  4385. * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
  4386. */
  4387. /**
  4388. * @param {?} paramsInheritanceStrategy
  4389. * @param {?} moduleInjector
  4390. * @return {?}
  4391. */
  4392. function resolveData(paramsInheritanceStrategy, moduleInjector) {
  4393. return function (source) {
  4394. return source.pipe(mergeMap(t => {
  4395. const { targetSnapshot, guards: { canActivateChecks } } = t;
  4396. if (!canActivateChecks.length) {
  4397. return of(t);
  4398. }
  4399. return from(canActivateChecks)
  4400. .pipe(concatMap(check => runResolve(check.route, /** @type {?} */ ((targetSnapshot)), paramsInheritanceStrategy, moduleInjector)), reduce((_, __) => _), map(_ => t));
  4401. }));
  4402. };
  4403. }
  4404. /**
  4405. * @param {?} futureARS
  4406. * @param {?} futureRSS
  4407. * @param {?} paramsInheritanceStrategy
  4408. * @param {?} moduleInjector
  4409. * @return {?}
  4410. */
  4411. function runResolve(futureARS, futureRSS, paramsInheritanceStrategy, moduleInjector) {
  4412. /** @type {?} */
  4413. const resolve = futureARS._resolve;
  4414. return resolveNode(resolve, futureARS, futureRSS, moduleInjector)
  4415. .pipe(map((resolvedData) => {
  4416. futureARS._resolvedData = resolvedData;
  4417. futureARS.data = Object.assign({}, futureARS.data, inheritedParamsDataResolve(futureARS, paramsInheritanceStrategy).resolve);
  4418. return null;
  4419. }));
  4420. }
  4421. /**
  4422. * @param {?} resolve
  4423. * @param {?} futureARS
  4424. * @param {?} futureRSS
  4425. * @param {?} moduleInjector
  4426. * @return {?}
  4427. */
  4428. function resolveNode(resolve, futureARS, futureRSS, moduleInjector) {
  4429. /** @type {?} */
  4430. const keys = Object.keys(resolve);
  4431. if (keys.length === 0) {
  4432. return of({});
  4433. }
  4434. if (keys.length === 1) {
  4435. /** @type {?} */
  4436. const key = keys[0];
  4437. return getResolver(resolve[key], futureARS, futureRSS, moduleInjector)
  4438. .pipe(map((value) => { return { [key]: value }; }));
  4439. }
  4440. /** @type {?} */
  4441. const data = {};
  4442. /** @type {?} */
  4443. const runningResolvers$ = from(keys).pipe(mergeMap((key) => {
  4444. return getResolver(resolve[key], futureARS, futureRSS, moduleInjector)
  4445. .pipe(map((value) => {
  4446. data[key] = value;
  4447. return value;
  4448. }));
  4449. }));
  4450. return runningResolvers$.pipe(last(), map(() => data));
  4451. }
  4452. /**
  4453. * @param {?} injectionToken
  4454. * @param {?} futureARS
  4455. * @param {?} futureRSS
  4456. * @param {?} moduleInjector
  4457. * @return {?}
  4458. */
  4459. function getResolver(injectionToken, futureARS, futureRSS, moduleInjector) {
  4460. /** @type {?} */
  4461. const resolver = getToken(injectionToken, futureARS, moduleInjector);
  4462. return resolver.resolve ? wrapIntoObservable(resolver.resolve(futureARS, futureRSS)) :
  4463. wrapIntoObservable(resolver(futureARS, futureRSS));
  4464. }
  4465. /**
  4466. * @fileoverview added by tsickle
  4467. * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
  4468. */
  4469. /**
  4470. * Perform a side effect through a switchMap for every emission on the source Observable,
  4471. * but return an Observable that is identical to the source. It's essentially the same as
  4472. * the `tap` operator, but if the side effectful `next` function returns an ObservableInput,
  4473. * it will wait before continuing with the original value.
  4474. * @template T
  4475. * @param {?} next
  4476. * @return {?}
  4477. */
  4478. function switchTap(next) {
  4479. return function (source) {
  4480. return source.pipe(switchMap(v => {
  4481. /** @type {?} */
  4482. const nextResult = next(v);
  4483. if (nextResult) {
  4484. return from(nextResult).pipe(map(() => v));
  4485. }
  4486. return from([v]);
  4487. }));
  4488. };
  4489. }
  4490. /**
  4491. * @fileoverview added by tsickle
  4492. * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
  4493. */
  4494. /**
  4495. * \@description
  4496. *
  4497. * Provides a way to customize when activated routes get reused.
  4498. *
  4499. * \@publicApi
  4500. * @abstract
  4501. */
  4502. class RouteReuseStrategy {
  4503. }
  4504. /**
  4505. * Does not detach any subtrees. Reuses routes as long as their route config is the same.
  4506. */
  4507. class DefaultRouteReuseStrategy {
  4508. /**
  4509. * @param {?} route
  4510. * @return {?}
  4511. */
  4512. shouldDetach(route) { return false; }
  4513. /**
  4514. * @param {?} route
  4515. * @param {?} detachedTree
  4516. * @return {?}
  4517. */
  4518. store(route, detachedTree) { }
  4519. /**
  4520. * @param {?} route
  4521. * @return {?}
  4522. */
  4523. shouldAttach(route) { return false; }
  4524. /**
  4525. * @param {?} route
  4526. * @return {?}
  4527. */
  4528. retrieve(route) { return null; }
  4529. /**
  4530. * @param {?} future
  4531. * @param {?} curr
  4532. * @return {?}
  4533. */
  4534. shouldReuseRoute(future, curr) {
  4535. return future.routeConfig === curr.routeConfig;
  4536. }
  4537. }
  4538. /**
  4539. * @fileoverview added by tsickle
  4540. * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
  4541. */
  4542. /** *
  4543. * \@docsNotRequired
  4544. * \@publicApi
  4545. @type {?} */
  4546. const ROUTES = new InjectionToken('ROUTES');
  4547. class RouterConfigLoader {
  4548. /**
  4549. * @param {?} loader
  4550. * @param {?} compiler
  4551. * @param {?=} onLoadStartListener
  4552. * @param {?=} onLoadEndListener
  4553. */
  4554. constructor(loader, compiler, onLoadStartListener, onLoadEndListener) {
  4555. this.loader = loader;
  4556. this.compiler = compiler;
  4557. this.onLoadStartListener = onLoadStartListener;
  4558. this.onLoadEndListener = onLoadEndListener;
  4559. }
  4560. /**
  4561. * @param {?} parentInjector
  4562. * @param {?} route
  4563. * @return {?}
  4564. */
  4565. load(parentInjector, route) {
  4566. if (this.onLoadStartListener) {
  4567. this.onLoadStartListener(route);
  4568. }
  4569. /** @type {?} */
  4570. const moduleFactory$ = this.loadModuleFactory(/** @type {?} */ ((route.loadChildren)));
  4571. return moduleFactory$.pipe(map((factory) => {
  4572. if (this.onLoadEndListener) {
  4573. this.onLoadEndListener(route);
  4574. }
  4575. /** @type {?} */
  4576. const module = factory.create(parentInjector);
  4577. return new LoadedRouterConfig(flatten(module.injector.get(ROUTES)).map(standardizeConfig), module);
  4578. }));
  4579. }
  4580. /**
  4581. * @param {?} loadChildren
  4582. * @return {?}
  4583. */
  4584. loadModuleFactory(loadChildren) {
  4585. if (typeof loadChildren === 'string') {
  4586. return from(this.loader.load(loadChildren));
  4587. }
  4588. else {
  4589. return wrapIntoObservable(loadChildren()).pipe(mergeMap((t) => {
  4590. if (t instanceof NgModuleFactory) {
  4591. return of(t);
  4592. }
  4593. else {
  4594. return from(this.compiler.compileModuleAsync(t));
  4595. }
  4596. }));
  4597. }
  4598. }
  4599. }
  4600. /**
  4601. * @fileoverview added by tsickle
  4602. * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
  4603. */
  4604. /**
  4605. * @license
  4606. * Copyright Google Inc. All Rights Reserved.
  4607. *
  4608. * Use of this source code is governed by an MIT-style license that can be
  4609. * found in the LICENSE file at https://angular.io/license
  4610. */
  4611. /**
  4612. * \@description
  4613. *
  4614. * Provides a way to migrate AngularJS applications to Angular.
  4615. *
  4616. * \@publicApi
  4617. * @abstract
  4618. */
  4619. class UrlHandlingStrategy {
  4620. }
  4621. /**
  4622. * \@publicApi
  4623. */
  4624. class DefaultUrlHandlingStrategy {
  4625. /**
  4626. * @param {?} url
  4627. * @return {?}
  4628. */
  4629. shouldProcessUrl(url) { return true; }
  4630. /**
  4631. * @param {?} url
  4632. * @return {?}
  4633. */
  4634. extract(url) { return url; }
  4635. /**
  4636. * @param {?} newUrlPart
  4637. * @param {?} wholeUrl
  4638. * @return {?}
  4639. */
  4640. merge(newUrlPart, wholeUrl) { return newUrlPart; }
  4641. }
  4642. /**
  4643. * @fileoverview added by tsickle
  4644. * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
  4645. */
  4646. /**
  4647. * @param {?} error
  4648. * @return {?}
  4649. */
  4650. function defaultErrorHandler(error) {
  4651. throw error;
  4652. }
  4653. /**
  4654. * @param {?} error
  4655. * @param {?} urlSerializer
  4656. * @param {?} url
  4657. * @return {?}
  4658. */
  4659. function defaultMalformedUriErrorHandler(error, urlSerializer, url) {
  4660. return urlSerializer.parse('/');
  4661. }
  4662. /**
  4663. * \@internal
  4664. * @param {?} snapshot
  4665. * @param {?} runExtras
  4666. * @return {?}
  4667. */
  4668. function defaultRouterHook(snapshot, runExtras) {
  4669. return /** @type {?} */ (of(null));
  4670. }
  4671. /**
  4672. * \@description
  4673. *
  4674. * Provides the navigation and url manipulation capabilities.
  4675. *
  4676. * See `Routes` for more details and examples.
  4677. *
  4678. * \@ngModule RouterModule
  4679. *
  4680. * \@publicApi
  4681. */
  4682. class Router {
  4683. /**
  4684. * Creates the router service.
  4685. * @param {?} rootComponentType
  4686. * @param {?} urlSerializer
  4687. * @param {?} rootContexts
  4688. * @param {?} location
  4689. * @param {?} injector
  4690. * @param {?} loader
  4691. * @param {?} compiler
  4692. * @param {?} config
  4693. */
  4694. constructor(rootComponentType, urlSerializer, rootContexts, location, injector, loader, compiler, config) {
  4695. this.rootComponentType = rootComponentType;
  4696. this.urlSerializer = urlSerializer;
  4697. this.rootContexts = rootContexts;
  4698. this.location = location;
  4699. this.config = config;
  4700. this.navigationId = 0;
  4701. this.isNgZoneEnabled = false;
  4702. this.events = new Subject();
  4703. /**
  4704. * Error handler that is invoked when a navigation errors.
  4705. *
  4706. * See `ErrorHandler` for more information.
  4707. */
  4708. this.errorHandler = defaultErrorHandler;
  4709. /**
  4710. * Malformed uri error handler is invoked when `Router.parseUrl(url)` throws an
  4711. * error due to containing an invalid character. The most common case would be a `%` sign
  4712. * that's not encoded and is not part of a percent encoded sequence.
  4713. */
  4714. this.malformedUriErrorHandler = defaultMalformedUriErrorHandler;
  4715. /**
  4716. * Indicates if at least one navigation happened.
  4717. */
  4718. this.navigated = false;
  4719. this.lastSuccessfulId = -1;
  4720. /**
  4721. * Used by RouterModule. This allows us to
  4722. * pause the navigation either before preactivation or after it.
  4723. * \@internal
  4724. */
  4725. this.hooks = {
  4726. beforePreactivation: defaultRouterHook,
  4727. afterPreactivation: defaultRouterHook
  4728. };
  4729. /**
  4730. * Extracts and merges URLs. Used for AngularJS to Angular migrations.
  4731. */
  4732. this.urlHandlingStrategy = new DefaultUrlHandlingStrategy();
  4733. this.routeReuseStrategy = new DefaultRouteReuseStrategy();
  4734. /**
  4735. * Define what the router should do if it receives a navigation request to the current URL.
  4736. * By default, the router will ignore this navigation. However, this prevents features such
  4737. * as a "refresh" button. Use this option to configure the behavior when navigating to the
  4738. * current URL. Default is 'ignore'.
  4739. */
  4740. this.onSameUrlNavigation = 'ignore';
  4741. /**
  4742. * Defines how the router merges params, data and resolved data from parent to child
  4743. * routes. Available options are:
  4744. *
  4745. * - `'emptyOnly'`, the default, only inherits parent params for path-less or component-less
  4746. * routes.
  4747. * - `'always'`, enables unconditional inheritance of parent params.
  4748. */
  4749. this.paramsInheritanceStrategy = 'emptyOnly';
  4750. /**
  4751. * Defines when the router updates the browser URL. The default behavior is to update after
  4752. * successful navigation. However, some applications may prefer a mode where the URL gets
  4753. * updated at the beginning of navigation. The most common use case would be updating the
  4754. * URL early so if navigation fails, you can show an error message with the URL that failed.
  4755. * Available options are:
  4756. *
  4757. * - `'deferred'`, the default, updates the browser URL after navigation has finished.
  4758. * - `'eager'`, updates browser URL at the beginning of navigation.
  4759. */
  4760. this.urlUpdateStrategy = 'deferred';
  4761. /**
  4762. * See {\@link RouterModule} for more information.
  4763. */
  4764. this.relativeLinkResolution = 'legacy';
  4765. /** @type {?} */
  4766. const onLoadStart = (r) => this.triggerEvent(new RouteConfigLoadStart(r));
  4767. /** @type {?} */
  4768. const onLoadEnd = (r) => this.triggerEvent(new RouteConfigLoadEnd(r));
  4769. this.ngModule = injector.get(NgModuleRef);
  4770. this.console = injector.get(ɵConsole);
  4771. /** @type {?} */
  4772. const ngZone = injector.get(NgZone);
  4773. this.isNgZoneEnabled = ngZone instanceof NgZone;
  4774. this.resetConfig(config);
  4775. this.currentUrlTree = createEmptyUrlTree();
  4776. this.rawUrlTree = this.currentUrlTree;
  4777. this.configLoader = new RouterConfigLoader(loader, compiler, onLoadStart, onLoadEnd);
  4778. this.routerState = createEmptyState(this.currentUrlTree, this.rootComponentType);
  4779. this.transitions = new BehaviorSubject({
  4780. id: 0,
  4781. currentUrlTree: this.currentUrlTree,
  4782. currentRawUrl: this.currentUrlTree,
  4783. extractedUrl: this.urlHandlingStrategy.extract(this.currentUrlTree),
  4784. urlAfterRedirects: this.urlHandlingStrategy.extract(this.currentUrlTree),
  4785. rawUrl: this.currentUrlTree,
  4786. extras: {},
  4787. resolve: null,
  4788. reject: null,
  4789. promise: Promise.resolve(true),
  4790. source: 'imperative',
  4791. state: null,
  4792. currentSnapshot: this.routerState.snapshot,
  4793. targetSnapshot: null,
  4794. currentRouterState: this.routerState,
  4795. targetRouterState: null,
  4796. guards: { canActivateChecks: [], canDeactivateChecks: [] },
  4797. guardsResult: null,
  4798. });
  4799. this.navigations = this.setupNavigations(this.transitions);
  4800. this.processNavigations();
  4801. }
  4802. /**
  4803. * @param {?} transitions
  4804. * @return {?}
  4805. */
  4806. setupNavigations(transitions) {
  4807. /** @type {?} */
  4808. const eventsSubject = (/** @type {?} */ (this.events));
  4809. return /** @type {?} */ ((transitions.pipe(filter(t => t.id !== 0),
  4810. // Extract URL
  4811. map(t => (/** @type {?} */ (Object.assign({}, t, { extractedUrl: this.urlHandlingStrategy.extract(t.rawUrl) })))),
  4812. // Using switchMap so we cancel executing navigations when a new one comes in
  4813. switchMap(t => {
  4814. /** @type {?} */
  4815. let completed = false;
  4816. /** @type {?} */
  4817. let errored = false;
  4818. return of(t).pipe(switchMap(t => {
  4819. /** @type {?} */
  4820. const urlTransition = !this.navigated || t.extractedUrl.toString() !== this.currentUrlTree.toString();
  4821. /** @type {?} */
  4822. const processCurrentUrl = (this.onSameUrlNavigation === 'reload' ? true : urlTransition) &&
  4823. this.urlHandlingStrategy.shouldProcessUrl(t.rawUrl);
  4824. if (processCurrentUrl) {
  4825. return of(t).pipe(
  4826. // Update URL if in `eager` update mode
  4827. tap(t => this.urlUpdateStrategy === 'eager' && !t.extras.skipLocationChange &&
  4828. this.setBrowserUrl(t.rawUrl, !!t.extras.replaceUrl, t.id)),
  4829. // Fire NavigationStart event
  4830. switchMap(t => {
  4831. /** @type {?} */
  4832. const transition = this.transitions.getValue();
  4833. eventsSubject.next(new NavigationStart(t.id, this.serializeUrl(t.extractedUrl), t.source, t.state));
  4834. if (transition !== this.transitions.getValue()) {
  4835. return EMPTY;
  4836. }
  4837. return [t];
  4838. }),
  4839. // This delay is required to match old behavior that forced navigation to
  4840. // always be async
  4841. switchMap(t => Promise.resolve(t)),
  4842. // ApplyRedirects
  4843. applyRedirects$1(this.ngModule.injector, this.configLoader, this.urlSerializer, this.config),
  4844. // Recognize
  4845. recognize$1(this.rootComponentType, this.config, (url) => this.serializeUrl(url), this.paramsInheritanceStrategy),
  4846. // Fire RoutesRecognized
  4847. tap(t => {
  4848. /** @type {?} */
  4849. const routesRecognized = new RoutesRecognized(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(t.urlAfterRedirects), /** @type {?} */ ((t.targetSnapshot)));
  4850. eventsSubject.next(routesRecognized);
  4851. }));
  4852. }
  4853. else {
  4854. /** @type {?} */
  4855. const processPreviousUrl = urlTransition && this.rawUrlTree &&
  4856. this.urlHandlingStrategy.shouldProcessUrl(this.rawUrlTree);
  4857. /* When the current URL shouldn't be processed, but the previous one was, we
  4858. * handle this "error condition" by navigating to the previously successful URL,
  4859. * but leaving the URL intact.*/
  4860. if (processPreviousUrl) {
  4861. const { id, extractedUrl, source, state, extras } = t;
  4862. /** @type {?} */
  4863. const navStart = new NavigationStart(id, this.serializeUrl(extractedUrl), source, state);
  4864. eventsSubject.next(navStart);
  4865. /** @type {?} */
  4866. const targetSnapshot = createEmptyState(extractedUrl, this.rootComponentType).snapshot;
  4867. return of(Object.assign({}, t, { targetSnapshot, urlAfterRedirects: extractedUrl, extras: Object.assign({}, extras, { skipLocationChange: false, replaceUrl: false }) }));
  4868. }
  4869. else {
  4870. /* When neither the current or previous URL can be processed, do nothing other
  4871. * than update router's internal reference to the current "settled" URL. This
  4872. * way the next navigation will be coming from the current URL in the browser.
  4873. */
  4874. this.rawUrlTree = t.rawUrl;
  4875. t.resolve(null);
  4876. return EMPTY;
  4877. }
  4878. }
  4879. }),
  4880. // Before Preactivation
  4881. switchTap(t => {
  4882. const { targetSnapshot, id: navigationId, extractedUrl: appliedUrlTree, rawUrl: rawUrlTree, extras: { skipLocationChange, replaceUrl } } = t;
  4883. return this.hooks.beforePreactivation(/** @type {?} */ ((targetSnapshot)), {
  4884. navigationId,
  4885. appliedUrlTree,
  4886. rawUrlTree,
  4887. skipLocationChange: !!skipLocationChange,
  4888. replaceUrl: !!replaceUrl,
  4889. });
  4890. }),
  4891. // --- GUARDS ---
  4892. tap(t => {
  4893. /** @type {?} */
  4894. const guardsStart = new GuardsCheckStart(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(t.urlAfterRedirects), /** @type {?} */ ((t.targetSnapshot)));
  4895. this.triggerEvent(guardsStart);
  4896. }), map(t => (Object.assign({}, t, { guards: getAllRouteGuards(/** @type {?} */ ((t.targetSnapshot)), t.currentSnapshot, this.rootContexts) }))), checkGuards(this.ngModule.injector, (evt) => this.triggerEvent(evt)), tap(t => {
  4897. /** @type {?} */
  4898. const guardsEnd = new GuardsCheckEnd(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(t.urlAfterRedirects), /** @type {?} */ ((t.targetSnapshot)), !!t.guardsResult);
  4899. this.triggerEvent(guardsEnd);
  4900. }), filter(t => {
  4901. if (!t.guardsResult) {
  4902. this.resetUrlToCurrentUrlTree();
  4903. /** @type {?} */
  4904. const navCancel = new NavigationCancel(t.id, this.serializeUrl(t.extractedUrl), '');
  4905. eventsSubject.next(navCancel);
  4906. t.resolve(false);
  4907. return false;
  4908. }
  4909. return true;
  4910. }),
  4911. // --- RESOLVE ---
  4912. switchTap(t => {
  4913. if (t.guards.canActivateChecks.length) {
  4914. return of(t).pipe(tap(t => {
  4915. /** @type {?} */
  4916. const resolveStart = new ResolveStart(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(t.urlAfterRedirects), /** @type {?} */ ((t.targetSnapshot)));
  4917. this.triggerEvent(resolveStart);
  4918. }), resolveData(this.paramsInheritanceStrategy, this.ngModule.injector), //
  4919. //
  4920. tap(t => {
  4921. /** @type {?} */
  4922. const resolveEnd = new ResolveEnd(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(t.urlAfterRedirects), /** @type {?} */ ((t.targetSnapshot)));
  4923. this.triggerEvent(resolveEnd);
  4924. }));
  4925. }
  4926. return undefined;
  4927. }),
  4928. // --- AFTER PREACTIVATION ---
  4929. switchTap(t => {
  4930. const { targetSnapshot, id: navigationId, extractedUrl: appliedUrlTree, rawUrl: rawUrlTree, extras: { skipLocationChange, replaceUrl } } = t;
  4931. return this.hooks.afterPreactivation(/** @type {?} */ ((targetSnapshot)), {
  4932. navigationId,
  4933. appliedUrlTree,
  4934. rawUrlTree,
  4935. skipLocationChange: !!skipLocationChange,
  4936. replaceUrl: !!replaceUrl,
  4937. });
  4938. }), map(t => {
  4939. /** @type {?} */
  4940. const targetRouterState = createRouterState(this.routeReuseStrategy, /** @type {?} */ ((t.targetSnapshot)), t.currentRouterState);
  4941. return (Object.assign({}, t, { targetRouterState }));
  4942. }), /* Once here, we are about to activate syncronously. The assumption is this will
  4943. succeed, and user code may read from the Router service. Therefore before
  4944. activation, we need to update router properties storing the current URL and the
  4945. RouterState, as well as updated the browser URL. All this should happen *before*
  4946. activating. */
  4947. tap(t => {
  4948. this.currentUrlTree = t.urlAfterRedirects;
  4949. this.rawUrlTree = this.urlHandlingStrategy.merge(this.currentUrlTree, t.rawUrl);
  4950. (/** @type {?} */ (this)).routerState = /** @type {?} */ ((t.targetRouterState));
  4951. if (this.urlUpdateStrategy === 'deferred' && !t.extras.skipLocationChange) {
  4952. this.setBrowserUrl(this.rawUrlTree, !!t.extras.replaceUrl, t.id);
  4953. }
  4954. }), activateRoutes(this.rootContexts, this.routeReuseStrategy, (evt) => this.triggerEvent(evt)), tap({
  4955. /**
  4956. * @return {?}
  4957. */
  4958. next() { completed = true; }, /**
  4959. * @return {?}
  4960. */
  4961. complete() { completed = true; }
  4962. }), finalize(() => {
  4963. /* When the navigation stream finishes either through error or success, we set the
  4964. * `completed` or `errored` flag. However, there are some situations where we could
  4965. * get here without either of those being set. For instance, a redirect during
  4966. * NavigationStart. Therefore, this is a catch-all to make sure the NavigationCancel
  4967. * event is fired when a navigation gets cancelled but not caught by other means. */
  4968. if (!completed && !errored) {
  4969. // Must reset to current URL tree here to ensure history.state is set. On a fresh
  4970. // page load, if a new navigation comes in before a successful navigation
  4971. // completes, there will be nothing in history.state.navigationId. This can cause
  4972. // sync problems with AngularJS sync code which looks for a value here in order
  4973. // to determine whether or not to handle a given popstate event or to leave it
  4974. // to the Angualr router.
  4975. this.resetUrlToCurrentUrlTree();
  4976. /** @type {?} */
  4977. const navCancel = new NavigationCancel(t.id, this.serializeUrl(t.extractedUrl), `Navigation ID ${t.id} is not equal to the current navigation id ${this.navigationId}`);
  4978. eventsSubject.next(navCancel);
  4979. t.resolve(false);
  4980. }
  4981. }), catchError((e) => {
  4982. errored = true;
  4983. /* This error type is issued during Redirect, and is handled as a cancellation
  4984. * rather than an error. */
  4985. if (isNavigationCancelingError(e)) {
  4986. this.navigated = true;
  4987. this.resetStateAndUrl(t.currentRouterState, t.currentUrlTree, t.rawUrl);
  4988. /** @type {?} */
  4989. const navCancel = new NavigationCancel(t.id, this.serializeUrl(t.extractedUrl), e.message);
  4990. eventsSubject.next(navCancel);
  4991. t.resolve(false);
  4992. /* All other errors should reset to the router's internal URL reference to the
  4993. * pre-error state. */
  4994. }
  4995. else {
  4996. this.resetStateAndUrl(t.currentRouterState, t.currentUrlTree, t.rawUrl);
  4997. /** @type {?} */
  4998. const navError = new NavigationError(t.id, this.serializeUrl(t.extractedUrl), e);
  4999. eventsSubject.next(navError);
  5000. try {
  5001. t.resolve(this.errorHandler(e));
  5002. }
  5003. catch (ee) {
  5004. t.reject(ee);
  5005. }
  5006. }
  5007. return EMPTY;
  5008. }));
  5009. // TODO(jasonaden): remove cast once g3 is on updated TypeScript
  5010. }))));
  5011. }
  5012. /**
  5013. * \@internal
  5014. * TODO: this should be removed once the constructor of the router made internal
  5015. * @param {?} rootComponentType
  5016. * @return {?}
  5017. */
  5018. resetRootComponentType(rootComponentType) {
  5019. this.rootComponentType = rootComponentType;
  5020. // TODO: vsavkin router 4.0 should make the root component set to null
  5021. // this will simplify the lifecycle of the router.
  5022. this.routerState.root.component = this.rootComponentType;
  5023. }
  5024. /**
  5025. * @return {?}
  5026. */
  5027. getTransition() { return this.transitions.value; }
  5028. /**
  5029. * @param {?} t
  5030. * @return {?}
  5031. */
  5032. setTransition(t) {
  5033. this.transitions.next(Object.assign({}, this.getTransition(), t));
  5034. }
  5035. /**
  5036. * Sets up the location change listener and performs the initial navigation.
  5037. * @return {?}
  5038. */
  5039. initialNavigation() {
  5040. this.setUpLocationChangeListener();
  5041. if (this.navigationId === 0) {
  5042. this.navigateByUrl(this.location.path(true), { replaceUrl: true });
  5043. }
  5044. }
  5045. /**
  5046. * Sets up the location change listener.
  5047. * @return {?}
  5048. */
  5049. setUpLocationChangeListener() {
  5050. // Don't need to use Zone.wrap any more, because zone.js
  5051. // already patch onPopState, so location change callback will
  5052. // run into ngZone
  5053. if (!this.locationSubscription) {
  5054. this.locationSubscription = /** @type {?} */ (this.location.subscribe((change) => {
  5055. /** @type {?} */
  5056. let rawUrlTree = this.parseUrl(change['url']);
  5057. /** @type {?} */
  5058. const source = change['type'] === 'popstate' ? 'popstate' : 'hashchange';
  5059. /** @type {?} */
  5060. const state = change.state && change.state.navigationId ?
  5061. { navigationId: change.state.navigationId } :
  5062. null;
  5063. setTimeout(() => { this.scheduleNavigation(rawUrlTree, source, state, { replaceUrl: true }); }, 0);
  5064. }));
  5065. }
  5066. }
  5067. /**
  5068. * The current url
  5069. * @return {?}
  5070. */
  5071. get url() { return this.serializeUrl(this.currentUrlTree); }
  5072. /**
  5073. * \@internal
  5074. * @param {?} event
  5075. * @return {?}
  5076. */
  5077. triggerEvent(event) { (/** @type {?} */ (this.events)).next(event); }
  5078. /**
  5079. * Resets the configuration used for navigation and generating links.
  5080. *
  5081. * \@usageNotes
  5082. *
  5083. * ### Example
  5084. *
  5085. * ```
  5086. * router.resetConfig([
  5087. * { path: 'team/:id', component: TeamCmp, children: [
  5088. * { path: 'simple', component: SimpleCmp },
  5089. * { path: 'user/:name', component: UserCmp }
  5090. * ]}
  5091. * ]);
  5092. * ```
  5093. * @param {?} config
  5094. * @return {?}
  5095. */
  5096. resetConfig(config) {
  5097. validateConfig(config);
  5098. this.config = config.map(standardizeConfig);
  5099. this.navigated = false;
  5100. this.lastSuccessfulId = -1;
  5101. }
  5102. /**
  5103. * \@docsNotRequired
  5104. * @return {?}
  5105. */
  5106. ngOnDestroy() { this.dispose(); }
  5107. /**
  5108. * Disposes of the router
  5109. * @return {?}
  5110. */
  5111. dispose() {
  5112. if (this.locationSubscription) {
  5113. this.locationSubscription.unsubscribe();
  5114. this.locationSubscription = /** @type {?} */ ((null));
  5115. }
  5116. }
  5117. /**
  5118. * Applies an array of commands to the current url tree and creates a new url tree.
  5119. *
  5120. * When given an activate route, applies the given commands starting from the route.
  5121. * When not given a route, applies the given command starting from the root.
  5122. *
  5123. * \@usageNotes
  5124. *
  5125. * ### Example
  5126. *
  5127. * ```
  5128. * // create /team/33/user/11
  5129. * router.createUrlTree(['/team', 33, 'user', 11]);
  5130. *
  5131. * // create /team/33;expand=true/user/11
  5132. * router.createUrlTree(['/team', 33, {expand: true}, 'user', 11]);
  5133. *
  5134. * // you can collapse static segments like this (this works only with the first passed-in value):
  5135. * router.createUrlTree(['/team/33/user', userId]);
  5136. *
  5137. * // If the first segment can contain slashes, and you do not want the router to split it, you
  5138. * // can do the following:
  5139. *
  5140. * router.createUrlTree([{segmentPath: '/one/two'}]);
  5141. *
  5142. * // create /team/33/(user/11//right:chat)
  5143. * router.createUrlTree(['/team', 33, {outlets: {primary: 'user/11', right: 'chat'}}]);
  5144. *
  5145. * // remove the right secondary node
  5146. * router.createUrlTree(['/team', 33, {outlets: {primary: 'user/11', right: null}}]);
  5147. *
  5148. * // assuming the current url is `/team/33/user/11` and the route points to `user/11`
  5149. *
  5150. * // navigate to /team/33/user/11/details
  5151. * router.createUrlTree(['details'], {relativeTo: route});
  5152. *
  5153. * // navigate to /team/33/user/22
  5154. * router.createUrlTree(['../22'], {relativeTo: route});
  5155. *
  5156. * // navigate to /team/44/user/22
  5157. * router.createUrlTree(['../../team/44/user/22'], {relativeTo: route});
  5158. * ```
  5159. * @param {?} commands
  5160. * @param {?=} navigationExtras
  5161. * @return {?}
  5162. */
  5163. createUrlTree(commands, navigationExtras = {}) {
  5164. const { relativeTo, queryParams, fragment, preserveQueryParams, queryParamsHandling, preserveFragment } = navigationExtras;
  5165. if (isDevMode() && preserveQueryParams && /** @type {?} */ (console) && /** @type {?} */ (console.warn)) {
  5166. console.warn('preserveQueryParams is deprecated, use queryParamsHandling instead.');
  5167. }
  5168. /** @type {?} */
  5169. const a = relativeTo || this.routerState.root;
  5170. /** @type {?} */
  5171. const f = preserveFragment ? this.currentUrlTree.fragment : fragment;
  5172. /** @type {?} */
  5173. let q = null;
  5174. if (queryParamsHandling) {
  5175. switch (queryParamsHandling) {
  5176. case 'merge':
  5177. q = Object.assign({}, this.currentUrlTree.queryParams, queryParams);
  5178. break;
  5179. case 'preserve':
  5180. q = this.currentUrlTree.queryParams;
  5181. break;
  5182. default:
  5183. q = queryParams || null;
  5184. }
  5185. }
  5186. else {
  5187. q = preserveQueryParams ? this.currentUrlTree.queryParams : queryParams || null;
  5188. }
  5189. if (q !== null) {
  5190. q = this.removeEmptyProps(q);
  5191. }
  5192. return createUrlTree(a, this.currentUrlTree, commands, /** @type {?} */ ((q)), /** @type {?} */ ((f)));
  5193. }
  5194. /**
  5195. * Navigate based on the provided url. This navigation is always absolute.
  5196. *
  5197. * Returns a promise that:
  5198. * - resolves to 'true' when navigation succeeds,
  5199. * - resolves to 'false' when navigation fails,
  5200. * - is rejected when an error happens.
  5201. *
  5202. * \@usageNotes
  5203. *
  5204. * ### Example
  5205. *
  5206. * ```
  5207. * router.navigateByUrl("/team/33/user/11");
  5208. *
  5209. * // Navigate without updating the URL
  5210. * router.navigateByUrl("/team/33/user/11", { skipLocationChange: true });
  5211. * ```
  5212. *
  5213. * Since `navigateByUrl()` takes an absolute URL as the first parameter,
  5214. * it will not apply any delta to the current URL and ignores any properties
  5215. * in the second parameter (the `NavigationExtras`) that would change the
  5216. * provided URL.
  5217. * @param {?} url
  5218. * @param {?=} extras
  5219. * @return {?}
  5220. */
  5221. navigateByUrl(url, extras = { skipLocationChange: false }) {
  5222. if (isDevMode() && this.isNgZoneEnabled && !NgZone.isInAngularZone()) {
  5223. this.console.warn(`Navigation triggered outside Angular zone, did you forget to call 'ngZone.run()'?`);
  5224. }
  5225. /** @type {?} */
  5226. const urlTree = url instanceof UrlTree ? url : this.parseUrl(url);
  5227. /** @type {?} */
  5228. const mergedTree = this.urlHandlingStrategy.merge(urlTree, this.rawUrlTree);
  5229. return this.scheduleNavigation(mergedTree, 'imperative', null, extras);
  5230. }
  5231. /**
  5232. * Navigate based on the provided array of commands and a starting point.
  5233. * If no starting route is provided, the navigation is absolute.
  5234. *
  5235. * Returns a promise that:
  5236. * - resolves to 'true' when navigation succeeds,
  5237. * - resolves to 'false' when navigation fails,
  5238. * - is rejected when an error happens.
  5239. *
  5240. * \@usageNotes
  5241. *
  5242. * ### Example
  5243. *
  5244. * ```
  5245. * router.navigate(['team', 33, 'user', 11], {relativeTo: route});
  5246. *
  5247. * // Navigate without updating the URL
  5248. * router.navigate(['team', 33, 'user', 11], {relativeTo: route, skipLocationChange: true});
  5249. * ```
  5250. *
  5251. * The first parameter of `navigate()` is a delta to be applied to the current URL
  5252. * or the one provided in the `relativeTo` property of the second parameter (the
  5253. * `NavigationExtras`).
  5254. * @param {?} commands
  5255. * @param {?=} extras
  5256. * @return {?}
  5257. */
  5258. navigate(commands, extras = { skipLocationChange: false }) {
  5259. validateCommands(commands);
  5260. return this.navigateByUrl(this.createUrlTree(commands, extras), extras);
  5261. }
  5262. /**
  5263. * Serializes a `UrlTree` into a string
  5264. * @param {?} url
  5265. * @return {?}
  5266. */
  5267. serializeUrl(url) { return this.urlSerializer.serialize(url); }
  5268. /**
  5269. * Parses a string into a `UrlTree`
  5270. * @param {?} url
  5271. * @return {?}
  5272. */
  5273. parseUrl(url) {
  5274. /** @type {?} */
  5275. let urlTree;
  5276. try {
  5277. urlTree = this.urlSerializer.parse(url);
  5278. }
  5279. catch (e) {
  5280. urlTree = this.malformedUriErrorHandler(e, this.urlSerializer, url);
  5281. }
  5282. return urlTree;
  5283. }
  5284. /**
  5285. * Returns whether the url is activated
  5286. * @param {?} url
  5287. * @param {?} exact
  5288. * @return {?}
  5289. */
  5290. isActive(url, exact) {
  5291. if (url instanceof UrlTree) {
  5292. return containsTree(this.currentUrlTree, url, exact);
  5293. }
  5294. /** @type {?} */
  5295. const urlTree = this.parseUrl(url);
  5296. return containsTree(this.currentUrlTree, urlTree, exact);
  5297. }
  5298. /**
  5299. * @param {?} params
  5300. * @return {?}
  5301. */
  5302. removeEmptyProps(params) {
  5303. return Object.keys(params).reduce((result, key) => {
  5304. /** @type {?} */
  5305. const value = params[key];
  5306. if (value !== null && value !== undefined) {
  5307. result[key] = value;
  5308. }
  5309. return result;
  5310. }, {});
  5311. }
  5312. /**
  5313. * @return {?}
  5314. */
  5315. processNavigations() {
  5316. this.navigations.subscribe(t => {
  5317. this.navigated = true;
  5318. this.lastSuccessfulId = t.id;
  5319. (/** @type {?} */ (this.events))
  5320. .next(new NavigationEnd(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(this.currentUrlTree)));
  5321. t.resolve(true);
  5322. }, e => { this.console.warn(`Unhandled Navigation Error: `); });
  5323. }
  5324. /**
  5325. * @param {?} rawUrl
  5326. * @param {?} source
  5327. * @param {?} state
  5328. * @param {?} extras
  5329. * @return {?}
  5330. */
  5331. scheduleNavigation(rawUrl, source, state, extras) {
  5332. /** @type {?} */
  5333. const lastNavigation = this.getTransition();
  5334. // If the user triggers a navigation imperatively (e.g., by using navigateByUrl),
  5335. // and that navigation results in 'replaceState' that leads to the same URL,
  5336. // we should skip those.
  5337. if (lastNavigation && source !== 'imperative' && lastNavigation.source === 'imperative' &&
  5338. lastNavigation.rawUrl.toString() === rawUrl.toString()) {
  5339. return Promise.resolve(true); // return value is not used
  5340. }
  5341. // Because of a bug in IE and Edge, the location class fires two events (popstate and
  5342. // hashchange) every single time. The second one should be ignored. Otherwise, the URL will
  5343. // flicker. Handles the case when a popstate was emitted first.
  5344. if (lastNavigation && source == 'hashchange' && lastNavigation.source === 'popstate' &&
  5345. lastNavigation.rawUrl.toString() === rawUrl.toString()) {
  5346. return Promise.resolve(true); // return value is not used
  5347. }
  5348. // Because of a bug in IE and Edge, the location class fires two events (popstate and
  5349. // hashchange) every single time. The second one should be ignored. Otherwise, the URL will
  5350. // flicker. Handles the case when a hashchange was emitted first.
  5351. if (lastNavigation && source == 'popstate' && lastNavigation.source === 'hashchange' &&
  5352. lastNavigation.rawUrl.toString() === rawUrl.toString()) {
  5353. return Promise.resolve(true); // return value is not used
  5354. }
  5355. /** @type {?} */
  5356. let resolve = null;
  5357. /** @type {?} */
  5358. let reject = null;
  5359. /** @type {?} */
  5360. const promise = new Promise((res, rej) => {
  5361. resolve = res;
  5362. reject = rej;
  5363. });
  5364. /** @type {?} */
  5365. const id = ++this.navigationId;
  5366. this.setTransition({
  5367. id,
  5368. source,
  5369. state,
  5370. currentUrlTree: this.currentUrlTree,
  5371. currentRawUrl: this.rawUrlTree, rawUrl, extras, resolve, reject, promise,
  5372. currentSnapshot: this.routerState.snapshot,
  5373. currentRouterState: this.routerState
  5374. });
  5375. // Make sure that the error is propagated even though `processNavigations` catch
  5376. // handler does not rethrow
  5377. return promise.catch((e) => { return Promise.reject(e); });
  5378. }
  5379. /**
  5380. * @param {?} url
  5381. * @param {?} replaceUrl
  5382. * @param {?} id
  5383. * @return {?}
  5384. */
  5385. setBrowserUrl(url, replaceUrl, id) {
  5386. /** @type {?} */
  5387. const path = this.urlSerializer.serialize(url);
  5388. if (this.location.isCurrentPathEqualTo(path) || replaceUrl) {
  5389. this.location.replaceState(path, '', { navigationId: id });
  5390. }
  5391. else {
  5392. this.location.go(path, '', { navigationId: id });
  5393. }
  5394. }
  5395. /**
  5396. * @param {?} storedState
  5397. * @param {?} storedUrl
  5398. * @param {?} rawUrl
  5399. * @return {?}
  5400. */
  5401. resetStateAndUrl(storedState, storedUrl, rawUrl) {
  5402. (/** @type {?} */ (this)).routerState = storedState;
  5403. this.currentUrlTree = storedUrl;
  5404. this.rawUrlTree = this.urlHandlingStrategy.merge(this.currentUrlTree, rawUrl);
  5405. this.resetUrlToCurrentUrlTree();
  5406. }
  5407. /**
  5408. * @return {?}
  5409. */
  5410. resetUrlToCurrentUrlTree() {
  5411. this.location.replaceState(this.urlSerializer.serialize(this.rawUrlTree), '', { navigationId: this.lastSuccessfulId });
  5412. }
  5413. }
  5414. /**
  5415. * @param {?} commands
  5416. * @return {?}
  5417. */
  5418. function validateCommands(commands) {
  5419. for (let i = 0; i < commands.length; i++) {
  5420. /** @type {?} */
  5421. const cmd = commands[i];
  5422. if (cmd == null) {
  5423. throw new Error(`The requested path contains ${cmd} segment at index ${i}`);
  5424. }
  5425. }
  5426. }
  5427. /**
  5428. * @fileoverview added by tsickle
  5429. * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
  5430. */
  5431. /**
  5432. * \@description
  5433. *
  5434. * Lets you link to specific routes in your app.
  5435. *
  5436. * Consider the following route configuration:
  5437. * `[{ path: 'user/:name', component: UserCmp }]`.
  5438. * When linking to this `user/:name` route, you use the `RouterLink` directive.
  5439. *
  5440. * If the link is static, you can use the directive as follows:
  5441. * `<a routerLink="/user/bob">link to user component</a>`
  5442. *
  5443. * If you use dynamic values to generate the link, you can pass an array of path
  5444. * segments, followed by the params for each segment.
  5445. *
  5446. * For instance `['/team', teamId, 'user', userName, {details: true}]`
  5447. * means that we want to generate a link to `/team/11/user/bob;details=true`.
  5448. *
  5449. * Multiple static segments can be merged into one
  5450. * (e.g., `['/team/11/user', userName, {details: true}]`).
  5451. *
  5452. * The first segment name can be prepended with `/`, `./`, or `../`:
  5453. * * If the first segment begins with `/`, the router will look up the route from the root of the
  5454. * app.
  5455. * * If the first segment begins with `./`, or doesn't begin with a slash, the router will
  5456. * instead look in the children of the current activated route.
  5457. * * And if the first segment begins with `../`, the router will go up one level.
  5458. *
  5459. * You can set query params and fragment as follows:
  5460. *
  5461. * ```
  5462. * <a [routerLink]="['/user/bob']" [queryParams]="{debug: true}" fragment="education">
  5463. * link to user component
  5464. * </a>
  5465. * ```
  5466. * RouterLink will use these to generate this link: `/user/bob#education?debug=true`.
  5467. *
  5468. * (Deprecated in v4.0.0 use `queryParamsHandling` instead) You can also tell the
  5469. * directive to preserve the current query params and fragment:
  5470. *
  5471. * ```
  5472. * <a [routerLink]="['/user/bob']" preserveQueryParams preserveFragment>
  5473. * link to user component
  5474. * </a>
  5475. * ```
  5476. *
  5477. * You can tell the directive to how to handle queryParams, available options are:
  5478. * - `'merge'`: merge the queryParams into the current queryParams
  5479. * - `'preserve'`: preserve the current queryParams
  5480. * - default/`''`: use the queryParams only
  5481. *
  5482. * Same options for {\@link NavigationExtras#queryParamsHandling
  5483. * NavigationExtras#queryParamsHandling}.
  5484. *
  5485. * ```
  5486. * <a [routerLink]="['/user/bob']" [queryParams]="{debug: true}" queryParamsHandling="merge">
  5487. * link to user component
  5488. * </a>
  5489. * ```
  5490. *
  5491. * The router link directive always treats the provided input as a delta to the current url.
  5492. *
  5493. * For instance, if the current url is `/user/(box//aux:team)`.
  5494. *
  5495. * Then the following link `<a [routerLink]="['/user/jim']">Jim</a>` will generate the link
  5496. * `/user/(jim//aux:team)`.
  5497. *
  5498. * See {\@link Router#createUrlTree createUrlTree} for more information.
  5499. *
  5500. * \@ngModule RouterModule
  5501. *
  5502. * \@publicApi
  5503. */
  5504. class RouterLink {
  5505. /**
  5506. * @param {?} router
  5507. * @param {?} route
  5508. * @param {?} tabIndex
  5509. * @param {?} renderer
  5510. * @param {?} el
  5511. */
  5512. constructor(router, route, tabIndex, renderer, el) {
  5513. this.router = router;
  5514. this.route = route;
  5515. this.commands = [];
  5516. if (tabIndex == null) {
  5517. renderer.setAttribute(el.nativeElement, 'tabindex', '0');
  5518. }
  5519. }
  5520. /**
  5521. * @param {?} commands
  5522. * @return {?}
  5523. */
  5524. set routerLink(commands) {
  5525. if (commands != null) {
  5526. this.commands = Array.isArray(commands) ? commands : [commands];
  5527. }
  5528. else {
  5529. this.commands = [];
  5530. }
  5531. }
  5532. /**
  5533. * @deprecated 4.0.0 use `queryParamsHandling` instead.
  5534. * @param {?} value
  5535. * @return {?}
  5536. */
  5537. set preserveQueryParams(value) {
  5538. if (isDevMode() && /** @type {?} */ (console) && /** @type {?} */ (console.warn)) {
  5539. console.warn('preserveQueryParams is deprecated!, use queryParamsHandling instead.');
  5540. }
  5541. this.preserve = value;
  5542. }
  5543. /**
  5544. * @return {?}
  5545. */
  5546. onClick() {
  5547. /** @type {?} */
  5548. const extras = {
  5549. skipLocationChange: attrBoolValue(this.skipLocationChange),
  5550. replaceUrl: attrBoolValue(this.replaceUrl),
  5551. };
  5552. this.router.navigateByUrl(this.urlTree, extras);
  5553. return true;
  5554. }
  5555. /**
  5556. * @return {?}
  5557. */
  5558. get urlTree() {
  5559. return this.router.createUrlTree(this.commands, {
  5560. relativeTo: this.route,
  5561. queryParams: this.queryParams,
  5562. fragment: this.fragment,
  5563. preserveQueryParams: attrBoolValue(this.preserve),
  5564. queryParamsHandling: this.queryParamsHandling,
  5565. preserveFragment: attrBoolValue(this.preserveFragment),
  5566. });
  5567. }
  5568. }
  5569. RouterLink.decorators = [
  5570. { type: Directive, args: [{ selector: ':not(a)[routerLink]' },] }
  5571. ];
  5572. /** @nocollapse */
  5573. RouterLink.ctorParameters = () => [
  5574. { type: Router },
  5575. { type: ActivatedRoute },
  5576. { type: String, decorators: [{ type: Attribute, args: ['tabindex',] }] },
  5577. { type: Renderer2 },
  5578. { type: ElementRef }
  5579. ];
  5580. RouterLink.propDecorators = {
  5581. queryParams: [{ type: Input }],
  5582. fragment: [{ type: Input }],
  5583. queryParamsHandling: [{ type: Input }],
  5584. preserveFragment: [{ type: Input }],
  5585. skipLocationChange: [{ type: Input }],
  5586. replaceUrl: [{ type: Input }],
  5587. routerLink: [{ type: Input }],
  5588. preserveQueryParams: [{ type: Input }],
  5589. onClick: [{ type: HostListener, args: ['click',] }]
  5590. };
  5591. /**
  5592. * \@description
  5593. *
  5594. * Lets you link to specific routes in your app.
  5595. *
  5596. * See `RouterLink` for more information.
  5597. *
  5598. * \@ngModule RouterModule
  5599. *
  5600. * \@publicApi
  5601. */
  5602. class RouterLinkWithHref {
  5603. /**
  5604. * @param {?} router
  5605. * @param {?} route
  5606. * @param {?} locationStrategy
  5607. */
  5608. constructor(router, route, locationStrategy) {
  5609. this.router = router;
  5610. this.route = route;
  5611. this.locationStrategy = locationStrategy;
  5612. this.commands = [];
  5613. this.subscription = router.events.subscribe((s) => {
  5614. if (s instanceof NavigationEnd) {
  5615. this.updateTargetUrlAndHref();
  5616. }
  5617. });
  5618. }
  5619. /**
  5620. * @param {?} commands
  5621. * @return {?}
  5622. */
  5623. set routerLink(commands) {
  5624. if (commands != null) {
  5625. this.commands = Array.isArray(commands) ? commands : [commands];
  5626. }
  5627. else {
  5628. this.commands = [];
  5629. }
  5630. }
  5631. /**
  5632. * @param {?} value
  5633. * @return {?}
  5634. */
  5635. set preserveQueryParams(value) {
  5636. if (isDevMode() && /** @type {?} */ (console) && /** @type {?} */ (console.warn)) {
  5637. console.warn('preserveQueryParams is deprecated, use queryParamsHandling instead.');
  5638. }
  5639. this.preserve = value;
  5640. }
  5641. /**
  5642. * @param {?} changes
  5643. * @return {?}
  5644. */
  5645. ngOnChanges(changes) { this.updateTargetUrlAndHref(); }
  5646. /**
  5647. * @return {?}
  5648. */
  5649. ngOnDestroy() { this.subscription.unsubscribe(); }
  5650. /**
  5651. * @param {?} button
  5652. * @param {?} ctrlKey
  5653. * @param {?} metaKey
  5654. * @param {?} shiftKey
  5655. * @return {?}
  5656. */
  5657. onClick(button, ctrlKey, metaKey, shiftKey) {
  5658. if (button !== 0 || ctrlKey || metaKey || shiftKey) {
  5659. return true;
  5660. }
  5661. if (typeof this.target === 'string' && this.target != '_self') {
  5662. return true;
  5663. }
  5664. /** @type {?} */
  5665. const extras = {
  5666. skipLocationChange: attrBoolValue(this.skipLocationChange),
  5667. replaceUrl: attrBoolValue(this.replaceUrl),
  5668. };
  5669. this.router.navigateByUrl(this.urlTree, extras);
  5670. return false;
  5671. }
  5672. /**
  5673. * @return {?}
  5674. */
  5675. updateTargetUrlAndHref() {
  5676. this.href = this.locationStrategy.prepareExternalUrl(this.router.serializeUrl(this.urlTree));
  5677. }
  5678. /**
  5679. * @return {?}
  5680. */
  5681. get urlTree() {
  5682. return this.router.createUrlTree(this.commands, {
  5683. relativeTo: this.route,
  5684. queryParams: this.queryParams,
  5685. fragment: this.fragment,
  5686. preserveQueryParams: attrBoolValue(this.preserve),
  5687. queryParamsHandling: this.queryParamsHandling,
  5688. preserveFragment: attrBoolValue(this.preserveFragment),
  5689. });
  5690. }
  5691. }
  5692. RouterLinkWithHref.decorators = [
  5693. { type: Directive, args: [{ selector: 'a[routerLink]' },] }
  5694. ];
  5695. /** @nocollapse */
  5696. RouterLinkWithHref.ctorParameters = () => [
  5697. { type: Router },
  5698. { type: ActivatedRoute },
  5699. { type: LocationStrategy }
  5700. ];
  5701. RouterLinkWithHref.propDecorators = {
  5702. target: [{ type: HostBinding, args: ['attr.target',] }, { type: Input }],
  5703. queryParams: [{ type: Input }],
  5704. fragment: [{ type: Input }],
  5705. queryParamsHandling: [{ type: Input }],
  5706. preserveFragment: [{ type: Input }],
  5707. skipLocationChange: [{ type: Input }],
  5708. replaceUrl: [{ type: Input }],
  5709. href: [{ type: HostBinding }],
  5710. routerLink: [{ type: Input }],
  5711. preserveQueryParams: [{ type: Input }],
  5712. onClick: [{ type: HostListener, args: ['click', ['$event.button', '$event.ctrlKey', '$event.metaKey', '$event.shiftKey'],] }]
  5713. };
  5714. /**
  5715. * @param {?} s
  5716. * @return {?}
  5717. */
  5718. function attrBoolValue(s) {
  5719. return s === '' || !!s;
  5720. }
  5721. /**
  5722. * @fileoverview added by tsickle
  5723. * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
  5724. */
  5725. /**
  5726. *
  5727. * \@description
  5728. *
  5729. * Lets you add a CSS class to an element when the link's route becomes active.
  5730. *
  5731. * This directive lets you add a CSS class to an element when the link's route
  5732. * becomes active.
  5733. *
  5734. * Consider the following example:
  5735. *
  5736. * ```
  5737. * <a routerLink="/user/bob" routerLinkActive="active-link">Bob</a>
  5738. * ```
  5739. *
  5740. * When the url is either '/user' or '/user/bob', the active-link class will
  5741. * be added to the `a` tag. If the url changes, the class will be removed.
  5742. *
  5743. * You can set more than one class, as follows:
  5744. *
  5745. * ```
  5746. * <a routerLink="/user/bob" routerLinkActive="class1 class2">Bob</a>
  5747. * <a routerLink="/user/bob" [routerLinkActive]="['class1', 'class2']">Bob</a>
  5748. * ```
  5749. *
  5750. * You can configure RouterLinkActive by passing `exact: true`. This will add the classes
  5751. * only when the url matches the link exactly.
  5752. *
  5753. * ```
  5754. * <a routerLink="/user/bob" routerLinkActive="active-link" [routerLinkActiveOptions]="{exact:
  5755. * true}">Bob</a>
  5756. * ```
  5757. *
  5758. * You can assign the RouterLinkActive instance to a template variable and directly check
  5759. * the `isActive` status.
  5760. * ```
  5761. * <a routerLink="/user/bob" routerLinkActive #rla="routerLinkActive">
  5762. * Bob {{ rla.isActive ? '(already open)' : ''}}
  5763. * </a>
  5764. * ```
  5765. *
  5766. * Finally, you can apply the RouterLinkActive directive to an ancestor of a RouterLink.
  5767. *
  5768. * ```
  5769. * <div routerLinkActive="active-link" [routerLinkActiveOptions]="{exact: true}">
  5770. * <a routerLink="/user/jim">Jim</a>
  5771. * <a routerLink="/user/bob">Bob</a>
  5772. * </div>
  5773. * ```
  5774. *
  5775. * This will set the active-link class on the div tag if the url is either '/user/jim' or
  5776. * '/user/bob'.
  5777. *
  5778. * \@ngModule RouterModule
  5779. *
  5780. * \@publicApi
  5781. */
  5782. class RouterLinkActive {
  5783. /**
  5784. * @param {?} router
  5785. * @param {?} element
  5786. * @param {?} renderer
  5787. * @param {?} cdr
  5788. */
  5789. constructor(router, element, renderer, cdr) {
  5790. this.router = router;
  5791. this.element = element;
  5792. this.renderer = renderer;
  5793. this.cdr = cdr;
  5794. this.classes = [];
  5795. this.isActive = false;
  5796. this.routerLinkActiveOptions = { exact: false };
  5797. this.subscription = router.events.subscribe((s) => {
  5798. if (s instanceof NavigationEnd) {
  5799. this.update();
  5800. }
  5801. });
  5802. }
  5803. /**
  5804. * @return {?}
  5805. */
  5806. ngAfterContentInit() {
  5807. this.links.changes.subscribe(_ => this.update());
  5808. this.linksWithHrefs.changes.subscribe(_ => this.update());
  5809. this.update();
  5810. }
  5811. /**
  5812. * @param {?} data
  5813. * @return {?}
  5814. */
  5815. set routerLinkActive(data) {
  5816. /** @type {?} */
  5817. const classes = Array.isArray(data) ? data : data.split(' ');
  5818. this.classes = classes.filter(c => !!c);
  5819. }
  5820. /**
  5821. * @param {?} changes
  5822. * @return {?}
  5823. */
  5824. ngOnChanges(changes) { this.update(); }
  5825. /**
  5826. * @return {?}
  5827. */
  5828. ngOnDestroy() { this.subscription.unsubscribe(); }
  5829. /**
  5830. * @return {?}
  5831. */
  5832. update() {
  5833. if (!this.links || !this.linksWithHrefs || !this.router.navigated)
  5834. return;
  5835. Promise.resolve().then(() => {
  5836. /** @type {?} */
  5837. const hasActiveLinks = this.hasActiveLinks();
  5838. if (this.isActive !== hasActiveLinks) {
  5839. (/** @type {?} */ (this)).isActive = hasActiveLinks;
  5840. this.classes.forEach((c) => {
  5841. if (hasActiveLinks) {
  5842. this.renderer.addClass(this.element.nativeElement, c);
  5843. }
  5844. else {
  5845. this.renderer.removeClass(this.element.nativeElement, c);
  5846. }
  5847. });
  5848. }
  5849. });
  5850. }
  5851. /**
  5852. * @param {?} router
  5853. * @return {?}
  5854. */
  5855. isLinkActive(router) {
  5856. return (link) => router.isActive(link.urlTree, this.routerLinkActiveOptions.exact);
  5857. }
  5858. /**
  5859. * @return {?}
  5860. */
  5861. hasActiveLinks() {
  5862. return this.links.some(this.isLinkActive(this.router)) ||
  5863. this.linksWithHrefs.some(this.isLinkActive(this.router));
  5864. }
  5865. }
  5866. RouterLinkActive.decorators = [
  5867. { type: Directive, args: [{
  5868. selector: '[routerLinkActive]',
  5869. exportAs: 'routerLinkActive',
  5870. },] }
  5871. ];
  5872. /** @nocollapse */
  5873. RouterLinkActive.ctorParameters = () => [
  5874. { type: Router },
  5875. { type: ElementRef },
  5876. { type: Renderer2 },
  5877. { type: ChangeDetectorRef }
  5878. ];
  5879. RouterLinkActive.propDecorators = {
  5880. links: [{ type: ContentChildren, args: [RouterLink, { descendants: true },] }],
  5881. linksWithHrefs: [{ type: ContentChildren, args: [RouterLinkWithHref, { descendants: true },] }],
  5882. routerLinkActiveOptions: [{ type: Input }],
  5883. routerLinkActive: [{ type: Input }]
  5884. };
  5885. /**
  5886. * @fileoverview added by tsickle
  5887. * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
  5888. */
  5889. /**
  5890. * @license
  5891. * Copyright Google Inc. All Rights Reserved.
  5892. *
  5893. * Use of this source code is governed by an MIT-style license that can be
  5894. * found in the LICENSE file at https://angular.io/license
  5895. */
  5896. /**
  5897. * Store contextual information about a `RouterOutlet`
  5898. *
  5899. * \@publicApi
  5900. */
  5901. class OutletContext {
  5902. constructor() {
  5903. this.outlet = null;
  5904. this.route = null;
  5905. this.resolver = null;
  5906. this.children = new ChildrenOutletContexts();
  5907. this.attachRef = null;
  5908. }
  5909. }
  5910. /**
  5911. * Store contextual information about the children (= nested) `RouterOutlet`
  5912. *
  5913. * \@publicApi
  5914. */
  5915. class ChildrenOutletContexts {
  5916. constructor() {
  5917. this.contexts = new Map();
  5918. }
  5919. /**
  5920. * Called when a `RouterOutlet` directive is instantiated
  5921. * @param {?} childName
  5922. * @param {?} outlet
  5923. * @return {?}
  5924. */
  5925. onChildOutletCreated(childName, outlet) {
  5926. /** @type {?} */
  5927. const context = this.getOrCreateContext(childName);
  5928. context.outlet = outlet;
  5929. this.contexts.set(childName, context);
  5930. }
  5931. /**
  5932. * Called when a `RouterOutlet` directive is destroyed.
  5933. * We need to keep the context as the outlet could be destroyed inside a NgIf and might be
  5934. * re-created later.
  5935. * @param {?} childName
  5936. * @return {?}
  5937. */
  5938. onChildOutletDestroyed(childName) {
  5939. /** @type {?} */
  5940. const context = this.getContext(childName);
  5941. if (context) {
  5942. context.outlet = null;
  5943. }
  5944. }
  5945. /**
  5946. * Called when the corresponding route is deactivated during navigation.
  5947. * Because the component get destroyed, all children outlet are destroyed.
  5948. * @return {?}
  5949. */
  5950. onOutletDeactivated() {
  5951. /** @type {?} */
  5952. const contexts = this.contexts;
  5953. this.contexts = new Map();
  5954. return contexts;
  5955. }
  5956. /**
  5957. * @param {?} contexts
  5958. * @return {?}
  5959. */
  5960. onOutletReAttached(contexts) { this.contexts = contexts; }
  5961. /**
  5962. * @param {?} childName
  5963. * @return {?}
  5964. */
  5965. getOrCreateContext(childName) {
  5966. /** @type {?} */
  5967. let context = this.getContext(childName);
  5968. if (!context) {
  5969. context = new OutletContext();
  5970. this.contexts.set(childName, context);
  5971. }
  5972. return context;
  5973. }
  5974. /**
  5975. * @param {?} childName
  5976. * @return {?}
  5977. */
  5978. getContext(childName) { return this.contexts.get(childName) || null; }
  5979. }
  5980. /**
  5981. * @fileoverview added by tsickle
  5982. * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
  5983. */
  5984. /**
  5985. * \@description
  5986. *
  5987. * Acts as a placeholder that Angular dynamically fills based on the current router state.
  5988. *
  5989. * ```
  5990. * <router-outlet></router-outlet>
  5991. * <router-outlet name='left'></router-outlet>
  5992. * <router-outlet name='right'></router-outlet>
  5993. * ```
  5994. *
  5995. * A router outlet will emit an activate event any time a new component is being instantiated,
  5996. * and a deactivate event when it is being destroyed.
  5997. *
  5998. * ```
  5999. * <router-outlet
  6000. * (activate)='onActivate($event)'
  6001. * (deactivate)='onDeactivate($event)'></router-outlet>
  6002. * ```
  6003. * \@ngModule RouterModule
  6004. *
  6005. * \@publicApi
  6006. */
  6007. class RouterOutlet {
  6008. /**
  6009. * @param {?} parentContexts
  6010. * @param {?} location
  6011. * @param {?} resolver
  6012. * @param {?} name
  6013. * @param {?} changeDetector
  6014. */
  6015. constructor(parentContexts, location, resolver, name, changeDetector) {
  6016. this.parentContexts = parentContexts;
  6017. this.location = location;
  6018. this.resolver = resolver;
  6019. this.changeDetector = changeDetector;
  6020. this.activated = null;
  6021. this._activatedRoute = null;
  6022. this.activateEvents = new EventEmitter();
  6023. this.deactivateEvents = new EventEmitter();
  6024. this.name = name || PRIMARY_OUTLET;
  6025. parentContexts.onChildOutletCreated(this.name, this);
  6026. }
  6027. /**
  6028. * @return {?}
  6029. */
  6030. ngOnDestroy() { this.parentContexts.onChildOutletDestroyed(this.name); }
  6031. /**
  6032. * @return {?}
  6033. */
  6034. ngOnInit() {
  6035. if (!this.activated) {
  6036. /** @type {?} */
  6037. const context = this.parentContexts.getContext(this.name);
  6038. if (context && context.route) {
  6039. if (context.attachRef) {
  6040. // `attachRef` is populated when there is an existing component to mount
  6041. this.attach(context.attachRef, context.route);
  6042. }
  6043. else {
  6044. // otherwise the component defined in the configuration is created
  6045. this.activateWith(context.route, context.resolver || null);
  6046. }
  6047. }
  6048. }
  6049. }
  6050. /**
  6051. * @return {?}
  6052. */
  6053. get isActivated() { return !!this.activated; }
  6054. /**
  6055. * @return {?}
  6056. */
  6057. get component() {
  6058. if (!this.activated)
  6059. throw new Error('Outlet is not activated');
  6060. return this.activated.instance;
  6061. }
  6062. /**
  6063. * @return {?}
  6064. */
  6065. get activatedRoute() {
  6066. if (!this.activated)
  6067. throw new Error('Outlet is not activated');
  6068. return /** @type {?} */ (this._activatedRoute);
  6069. }
  6070. /**
  6071. * @return {?}
  6072. */
  6073. get activatedRouteData() {
  6074. if (this._activatedRoute) {
  6075. return this._activatedRoute.snapshot.data;
  6076. }
  6077. return {};
  6078. }
  6079. /**
  6080. * Called when the `RouteReuseStrategy` instructs to detach the subtree
  6081. * @return {?}
  6082. */
  6083. detach() {
  6084. if (!this.activated)
  6085. throw new Error('Outlet is not activated');
  6086. this.location.detach();
  6087. /** @type {?} */
  6088. const cmp = this.activated;
  6089. this.activated = null;
  6090. this._activatedRoute = null;
  6091. return cmp;
  6092. }
  6093. /**
  6094. * Called when the `RouteReuseStrategy` instructs to re-attach a previously detached subtree
  6095. * @param {?} ref
  6096. * @param {?} activatedRoute
  6097. * @return {?}
  6098. */
  6099. attach(ref, activatedRoute) {
  6100. this.activated = ref;
  6101. this._activatedRoute = activatedRoute;
  6102. this.location.insert(ref.hostView);
  6103. }
  6104. /**
  6105. * @return {?}
  6106. */
  6107. deactivate() {
  6108. if (this.activated) {
  6109. /** @type {?} */
  6110. const c = this.component;
  6111. this.activated.destroy();
  6112. this.activated = null;
  6113. this._activatedRoute = null;
  6114. this.deactivateEvents.emit(c);
  6115. }
  6116. }
  6117. /**
  6118. * @param {?} activatedRoute
  6119. * @param {?} resolver
  6120. * @return {?}
  6121. */
  6122. activateWith(activatedRoute, resolver) {
  6123. if (this.isActivated) {
  6124. throw new Error('Cannot activate an already activated outlet');
  6125. }
  6126. this._activatedRoute = activatedRoute;
  6127. /** @type {?} */
  6128. const snapshot = activatedRoute._futureSnapshot;
  6129. /** @type {?} */
  6130. const component = /** @type {?} */ (/** @type {?} */ ((snapshot.routeConfig)).component);
  6131. resolver = resolver || this.resolver;
  6132. /** @type {?} */
  6133. const factory = resolver.resolveComponentFactory(component);
  6134. /** @type {?} */
  6135. const childContexts = this.parentContexts.getOrCreateContext(this.name).children;
  6136. /** @type {?} */
  6137. const injector = new OutletInjector(activatedRoute, childContexts, this.location.injector);
  6138. this.activated = this.location.createComponent(factory, this.location.length, injector);
  6139. // Calling `markForCheck` to make sure we will run the change detection when the
  6140. // `RouterOutlet` is inside a `ChangeDetectionStrategy.OnPush` component.
  6141. this.changeDetector.markForCheck();
  6142. this.activateEvents.emit(this.activated.instance);
  6143. }
  6144. }
  6145. RouterOutlet.decorators = [
  6146. { type: Directive, args: [{ selector: 'router-outlet', exportAs: 'outlet' },] }
  6147. ];
  6148. /** @nocollapse */
  6149. RouterOutlet.ctorParameters = () => [
  6150. { type: ChildrenOutletContexts },
  6151. { type: ViewContainerRef },
  6152. { type: ComponentFactoryResolver },
  6153. { type: String, decorators: [{ type: Attribute, args: ['name',] }] },
  6154. { type: ChangeDetectorRef }
  6155. ];
  6156. RouterOutlet.propDecorators = {
  6157. activateEvents: [{ type: Output, args: ['activate',] }],
  6158. deactivateEvents: [{ type: Output, args: ['deactivate',] }]
  6159. };
  6160. class OutletInjector {
  6161. /**
  6162. * @param {?} route
  6163. * @param {?} childContexts
  6164. * @param {?} parent
  6165. */
  6166. constructor(route, childContexts, parent) {
  6167. this.route = route;
  6168. this.childContexts = childContexts;
  6169. this.parent = parent;
  6170. }
  6171. /**
  6172. * @param {?} token
  6173. * @param {?=} notFoundValue
  6174. * @return {?}
  6175. */
  6176. get(token, notFoundValue) {
  6177. if (token === ActivatedRoute) {
  6178. return this.route;
  6179. }
  6180. if (token === ChildrenOutletContexts) {
  6181. return this.childContexts;
  6182. }
  6183. return this.parent.get(token, notFoundValue);
  6184. }
  6185. }
  6186. /**
  6187. * @fileoverview added by tsickle
  6188. * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
  6189. */
  6190. /**
  6191. * \@description
  6192. *
  6193. * Provides a preloading strategy.
  6194. *
  6195. * \@publicApi
  6196. * @abstract
  6197. */
  6198. class PreloadingStrategy {
  6199. }
  6200. /**
  6201. * \@description
  6202. *
  6203. * Provides a preloading strategy that preloads all modules as quickly as possible.
  6204. *
  6205. * ```
  6206. * RouteModule.forRoot(ROUTES, {preloadingStrategy: PreloadAllModules})
  6207. * ```
  6208. *
  6209. * \@publicApi
  6210. */
  6211. class PreloadAllModules {
  6212. /**
  6213. * @param {?} route
  6214. * @param {?} fn
  6215. * @return {?}
  6216. */
  6217. preload(route, fn) {
  6218. return fn().pipe(catchError(() => of(null)));
  6219. }
  6220. }
  6221. /**
  6222. * \@description
  6223. *
  6224. * Provides a preloading strategy that does not preload any modules.
  6225. *
  6226. * This strategy is enabled by default.
  6227. *
  6228. * \@publicApi
  6229. */
  6230. class NoPreloading {
  6231. /**
  6232. * @param {?} route
  6233. * @param {?} fn
  6234. * @return {?}
  6235. */
  6236. preload(route, fn) { return of(null); }
  6237. }
  6238. /**
  6239. * The preloader optimistically loads all router configurations to
  6240. * make navigations into lazily-loaded sections of the application faster.
  6241. *
  6242. * The preloader runs in the background. When the router bootstraps, the preloader
  6243. * starts listening to all navigation events. After every such event, the preloader
  6244. * will check if any configurations can be loaded lazily.
  6245. *
  6246. * If a route is protected by `canLoad` guards, the preloaded will not load it.
  6247. *
  6248. * \@publicApi
  6249. */
  6250. class RouterPreloader {
  6251. /**
  6252. * @param {?} router
  6253. * @param {?} moduleLoader
  6254. * @param {?} compiler
  6255. * @param {?} injector
  6256. * @param {?} preloadingStrategy
  6257. */
  6258. constructor(router, moduleLoader, compiler, injector, preloadingStrategy) {
  6259. this.router = router;
  6260. this.injector = injector;
  6261. this.preloadingStrategy = preloadingStrategy;
  6262. /** @type {?} */
  6263. const onStartLoad = (r) => router.triggerEvent(new RouteConfigLoadStart(r));
  6264. /** @type {?} */
  6265. const onEndLoad = (r) => router.triggerEvent(new RouteConfigLoadEnd(r));
  6266. this.loader = new RouterConfigLoader(moduleLoader, compiler, onStartLoad, onEndLoad);
  6267. }
  6268. /**
  6269. * @return {?}
  6270. */
  6271. setUpPreloading() {
  6272. this.subscription =
  6273. this.router.events
  6274. .pipe(filter((e) => e instanceof NavigationEnd), concatMap(() => this.preload()))
  6275. .subscribe(() => { });
  6276. }
  6277. /**
  6278. * @return {?}
  6279. */
  6280. preload() {
  6281. /** @type {?} */
  6282. const ngModule = this.injector.get(NgModuleRef);
  6283. return this.processRoutes(ngModule, this.router.config);
  6284. }
  6285. /**
  6286. * @return {?}
  6287. */
  6288. ngOnDestroy() { this.subscription.unsubscribe(); }
  6289. /**
  6290. * @param {?} ngModule
  6291. * @param {?} routes
  6292. * @return {?}
  6293. */
  6294. processRoutes(ngModule, routes) {
  6295. /** @type {?} */
  6296. const res = [];
  6297. for (const route of routes) {
  6298. // we already have the config loaded, just recurse
  6299. if (route.loadChildren && !route.canLoad && route._loadedConfig) {
  6300. /** @type {?} */
  6301. const childConfig = route._loadedConfig;
  6302. res.push(this.processRoutes(childConfig.module, childConfig.routes));
  6303. // no config loaded, fetch the config
  6304. }
  6305. else if (route.loadChildren && !route.canLoad) {
  6306. res.push(this.preloadConfig(ngModule, route));
  6307. // recurse into children
  6308. }
  6309. else if (route.children) {
  6310. res.push(this.processRoutes(ngModule, route.children));
  6311. }
  6312. }
  6313. return from(res).pipe(mergeAll(), map((_) => void 0));
  6314. }
  6315. /**
  6316. * @param {?} ngModule
  6317. * @param {?} route
  6318. * @return {?}
  6319. */
  6320. preloadConfig(ngModule, route) {
  6321. return this.preloadingStrategy.preload(route, () => {
  6322. /** @type {?} */
  6323. const loaded$ = this.loader.load(ngModule.injector, route);
  6324. return loaded$.pipe(mergeMap((config) => {
  6325. route._loadedConfig = config;
  6326. return this.processRoutes(config.module, config.routes);
  6327. }));
  6328. });
  6329. }
  6330. }
  6331. RouterPreloader.decorators = [
  6332. { type: Injectable }
  6333. ];
  6334. /** @nocollapse */
  6335. RouterPreloader.ctorParameters = () => [
  6336. { type: Router },
  6337. { type: NgModuleFactoryLoader },
  6338. { type: Compiler },
  6339. { type: Injector },
  6340. { type: PreloadingStrategy }
  6341. ];
  6342. /**
  6343. * @fileoverview added by tsickle
  6344. * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
  6345. */
  6346. class RouterScroller {
  6347. /**
  6348. * @param {?} router
  6349. * @param {?} viewportScroller
  6350. * @param {?=} options
  6351. */
  6352. constructor(router, viewportScroller, options = {}) {
  6353. this.router = router;
  6354. this.viewportScroller = viewportScroller;
  6355. this.options = options;
  6356. this.lastId = 0;
  6357. this.lastSource = 'imperative';
  6358. this.restoredId = 0;
  6359. this.store = {};
  6360. // Default both options to 'disabled'
  6361. options.scrollPositionRestoration = options.scrollPositionRestoration || 'disabled';
  6362. options.anchorScrolling = options.anchorScrolling || 'disabled';
  6363. }
  6364. /**
  6365. * @return {?}
  6366. */
  6367. init() {
  6368. // we want to disable the automatic scrolling because having two places
  6369. // responsible for scrolling results race conditions, especially given
  6370. // that browser don't implement this behavior consistently
  6371. if (this.options.scrollPositionRestoration !== 'disabled') {
  6372. this.viewportScroller.setHistoryScrollRestoration('manual');
  6373. }
  6374. this.routerEventsSubscription = this.createScrollEvents();
  6375. this.scrollEventsSubscription = this.consumeScrollEvents();
  6376. }
  6377. /**
  6378. * @return {?}
  6379. */
  6380. createScrollEvents() {
  6381. return this.router.events.subscribe(e => {
  6382. if (e instanceof NavigationStart) {
  6383. // store the scroll position of the current stable navigations.
  6384. this.store[this.lastId] = this.viewportScroller.getScrollPosition();
  6385. this.lastSource = e.navigationTrigger;
  6386. this.restoredId = e.restoredState ? e.restoredState.navigationId : 0;
  6387. }
  6388. else if (e instanceof NavigationEnd) {
  6389. this.lastId = e.id;
  6390. this.scheduleScrollEvent(e, this.router.parseUrl(e.urlAfterRedirects).fragment);
  6391. }
  6392. });
  6393. }
  6394. /**
  6395. * @return {?}
  6396. */
  6397. consumeScrollEvents() {
  6398. return this.router.events.subscribe(e => {
  6399. if (!(e instanceof Scroll))
  6400. return;
  6401. // a popstate event. The pop state event will always ignore anchor scrolling.
  6402. if (e.position) {
  6403. if (this.options.scrollPositionRestoration === 'top') {
  6404. this.viewportScroller.scrollToPosition([0, 0]);
  6405. }
  6406. else if (this.options.scrollPositionRestoration === 'enabled') {
  6407. this.viewportScroller.scrollToPosition(e.position);
  6408. }
  6409. // imperative navigation "forward"
  6410. }
  6411. else {
  6412. if (e.anchor && this.options.anchorScrolling === 'enabled') {
  6413. this.viewportScroller.scrollToAnchor(e.anchor);
  6414. }
  6415. else if (this.options.scrollPositionRestoration !== 'disabled') {
  6416. this.viewportScroller.scrollToPosition([0, 0]);
  6417. }
  6418. }
  6419. });
  6420. }
  6421. /**
  6422. * @param {?} routerEvent
  6423. * @param {?} anchor
  6424. * @return {?}
  6425. */
  6426. scheduleScrollEvent(routerEvent, anchor) {
  6427. this.router.triggerEvent(new Scroll(routerEvent, this.lastSource === 'popstate' ? this.store[this.restoredId] : null, anchor));
  6428. }
  6429. /**
  6430. * @return {?}
  6431. */
  6432. ngOnDestroy() {
  6433. if (this.routerEventsSubscription) {
  6434. this.routerEventsSubscription.unsubscribe();
  6435. }
  6436. if (this.scrollEventsSubscription) {
  6437. this.scrollEventsSubscription.unsubscribe();
  6438. }
  6439. }
  6440. }
  6441. /**
  6442. * @fileoverview added by tsickle
  6443. * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
  6444. */
  6445. /** *
  6446. * \@description
  6447. *
  6448. * Contains a list of directives
  6449. *
  6450. *
  6451. @type {?} */
  6452. const ROUTER_DIRECTIVES = [RouterOutlet, RouterLink, RouterLinkWithHref, RouterLinkActive, EmptyOutletComponent];
  6453. /** *
  6454. * \@description
  6455. *
  6456. * Is used in DI to configure the router.
  6457. *
  6458. * \@publicApi
  6459. @type {?} */
  6460. const ROUTER_CONFIGURATION = new InjectionToken('ROUTER_CONFIGURATION');
  6461. /** *
  6462. * \@docsNotRequired
  6463. @type {?} */
  6464. const ROUTER_FORROOT_GUARD = new InjectionToken('ROUTER_FORROOT_GUARD');
  6465. /** @type {?} */
  6466. const ROUTER_PROVIDERS = [
  6467. Location,
  6468. { provide: UrlSerializer, useClass: DefaultUrlSerializer },
  6469. {
  6470. provide: Router,
  6471. useFactory: setupRouter,
  6472. deps: [
  6473. ApplicationRef, UrlSerializer, ChildrenOutletContexts, Location, Injector,
  6474. NgModuleFactoryLoader, Compiler, ROUTES, ROUTER_CONFIGURATION,
  6475. [UrlHandlingStrategy, new Optional()], [RouteReuseStrategy, new Optional()]
  6476. ]
  6477. },
  6478. ChildrenOutletContexts,
  6479. { provide: ActivatedRoute, useFactory: rootRoute, deps: [Router] },
  6480. { provide: NgModuleFactoryLoader, useClass: SystemJsNgModuleLoader },
  6481. RouterPreloader,
  6482. NoPreloading,
  6483. PreloadAllModules,
  6484. { provide: ROUTER_CONFIGURATION, useValue: { enableTracing: false } },
  6485. ];
  6486. /**
  6487. * @return {?}
  6488. */
  6489. function routerNgProbeToken() {
  6490. return new NgProbeToken('Router', Router);
  6491. }
  6492. /**
  6493. * \@usageNotes
  6494. *
  6495. * RouterModule can be imported multiple times: once per lazily-loaded bundle.
  6496. * Since the router deals with a global shared resource--location, we cannot have
  6497. * more than one router service active.
  6498. *
  6499. * That is why there are two ways to create the module: `RouterModule.forRoot` and
  6500. * `RouterModule.forChild`.
  6501. *
  6502. * * `forRoot` creates a module that contains all the directives, the given routes, and the router
  6503. * service itself.
  6504. * * `forChild` creates a module that contains all the directives and the given routes, but does not
  6505. * include the router service.
  6506. *
  6507. * When registered at the root, the module should be used as follows
  6508. *
  6509. * ```
  6510. * \@NgModule({
  6511. * imports: [RouterModule.forRoot(ROUTES)]
  6512. * })
  6513. * class MyNgModule {}
  6514. * ```
  6515. *
  6516. * For submodules and lazy loaded submodules the module should be used as follows:
  6517. *
  6518. * ```
  6519. * \@NgModule({
  6520. * imports: [RouterModule.forChild(ROUTES)]
  6521. * })
  6522. * class MyNgModule {}
  6523. * ```
  6524. *
  6525. * \@description
  6526. *
  6527. * Adds router directives and providers.
  6528. *
  6529. * Managing state transitions is one of the hardest parts of building applications. This is
  6530. * especially true on the web, where you also need to ensure that the state is reflected in the URL.
  6531. * In addition, we often want to split applications into multiple bundles and load them on demand.
  6532. * Doing this transparently is not trivial.
  6533. *
  6534. * The Angular router solves these problems. Using the router, you can declaratively specify
  6535. * application states, manage state transitions while taking care of the URL, and load bundles on
  6536. * demand.
  6537. *
  6538. * [Read this developer guide](https://angular.io/docs/ts/latest/guide/router.html) to get an
  6539. * overview of how the router should be used.
  6540. *
  6541. * \@publicApi
  6542. */
  6543. class RouterModule {
  6544. /**
  6545. * @param {?} guard
  6546. * @param {?} router
  6547. */
  6548. constructor(guard, router) { }
  6549. /**
  6550. * Creates a module with all the router providers and directives. It also optionally sets up an
  6551. * application listener to perform an initial navigation.
  6552. *
  6553. * Options (see `ExtraOptions`):
  6554. * * `enableTracing` makes the router log all its internal events to the console.
  6555. * * `useHash` enables the location strategy that uses the URL fragment instead of the history
  6556. * API.
  6557. * * `initialNavigation` disables the initial navigation.
  6558. * * `errorHandler` provides a custom error handler.
  6559. * * `preloadingStrategy` configures a preloading strategy (see `PreloadAllModules`).
  6560. * * `onSameUrlNavigation` configures how the router handles navigation to the current URL. See
  6561. * `ExtraOptions` for more details.
  6562. * * `paramsInheritanceStrategy` defines how the router merges params, data and resolved data
  6563. * from parent to child routes.
  6564. * @param {?} routes
  6565. * @param {?=} config
  6566. * @return {?}
  6567. */
  6568. static forRoot(routes, config) {
  6569. return {
  6570. ngModule: RouterModule,
  6571. providers: [
  6572. ROUTER_PROVIDERS,
  6573. provideRoutes(routes),
  6574. {
  6575. provide: ROUTER_FORROOT_GUARD,
  6576. useFactory: provideForRootGuard,
  6577. deps: [[Router, new Optional(), new SkipSelf()]]
  6578. },
  6579. { provide: ROUTER_CONFIGURATION, useValue: config ? config : {} },
  6580. {
  6581. provide: LocationStrategy,
  6582. useFactory: provideLocationStrategy,
  6583. deps: [
  6584. PlatformLocation, [new Inject(APP_BASE_HREF), new Optional()], ROUTER_CONFIGURATION
  6585. ]
  6586. },
  6587. {
  6588. provide: RouterScroller,
  6589. useFactory: createRouterScroller,
  6590. deps: [Router, ViewportScroller, ROUTER_CONFIGURATION]
  6591. },
  6592. {
  6593. provide: PreloadingStrategy,
  6594. useExisting: config && config.preloadingStrategy ? config.preloadingStrategy :
  6595. NoPreloading
  6596. },
  6597. { provide: NgProbeToken, multi: true, useFactory: routerNgProbeToken },
  6598. provideRouterInitializer(),
  6599. ],
  6600. };
  6601. }
  6602. /**
  6603. * Creates a module with all the router directives and a provider registering routes.
  6604. * @param {?} routes
  6605. * @return {?}
  6606. */
  6607. static forChild(routes) {
  6608. return { ngModule: RouterModule, providers: [provideRoutes(routes)] };
  6609. }
  6610. }
  6611. RouterModule.decorators = [
  6612. { type: NgModule, args: [{
  6613. declarations: ROUTER_DIRECTIVES,
  6614. exports: ROUTER_DIRECTIVES,
  6615. entryComponents: [EmptyOutletComponent]
  6616. },] }
  6617. ];
  6618. /** @nocollapse */
  6619. RouterModule.ctorParameters = () => [
  6620. { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [ROUTER_FORROOT_GUARD,] }] },
  6621. { type: Router, decorators: [{ type: Optional }] }
  6622. ];
  6623. /**
  6624. * @param {?} router
  6625. * @param {?} viewportScroller
  6626. * @param {?} config
  6627. * @return {?}
  6628. */
  6629. function createRouterScroller(router, viewportScroller, config) {
  6630. if (config.scrollOffset) {
  6631. viewportScroller.setOffset(config.scrollOffset);
  6632. }
  6633. return new RouterScroller(router, viewportScroller, config);
  6634. }
  6635. /**
  6636. * @param {?} platformLocationStrategy
  6637. * @param {?} baseHref
  6638. * @param {?=} options
  6639. * @return {?}
  6640. */
  6641. function provideLocationStrategy(platformLocationStrategy, baseHref, options = {}) {
  6642. return options.useHash ? new HashLocationStrategy(platformLocationStrategy, baseHref) :
  6643. new PathLocationStrategy(platformLocationStrategy, baseHref);
  6644. }
  6645. /**
  6646. * @param {?} router
  6647. * @return {?}
  6648. */
  6649. function provideForRootGuard(router) {
  6650. if (router) {
  6651. throw new Error(`RouterModule.forRoot() called twice. Lazy loaded modules should use RouterModule.forChild() instead.`);
  6652. }
  6653. return 'guarded';
  6654. }
  6655. /**
  6656. * \@description
  6657. *
  6658. * Registers routes.
  6659. *
  6660. * \@usageNotes
  6661. * ### Example
  6662. *
  6663. * ```
  6664. * \@NgModule({
  6665. * imports: [RouterModule.forChild(ROUTES)],
  6666. * providers: [provideRoutes(EXTRA_ROUTES)]
  6667. * })
  6668. * class MyNgModule {}
  6669. * ```
  6670. *
  6671. * \@publicApi
  6672. * @param {?} routes
  6673. * @return {?}
  6674. */
  6675. function provideRoutes(routes) {
  6676. return [
  6677. { provide: ANALYZE_FOR_ENTRY_COMPONENTS, multi: true, useValue: routes },
  6678. { provide: ROUTES, multi: true, useValue: routes },
  6679. ];
  6680. }
  6681. /**
  6682. * @param {?} ref
  6683. * @param {?} urlSerializer
  6684. * @param {?} contexts
  6685. * @param {?} location
  6686. * @param {?} injector
  6687. * @param {?} loader
  6688. * @param {?} compiler
  6689. * @param {?} config
  6690. * @param {?=} opts
  6691. * @param {?=} urlHandlingStrategy
  6692. * @param {?=} routeReuseStrategy
  6693. * @return {?}
  6694. */
  6695. function setupRouter(ref, urlSerializer, contexts, location, injector, loader, compiler, config, opts = {}, urlHandlingStrategy, routeReuseStrategy) {
  6696. /** @type {?} */
  6697. const router = new Router(null, urlSerializer, contexts, location, injector, loader, compiler, flatten(config));
  6698. if (urlHandlingStrategy) {
  6699. router.urlHandlingStrategy = urlHandlingStrategy;
  6700. }
  6701. if (routeReuseStrategy) {
  6702. router.routeReuseStrategy = routeReuseStrategy;
  6703. }
  6704. if (opts.errorHandler) {
  6705. router.errorHandler = opts.errorHandler;
  6706. }
  6707. if (opts.malformedUriErrorHandler) {
  6708. router.malformedUriErrorHandler = opts.malformedUriErrorHandler;
  6709. }
  6710. if (opts.enableTracing) {
  6711. /** @type {?} */
  6712. const dom = ɵgetDOM();
  6713. router.events.subscribe((e) => {
  6714. dom.logGroup(`Router Event: ${((/** @type {?} */ (e.constructor))).name}`);
  6715. dom.log(e.toString());
  6716. dom.log(e);
  6717. dom.logGroupEnd();
  6718. });
  6719. }
  6720. if (opts.onSameUrlNavigation) {
  6721. router.onSameUrlNavigation = opts.onSameUrlNavigation;
  6722. }
  6723. if (opts.paramsInheritanceStrategy) {
  6724. router.paramsInheritanceStrategy = opts.paramsInheritanceStrategy;
  6725. }
  6726. if (opts.urlUpdateStrategy) {
  6727. router.urlUpdateStrategy = opts.urlUpdateStrategy;
  6728. }
  6729. if (opts.relativeLinkResolution) {
  6730. router.relativeLinkResolution = opts.relativeLinkResolution;
  6731. }
  6732. return router;
  6733. }
  6734. /**
  6735. * @param {?} router
  6736. * @return {?}
  6737. */
  6738. function rootRoute(router) {
  6739. return router.routerState.root;
  6740. }
  6741. /**
  6742. * To initialize the router properly we need to do in two steps:
  6743. *
  6744. * We need to start the navigation in a APP_INITIALIZER to block the bootstrap if
  6745. * a resolver or a guards executes asynchronously. Second, we need to actually run
  6746. * activation in a BOOTSTRAP_LISTENER. We utilize the afterPreactivation
  6747. * hook provided by the router to do that.
  6748. *
  6749. * The router navigation starts, reaches the point when preactivation is done, and then
  6750. * pauses. It waits for the hook to be resolved. We then resolve it only in a bootstrap listener.
  6751. */
  6752. class RouterInitializer {
  6753. /**
  6754. * @param {?} injector
  6755. */
  6756. constructor(injector) {
  6757. this.injector = injector;
  6758. this.initNavigation = false;
  6759. this.resultOfPreactivationDone = new Subject();
  6760. }
  6761. /**
  6762. * @return {?}
  6763. */
  6764. appInitializer() {
  6765. /** @type {?} */
  6766. const p = this.injector.get(LOCATION_INITIALIZED, Promise.resolve(null));
  6767. return p.then(() => {
  6768. /** @type {?} */
  6769. let resolve = /** @type {?} */ ((null));
  6770. /** @type {?} */
  6771. const res = new Promise(r => resolve = r);
  6772. /** @type {?} */
  6773. const router = this.injector.get(Router);
  6774. /** @type {?} */
  6775. const opts = this.injector.get(ROUTER_CONFIGURATION);
  6776. if (this.isLegacyDisabled(opts) || this.isLegacyEnabled(opts)) {
  6777. resolve(true);
  6778. }
  6779. else if (opts.initialNavigation === 'disabled') {
  6780. router.setUpLocationChangeListener();
  6781. resolve(true);
  6782. }
  6783. else if (opts.initialNavigation === 'enabled') {
  6784. router.hooks.afterPreactivation = () => {
  6785. // only the initial navigation should be delayed
  6786. if (!this.initNavigation) {
  6787. this.initNavigation = true;
  6788. resolve(true);
  6789. return this.resultOfPreactivationDone;
  6790. // subsequent navigations should not be delayed
  6791. }
  6792. else {
  6793. return /** @type {?} */ (of(null));
  6794. }
  6795. };
  6796. router.initialNavigation();
  6797. }
  6798. else {
  6799. throw new Error(`Invalid initialNavigation options: '${opts.initialNavigation}'`);
  6800. }
  6801. return res;
  6802. });
  6803. }
  6804. /**
  6805. * @param {?} bootstrappedComponentRef
  6806. * @return {?}
  6807. */
  6808. bootstrapListener(bootstrappedComponentRef) {
  6809. /** @type {?} */
  6810. const opts = this.injector.get(ROUTER_CONFIGURATION);
  6811. /** @type {?} */
  6812. const preloader = this.injector.get(RouterPreloader);
  6813. /** @type {?} */
  6814. const routerScroller = this.injector.get(RouterScroller);
  6815. /** @type {?} */
  6816. const router = this.injector.get(Router);
  6817. /** @type {?} */
  6818. const ref = this.injector.get(ApplicationRef);
  6819. if (bootstrappedComponentRef !== ref.components[0]) {
  6820. return;
  6821. }
  6822. if (this.isLegacyEnabled(opts)) {
  6823. router.initialNavigation();
  6824. }
  6825. else if (this.isLegacyDisabled(opts)) {
  6826. router.setUpLocationChangeListener();
  6827. }
  6828. preloader.setUpPreloading();
  6829. routerScroller.init();
  6830. router.resetRootComponentType(ref.componentTypes[0]);
  6831. this.resultOfPreactivationDone.next(/** @type {?} */ ((null)));
  6832. this.resultOfPreactivationDone.complete();
  6833. }
  6834. /**
  6835. * @param {?} opts
  6836. * @return {?}
  6837. */
  6838. isLegacyEnabled(opts) {
  6839. return opts.initialNavigation === 'legacy_enabled' || opts.initialNavigation === true ||
  6840. opts.initialNavigation === undefined;
  6841. }
  6842. /**
  6843. * @param {?} opts
  6844. * @return {?}
  6845. */
  6846. isLegacyDisabled(opts) {
  6847. return opts.initialNavigation === 'legacy_disabled' || opts.initialNavigation === false;
  6848. }
  6849. }
  6850. RouterInitializer.decorators = [
  6851. { type: Injectable }
  6852. ];
  6853. /** @nocollapse */
  6854. RouterInitializer.ctorParameters = () => [
  6855. { type: Injector }
  6856. ];
  6857. /**
  6858. * @param {?} r
  6859. * @return {?}
  6860. */
  6861. function getAppInitializer(r) {
  6862. return r.appInitializer.bind(r);
  6863. }
  6864. /**
  6865. * @param {?} r
  6866. * @return {?}
  6867. */
  6868. function getBootstrapListener(r) {
  6869. return r.bootstrapListener.bind(r);
  6870. }
  6871. /** *
  6872. * A token for the router initializer that will be called after the app is bootstrapped.
  6873. *
  6874. * \@publicApi
  6875. @type {?} */
  6876. const ROUTER_INITIALIZER = new InjectionToken('Router Initializer');
  6877. /**
  6878. * @return {?}
  6879. */
  6880. function provideRouterInitializer() {
  6881. return [
  6882. RouterInitializer,
  6883. {
  6884. provide: APP_INITIALIZER,
  6885. multi: true,
  6886. useFactory: getAppInitializer,
  6887. deps: [RouterInitializer]
  6888. },
  6889. { provide: ROUTER_INITIALIZER, useFactory: getBootstrapListener, deps: [RouterInitializer] },
  6890. { provide: APP_BOOTSTRAP_LISTENER, multi: true, useExisting: ROUTER_INITIALIZER },
  6891. ];
  6892. }
  6893. /**
  6894. * @fileoverview added by tsickle
  6895. * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
  6896. */
  6897. /** *
  6898. * \@publicApi
  6899. @type {?} */
  6900. const VERSION = new Version('7.0.3');
  6901. /**
  6902. * @fileoverview added by tsickle
  6903. * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
  6904. */
  6905. /**
  6906. * @fileoverview added by tsickle
  6907. * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
  6908. */
  6909. /**
  6910. * @fileoverview added by tsickle
  6911. * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
  6912. */
  6913. // This file only reexports content of the `src` folder. Keep it that way.
  6914. /**
  6915. * @fileoverview added by tsickle
  6916. * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
  6917. */
  6918. /**
  6919. * Generated bundle index. Do not edit.
  6920. */
  6921. export { ROUTER_FORROOT_GUARD as ɵangular_packages_router_router_a, RouterInitializer as ɵangular_packages_router_router_h, createRouterScroller as ɵangular_packages_router_router_c, getAppInitializer as ɵangular_packages_router_router_i, getBootstrapListener as ɵangular_packages_router_router_j, provideForRootGuard as ɵangular_packages_router_router_e, provideLocationStrategy as ɵangular_packages_router_router_d, provideRouterInitializer as ɵangular_packages_router_router_k, rootRoute as ɵangular_packages_router_router_g, routerNgProbeToken as ɵangular_packages_router_router_b, setupRouter as ɵangular_packages_router_router_f, RouterScroller as ɵangular_packages_router_router_n, Tree as ɵangular_packages_router_router_l, TreeNode as ɵangular_packages_router_router_m, RouterLink, RouterLinkWithHref, RouterLinkActive, RouterOutlet, ActivationEnd, ActivationStart, ChildActivationEnd, ChildActivationStart, GuardsCheckEnd, GuardsCheckStart, NavigationCancel, NavigationEnd, NavigationError, NavigationStart, ResolveEnd, ResolveStart, RouteConfigLoadEnd, RouteConfigLoadStart, RouterEvent, RoutesRecognized, Scroll, RouteReuseStrategy, Router, ROUTES, ROUTER_CONFIGURATION, ROUTER_INITIALIZER, RouterModule, provideRoutes, ChildrenOutletContexts, OutletContext, NoPreloading, PreloadAllModules, PreloadingStrategy, RouterPreloader, ActivatedRoute, ActivatedRouteSnapshot, RouterState, RouterStateSnapshot, PRIMARY_OUTLET, convertToParamMap, UrlHandlingStrategy, DefaultUrlSerializer, UrlSegment, UrlSegmentGroup, UrlSerializer, UrlTree, VERSION, EmptyOutletComponent as ɵEmptyOutletComponent, ROUTER_PROVIDERS as ɵROUTER_PROVIDERS, flatten as ɵflatten };
  6922. //# sourceMappingURL=router.js.map