@angular/router
Version:
Angular - the routing library
1,386 lines (1,375 loc) • 178 kB
JavaScript
/**
* @license Angular v21.0.5
* (c) 2010-2025 Google LLC. https://angular.dev/
* License: MIT
*/
import { DOCUMENT, Location } from '@angular/common';
import * as i0 from '@angular/core';
import { ɵisPromise as _isPromise, ɵRuntimeError as _RuntimeError, Injectable, ɵisNgModule as _isNgModule, isStandalone, createEnvironmentInjector, InjectionToken, EventEmitter, input, inject, ViewContainerRef, ChangeDetectorRef, Directive, Input, Output, reflectComponentType, Component, ɵisInjectable as _isInjectable, runInInjectionContext, makeEnvironmentProviders, Compiler, NgModuleFactory, ɵresolveComponentResources as _resolveComponentResources, afterNextRender, signal, EnvironmentInjector, DestroyRef, untracked, ɵConsole as _Console, ɵPendingTasksInternal as _PendingTasksInternal, ɵINTERNAL_APPLICATION_ERROR_HANDLER as _INTERNAL_APPLICATION_ERROR_HANDLER, ɵformatRuntimeError as _formatRuntimeError } from '@angular/core';
import { isObservable, from, of, BehaviorSubject, combineLatest, EmptyError, Observable, concat, defer, pipe, throwError, EMPTY, Subject, Subscription } from 'rxjs';
import { first, map, switchMap, take, startWith, filter, takeUntil, mergeMap, concatMap, tap, catchError, scan, defaultIfEmpty, last as last$1, takeLast, finalize } from 'rxjs/operators';
import * as i1 from '@angular/platform-browser';
const PRIMARY_OUTLET = 'primary';
const RouteTitleKey = /* @__PURE__ */Symbol('RouteTitle');
class ParamsAsMap {
params;
constructor(params) {
this.params = params || {};
}
has(name) {
return Object.prototype.hasOwnProperty.call(this.params, name);
}
get(name) {
if (this.has(name)) {
const v = this.params[name];
return Array.isArray(v) ? v[0] : v;
}
return null;
}
getAll(name) {
if (this.has(name)) {
const v = this.params[name];
return Array.isArray(v) ? v : [v];
}
return [];
}
get keys() {
return Object.keys(this.params);
}
}
function convertToParamMap(params) {
return new ParamsAsMap(params);
}
function defaultUrlMatcher(segments, segmentGroup, route) {
const parts = route.path.split('/');
if (parts.length > segments.length) {
return null;
}
if (route.pathMatch === 'full' && (segmentGroup.hasChildren() || parts.length < segments.length)) {
return null;
}
const posParams = {};
for (let index = 0; index < parts.length; index++) {
const part = parts[index];
const segment = segments[index];
const isParameter = part[0] === ':';
if (isParameter) {
posParams[part.substring(1)] = segment;
} else if (part !== segment.path) {
return null;
}
}
return {
consumed: segments.slice(0, parts.length),
posParams
};
}
function firstValueFrom(source) {
return new Promise((resolve, reject) => {
source.pipe(first()).subscribe({
next: value => resolve(value),
error: err => reject(err)
});
});
}
function shallowEqualArrays(a, b) {
if (a.length !== b.length) return false;
for (let i = 0; i < a.length; ++i) {
if (!shallowEqual(a[i], b[i])) return false;
}
return true;
}
function shallowEqual(a, b) {
const k1 = a ? getDataKeys(a) : undefined;
const k2 = b ? getDataKeys(b) : undefined;
if (!k1 || !k2 || k1.length != k2.length) {
return false;
}
let key;
for (let i = 0; i < k1.length; i++) {
key = k1[i];
if (!equalArraysOrString(a[key], b[key])) {
return false;
}
}
return true;
}
function getDataKeys(obj) {
return [...Object.keys(obj), ...Object.getOwnPropertySymbols(obj)];
}
function equalArraysOrString(a, b) {
if (Array.isArray(a) && Array.isArray(b)) {
if (a.length !== b.length) return false;
const aSorted = [...a].sort();
const bSorted = [...b].sort();
return aSorted.every((val, index) => bSorted[index] === val);
} else {
return a === b;
}
}
function last(a) {
return a.length > 0 ? a[a.length - 1] : null;
}
function wrapIntoObservable(value) {
if (isObservable(value)) {
return value;
}
if (_isPromise(value)) {
return from(Promise.resolve(value));
}
return of(value);
}
function wrapIntoPromise(value) {
if (isObservable(value)) {
return firstValueFrom(value);
}
return Promise.resolve(value);
}
const pathCompareMap = {
'exact': equalSegmentGroups,
'subset': containsSegmentGroup
};
const paramCompareMap = {
'exact': equalParams,
'subset': containsParams,
'ignored': () => true
};
function containsTree(container, containee, options) {
return pathCompareMap[options.paths](container.root, containee.root, options.matrixParams) && paramCompareMap[options.queryParams](container.queryParams, containee.queryParams) && !(options.fragment === 'exact' && container.fragment !== containee.fragment);
}
function equalParams(container, containee) {
return shallowEqual(container, containee);
}
function equalSegmentGroups(container, containee, matrixParams) {
if (!equalPath(container.segments, containee.segments)) return false;
if (!matrixParamsMatch(container.segments, containee.segments, matrixParams)) {
return false;
}
if (container.numberOfChildren !== containee.numberOfChildren) return false;
for (const c in containee.children) {
if (!container.children[c]) return false;
if (!equalSegmentGroups(container.children[c], containee.children[c], matrixParams)) return false;
}
return true;
}
function containsParams(container, containee) {
return Object.keys(containee).length <= Object.keys(container).length && Object.keys(containee).every(key => equalArraysOrString(container[key], containee[key]));
}
function containsSegmentGroup(container, containee, matrixParams) {
return containsSegmentGroupHelper(container, containee, containee.segments, matrixParams);
}
function containsSegmentGroupHelper(container, containee, containeePaths, matrixParams) {
if (container.segments.length > containeePaths.length) {
const current = container.segments.slice(0, containeePaths.length);
if (!equalPath(current, containeePaths)) return false;
if (containee.hasChildren()) return false;
if (!matrixParamsMatch(current, containeePaths, matrixParams)) return false;
return true;
} else if (container.segments.length === containeePaths.length) {
if (!equalPath(container.segments, containeePaths)) return false;
if (!matrixParamsMatch(container.segments, containeePaths, matrixParams)) return false;
for (const c in containee.children) {
if (!container.children[c]) return false;
if (!containsSegmentGroup(container.children[c], containee.children[c], matrixParams)) {
return false;
}
}
return true;
} else {
const current = containeePaths.slice(0, container.segments.length);
const next = containeePaths.slice(container.segments.length);
if (!equalPath(container.segments, current)) return false;
if (!matrixParamsMatch(container.segments, current, matrixParams)) return false;
if (!container.children[PRIMARY_OUTLET]) return false;
return containsSegmentGroupHelper(container.children[PRIMARY_OUTLET], containee, next, matrixParams);
}
}
function matrixParamsMatch(containerPaths, containeePaths, options) {
return containeePaths.every((containeeSegment, i) => {
return paramCompareMap[options](containerPaths[i].parameters, containeeSegment.parameters);
});
}
class UrlTree {
root;
queryParams;
fragment;
_queryParamMap;
constructor(root = new UrlSegmentGroup([], {}), queryParams = {}, fragment = null) {
this.root = root;
this.queryParams = queryParams;
this.fragment = fragment;
if (typeof ngDevMode === 'undefined' || ngDevMode) {
if (root.segments.length > 0) {
throw new _RuntimeError(4015, 'The root `UrlSegmentGroup` should not contain `segments`. ' + 'Instead, these segments belong in the `children` so they can be associated with a named outlet.');
}
}
}
get queryParamMap() {
this._queryParamMap ??= convertToParamMap(this.queryParams);
return this._queryParamMap;
}
toString() {
return DEFAULT_SERIALIZER.serialize(this);
}
}
class UrlSegmentGroup {
segments;
children;
parent = null;
constructor(segments, children) {
this.segments = segments;
this.children = children;
Object.values(children).forEach(v => v.parent = this);
}
hasChildren() {
return this.numberOfChildren > 0;
}
get numberOfChildren() {
return Object.keys(this.children).length;
}
toString() {
return serializePaths(this);
}
}
class UrlSegment {
path;
parameters;
_parameterMap;
constructor(path, parameters) {
this.path = path;
this.parameters = parameters;
}
get parameterMap() {
this._parameterMap ??= convertToParamMap(this.parameters);
return this._parameterMap;
}
toString() {
return serializePath(this);
}
}
function equalSegments(as, bs) {
return equalPath(as, bs) && as.every((a, i) => shallowEqual(a.parameters, bs[i].parameters));
}
function equalPath(as, bs) {
if (as.length !== bs.length) return false;
return as.every((a, i) => a.path === bs[i].path);
}
function mapChildrenIntoArray(segment, fn) {
let res = [];
Object.entries(segment.children).forEach(([childOutlet, child]) => {
if (childOutlet === PRIMARY_OUTLET) {
res = res.concat(fn(child, childOutlet));
}
});
Object.entries(segment.children).forEach(([childOutlet, child]) => {
if (childOutlet !== PRIMARY_OUTLET) {
res = res.concat(fn(child, childOutlet));
}
});
return res;
}
class UrlSerializer {
static ɵfac = i0.ɵɵngDeclareFactory({
minVersion: "12.0.0",
version: "21.0.5",
ngImport: i0,
type: UrlSerializer,
deps: [],
target: i0.ɵɵFactoryTarget.Injectable
});
static ɵprov = i0.ɵɵngDeclareInjectable({
minVersion: "12.0.0",
version: "21.0.5",
ngImport: i0,
type: UrlSerializer,
providedIn: 'root',
useFactory: () => new DefaultUrlSerializer()
});
}
i0.ɵɵngDeclareClassMetadata({
minVersion: "12.0.0",
version: "21.0.5",
ngImport: i0,
type: UrlSerializer,
decorators: [{
type: Injectable,
args: [{
providedIn: 'root',
useFactory: () => new DefaultUrlSerializer()
}]
}]
});
class DefaultUrlSerializer {
parse(url) {
const p = new UrlParser(url);
return new UrlTree(p.parseRootSegment(), p.parseQueryParams(), p.parseFragment());
}
serialize(tree) {
const segment = `/${serializeSegment(tree.root, true)}`;
const query = serializeQueryParams(tree.queryParams);
const fragment = typeof tree.fragment === `string` ? `#${encodeUriFragment(tree.fragment)}` : '';
return `${segment}${query}${fragment}`;
}
}
const DEFAULT_SERIALIZER = new DefaultUrlSerializer();
function serializePaths(segment) {
return segment.segments.map(p => serializePath(p)).join('/');
}
function serializeSegment(segment, root) {
if (!segment.hasChildren()) {
return serializePaths(segment);
}
if (root) {
const primary = segment.children[PRIMARY_OUTLET] ? serializeSegment(segment.children[PRIMARY_OUTLET], false) : '';
const children = [];
Object.entries(segment.children).forEach(([k, v]) => {
if (k !== PRIMARY_OUTLET) {
children.push(`${k}:${serializeSegment(v, false)}`);
}
});
return children.length > 0 ? `${primary}(${children.join('//')})` : primary;
} else {
const children = mapChildrenIntoArray(segment, (v, k) => {
if (k === PRIMARY_OUTLET) {
return [serializeSegment(segment.children[PRIMARY_OUTLET], false)];
}
return [`${k}:${serializeSegment(v, false)}`];
});
if (Object.keys(segment.children).length === 1 && segment.children[PRIMARY_OUTLET] != null) {
return `${serializePaths(segment)}/${children[0]}`;
}
return `${serializePaths(segment)}/(${children.join('//')})`;
}
}
function encodeUriString(s) {
return encodeURIComponent(s).replace(/%40/g, '@').replace(/%3A/gi, ':').replace(/%24/g, '$').replace(/%2C/gi, ',');
}
function encodeUriQuery(s) {
return encodeUriString(s).replace(/%3B/gi, ';');
}
function encodeUriFragment(s) {
return encodeURI(s);
}
function encodeUriSegment(s) {
return encodeUriString(s).replace(/\(/g, '%28').replace(/\)/g, '%29').replace(/%26/gi, '&');
}
function decode(s) {
return decodeURIComponent(s);
}
function decodeQuery(s) {
return decode(s.replace(/\+/g, '%20'));
}
function serializePath(path) {
return `${encodeUriSegment(path.path)}${serializeMatrixParams(path.parameters)}`;
}
function serializeMatrixParams(params) {
return Object.entries(params).map(([key, value]) => `;${encodeUriSegment(key)}=${encodeUriSegment(value)}`).join('');
}
function serializeQueryParams(params) {
const strParams = Object.entries(params).map(([name, value]) => {
return Array.isArray(value) ? value.map(v => `${encodeUriQuery(name)}=${encodeUriQuery(v)}`).join('&') : `${encodeUriQuery(name)}=${encodeUriQuery(value)}`;
}).filter(s => s);
return strParams.length ? `?${strParams.join('&')}` : '';
}
const SEGMENT_RE = /^[^\/()?;#]+/;
function matchSegments(str) {
const match = str.match(SEGMENT_RE);
return match ? match[0] : '';
}
const MATRIX_PARAM_SEGMENT_RE = /^[^\/()?;=#]+/;
function matchMatrixKeySegments(str) {
const match = str.match(MATRIX_PARAM_SEGMENT_RE);
return match ? match[0] : '';
}
const QUERY_PARAM_RE = /^[^=?&#]+/;
function matchQueryParams(str) {
const match = str.match(QUERY_PARAM_RE);
return match ? match[0] : '';
}
const QUERY_PARAM_VALUE_RE = /^[^&#]+/;
function matchUrlQueryParamValue(str) {
const match = str.match(QUERY_PARAM_VALUE_RE);
return match ? match[0] : '';
}
class UrlParser {
url;
remaining;
constructor(url) {
this.url = url;
this.remaining = url;
}
parseRootSegment() {
this.consumeOptional('/');
if (this.remaining === '' || this.peekStartsWith('?') || this.peekStartsWith('#')) {
return new UrlSegmentGroup([], {});
}
return new UrlSegmentGroup([], this.parseChildren());
}
parseQueryParams() {
const params = {};
if (this.consumeOptional('?')) {
do {
this.parseQueryParam(params);
} while (this.consumeOptional('&'));
}
return params;
}
parseFragment() {
return this.consumeOptional('#') ? decodeURIComponent(this.remaining) : null;
}
parseChildren() {
if (this.remaining === '') {
return {};
}
this.consumeOptional('/');
const segments = [];
if (!this.peekStartsWith('(')) {
segments.push(this.parseSegment());
}
while (this.peekStartsWith('/') && !this.peekStartsWith('//') && !this.peekStartsWith('/(')) {
this.capture('/');
segments.push(this.parseSegment());
}
let children = {};
if (this.peekStartsWith('/(')) {
this.capture('/');
children = this.parseParens(true);
}
let res = {};
if (this.peekStartsWith('(')) {
res = this.parseParens(false);
}
if (segments.length > 0 || Object.keys(children).length > 0) {
res[PRIMARY_OUTLET] = new UrlSegmentGroup(segments, children);
}
return res;
}
parseSegment() {
const path = matchSegments(this.remaining);
if (path === '' && this.peekStartsWith(';')) {
throw new _RuntimeError(4009, (typeof ngDevMode === 'undefined' || ngDevMode) && `Empty path url segment cannot have parameters: '${this.remaining}'.`);
}
this.capture(path);
return new UrlSegment(decode(path), this.parseMatrixParams());
}
parseMatrixParams() {
const params = {};
while (this.consumeOptional(';')) {
this.parseParam(params);
}
return params;
}
parseParam(params) {
const key = matchMatrixKeySegments(this.remaining);
if (!key) {
return;
}
this.capture(key);
let value = '';
if (this.consumeOptional('=')) {
const valueMatch = matchSegments(this.remaining);
if (valueMatch) {
value = valueMatch;
this.capture(value);
}
}
params[decode(key)] = decode(value);
}
parseQueryParam(params) {
const key = matchQueryParams(this.remaining);
if (!key) {
return;
}
this.capture(key);
let value = '';
if (this.consumeOptional('=')) {
const valueMatch = matchUrlQueryParamValue(this.remaining);
if (valueMatch) {
value = valueMatch;
this.capture(value);
}
}
const decodedKey = decodeQuery(key);
const decodedVal = decodeQuery(value);
if (params.hasOwnProperty(decodedKey)) {
let currentVal = params[decodedKey];
if (!Array.isArray(currentVal)) {
currentVal = [currentVal];
params[decodedKey] = currentVal;
}
currentVal.push(decodedVal);
} else {
params[decodedKey] = decodedVal;
}
}
parseParens(allowPrimary) {
const segments = {};
this.capture('(');
while (!this.consumeOptional(')') && this.remaining.length > 0) {
const path = matchSegments(this.remaining);
const next = this.remaining[path.length];
if (next !== '/' && next !== ')' && next !== ';') {
throw new _RuntimeError(4010, (typeof ngDevMode === 'undefined' || ngDevMode) && `Cannot parse url '${this.url}'`);
}
let outletName;
if (path.indexOf(':') > -1) {
outletName = path.slice(0, path.indexOf(':'));
this.capture(outletName);
this.capture(':');
} else if (allowPrimary) {
outletName = PRIMARY_OUTLET;
}
const children = this.parseChildren();
segments[outletName ?? PRIMARY_OUTLET] = Object.keys(children).length === 1 && children[PRIMARY_OUTLET] ? children[PRIMARY_OUTLET] : new UrlSegmentGroup([], children);
this.consumeOptional('//');
}
return segments;
}
peekStartsWith(str) {
return this.remaining.startsWith(str);
}
consumeOptional(str) {
if (this.peekStartsWith(str)) {
this.remaining = this.remaining.substring(str.length);
return true;
}
return false;
}
capture(str) {
if (!this.consumeOptional(str)) {
throw new _RuntimeError(4011, (typeof ngDevMode === 'undefined' || ngDevMode) && `Expected "${str}".`);
}
}
}
function createRoot(rootCandidate) {
return rootCandidate.segments.length > 0 ? new UrlSegmentGroup([], {
[PRIMARY_OUTLET]: rootCandidate
}) : rootCandidate;
}
function squashSegmentGroup(segmentGroup) {
const newChildren = {};
for (const [childOutlet, child] of Object.entries(segmentGroup.children)) {
const childCandidate = squashSegmentGroup(child);
if (childOutlet === PRIMARY_OUTLET && childCandidate.segments.length === 0 && childCandidate.hasChildren()) {
for (const [grandChildOutlet, grandChild] of Object.entries(childCandidate.children)) {
newChildren[grandChildOutlet] = grandChild;
}
} else if (childCandidate.segments.length > 0 || childCandidate.hasChildren()) {
newChildren[childOutlet] = childCandidate;
}
}
const s = new UrlSegmentGroup(segmentGroup.segments, newChildren);
return mergeTrivialChildren(s);
}
function mergeTrivialChildren(s) {
if (s.numberOfChildren === 1 && s.children[PRIMARY_OUTLET]) {
const c = s.children[PRIMARY_OUTLET];
return new UrlSegmentGroup(s.segments.concat(c.segments), c.children);
}
return s;
}
function isUrlTree(v) {
return v instanceof UrlTree;
}
function createUrlTreeFromSnapshot(relativeTo, commands, queryParams = null, fragment = null, urlSerializer = new DefaultUrlSerializer()) {
const relativeToUrlSegmentGroup = createSegmentGroupFromRoute(relativeTo);
return createUrlTreeFromSegmentGroup(relativeToUrlSegmentGroup, commands, queryParams, fragment, urlSerializer);
}
function createSegmentGroupFromRoute(route) {
let targetGroup;
function createSegmentGroupFromRouteRecursive(currentRoute) {
const childOutlets = {};
for (const childSnapshot of currentRoute.children) {
const root = createSegmentGroupFromRouteRecursive(childSnapshot);
childOutlets[childSnapshot.outlet] = root;
}
const segmentGroup = new UrlSegmentGroup(currentRoute.url, childOutlets);
if (currentRoute === route) {
targetGroup = segmentGroup;
}
return segmentGroup;
}
const rootCandidate = createSegmentGroupFromRouteRecursive(route.root);
const rootSegmentGroup = createRoot(rootCandidate);
return targetGroup ?? rootSegmentGroup;
}
function createUrlTreeFromSegmentGroup(relativeTo, commands, queryParams, fragment, urlSerializer) {
let root = relativeTo;
while (root.parent) {
root = root.parent;
}
if (commands.length === 0) {
return tree(root, root, root, queryParams, fragment, urlSerializer);
}
const nav = computeNavigation(commands);
if (nav.toRoot()) {
return tree(root, root, new UrlSegmentGroup([], {}), queryParams, fragment, urlSerializer);
}
const position = findStartingPositionForTargetGroup(nav, root, relativeTo);
const newSegmentGroup = position.processChildren ? updateSegmentGroupChildren(position.segmentGroup, position.index, nav.commands) : updateSegmentGroup(position.segmentGroup, position.index, nav.commands);
return tree(root, position.segmentGroup, newSegmentGroup, queryParams, fragment, urlSerializer);
}
function isMatrixParams(command) {
return typeof command === 'object' && command != null && !command.outlets && !command.segmentPath;
}
function isCommandWithOutlets(command) {
return typeof command === 'object' && command != null && command.outlets;
}
function normalizeQueryParams(k, v, urlSerializer) {
k ||= 'ɵ';
const tree = new UrlTree();
tree.queryParams = {
[k]: v
};
return urlSerializer.parse(urlSerializer.serialize(tree)).queryParams[k];
}
function tree(oldRoot, oldSegmentGroup, newSegmentGroup, queryParams, fragment, urlSerializer) {
const qp = {};
for (const [key, value] of Object.entries(queryParams ?? {})) {
qp[key] = Array.isArray(value) ? value.map(v => normalizeQueryParams(key, v, urlSerializer)) : normalizeQueryParams(key, value, urlSerializer);
}
let rootCandidate;
if (oldRoot === oldSegmentGroup) {
rootCandidate = newSegmentGroup;
} else {
rootCandidate = replaceSegment(oldRoot, oldSegmentGroup, newSegmentGroup);
}
const newRoot = createRoot(squashSegmentGroup(rootCandidate));
return new UrlTree(newRoot, qp, fragment);
}
function replaceSegment(current, oldSegment, newSegment) {
const children = {};
Object.entries(current.children).forEach(([outletName, c]) => {
if (c === oldSegment) {
children[outletName] = newSegment;
} else {
children[outletName] = replaceSegment(c, oldSegment, newSegment);
}
});
return new UrlSegmentGroup(current.segments, children);
}
class Navigation {
isAbsolute;
numberOfDoubleDots;
commands;
constructor(isAbsolute, numberOfDoubleDots, commands) {
this.isAbsolute = isAbsolute;
this.numberOfDoubleDots = numberOfDoubleDots;
this.commands = commands;
if (isAbsolute && commands.length > 0 && isMatrixParams(commands[0])) {
throw new _RuntimeError(4003, (typeof ngDevMode === 'undefined' || ngDevMode) && 'Root segment cannot have matrix parameters');
}
const cmdWithOutlet = commands.find(isCommandWithOutlets);
if (cmdWithOutlet && cmdWithOutlet !== last(commands)) {
throw new _RuntimeError(4004, (typeof ngDevMode === 'undefined' || ngDevMode) && '{outlets:{}} has to be the last command');
}
}
toRoot() {
return this.isAbsolute && this.commands.length === 1 && this.commands[0] == '/';
}
}
function computeNavigation(commands) {
if (typeof commands[0] === 'string' && commands.length === 1 && commands[0] === '/') {
return new Navigation(true, 0, commands);
}
let numberOfDoubleDots = 0;
let isAbsolute = false;
const res = commands.reduce((res, cmd, cmdIdx) => {
if (typeof cmd === 'object' && cmd != null) {
if (cmd.outlets) {
const outlets = {};
Object.entries(cmd.outlets).forEach(([name, commands]) => {
outlets[name] = typeof commands === 'string' ? commands.split('/') : commands;
});
return [...res, {
outlets
}];
}
if (cmd.segmentPath) {
return [...res, cmd.segmentPath];
}
}
if (!(typeof cmd === 'string')) {
return [...res, cmd];
}
if (cmdIdx === 0) {
cmd.split('/').forEach((urlPart, partIndex) => {
if (partIndex == 0 && urlPart === '.') ; else if (partIndex == 0 && urlPart === '') {
isAbsolute = true;
} else if (urlPart === '..') {
numberOfDoubleDots++;
} else if (urlPart != '') {
res.push(urlPart);
}
});
return res;
}
return [...res, cmd];
}, []);
return new Navigation(isAbsolute, numberOfDoubleDots, res);
}
class Position {
segmentGroup;
processChildren;
index;
constructor(segmentGroup, processChildren, index) {
this.segmentGroup = segmentGroup;
this.processChildren = processChildren;
this.index = index;
}
}
function findStartingPositionForTargetGroup(nav, root, target) {
if (nav.isAbsolute) {
return new Position(root, true, 0);
}
if (!target) {
return new Position(root, false, NaN);
}
if (target.parent === null) {
return new Position(target, true, 0);
}
const modifier = isMatrixParams(nav.commands[0]) ? 0 : 1;
const index = target.segments.length - 1 + modifier;
return createPositionApplyingDoubleDots(target, index, nav.numberOfDoubleDots);
}
function createPositionApplyingDoubleDots(group, index, numberOfDoubleDots) {
let g = group;
let ci = index;
let dd = numberOfDoubleDots;
while (dd > ci) {
dd -= ci;
g = g.parent;
if (!g) {
throw new _RuntimeError(4005, (typeof ngDevMode === 'undefined' || ngDevMode) && "Invalid number of '../'");
}
ci = g.segments.length;
}
return new Position(g, false, ci - dd);
}
function getOutlets(commands) {
if (isCommandWithOutlets(commands[0])) {
return commands[0].outlets;
}
return {
[PRIMARY_OUTLET]: commands
};
}
function updateSegmentGroup(segmentGroup, startIndex, commands) {
segmentGroup ??= new UrlSegmentGroup([], {});
if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) {
return updateSegmentGroupChildren(segmentGroup, startIndex, commands);
}
const m = prefixedWith(segmentGroup, startIndex, commands);
const slicedCommands = commands.slice(m.commandIndex);
if (m.match && m.pathIndex < segmentGroup.segments.length) {
const g = new UrlSegmentGroup(segmentGroup.segments.slice(0, m.pathIndex), {});
g.children[PRIMARY_OUTLET] = new UrlSegmentGroup(segmentGroup.segments.slice(m.pathIndex), segmentGroup.children);
return updateSegmentGroupChildren(g, 0, slicedCommands);
} else if (m.match && slicedCommands.length === 0) {
return new UrlSegmentGroup(segmentGroup.segments, {});
} else if (m.match && !segmentGroup.hasChildren()) {
return createNewSegmentGroup(segmentGroup, startIndex, commands);
} else if (m.match) {
return updateSegmentGroupChildren(segmentGroup, 0, slicedCommands);
} else {
return createNewSegmentGroup(segmentGroup, startIndex, commands);
}
}
function updateSegmentGroupChildren(segmentGroup, startIndex, commands) {
if (commands.length === 0) {
return new UrlSegmentGroup(segmentGroup.segments, {});
} else {
const outlets = getOutlets(commands);
const children = {};
if (Object.keys(outlets).some(o => o !== PRIMARY_OUTLET) && segmentGroup.children[PRIMARY_OUTLET] && segmentGroup.numberOfChildren === 1 && segmentGroup.children[PRIMARY_OUTLET].segments.length === 0) {
const childrenOfEmptyChild = updateSegmentGroupChildren(segmentGroup.children[PRIMARY_OUTLET], startIndex, commands);
return new UrlSegmentGroup(segmentGroup.segments, childrenOfEmptyChild.children);
}
Object.entries(outlets).forEach(([outlet, commands]) => {
if (typeof commands === 'string') {
commands = [commands];
}
if (commands !== null) {
children[outlet] = updateSegmentGroup(segmentGroup.children[outlet], startIndex, commands);
}
});
Object.entries(segmentGroup.children).forEach(([childOutlet, child]) => {
if (outlets[childOutlet] === undefined) {
children[childOutlet] = child;
}
});
return new UrlSegmentGroup(segmentGroup.segments, children);
}
}
function prefixedWith(segmentGroup, startIndex, commands) {
let currentCommandIndex = 0;
let currentPathIndex = startIndex;
const noMatch = {
match: false,
pathIndex: 0,
commandIndex: 0
};
while (currentPathIndex < segmentGroup.segments.length) {
if (currentCommandIndex >= commands.length) return noMatch;
const path = segmentGroup.segments[currentPathIndex];
const command = commands[currentCommandIndex];
if (isCommandWithOutlets(command)) {
break;
}
const curr = `${command}`;
const next = currentCommandIndex < commands.length - 1 ? commands[currentCommandIndex + 1] : null;
if (currentPathIndex > 0 && curr === undefined) break;
if (curr && next && typeof next === 'object' && next.outlets === undefined) {
if (!compare(curr, next, path)) return noMatch;
currentCommandIndex += 2;
} else {
if (!compare(curr, {}, path)) return noMatch;
currentCommandIndex++;
}
currentPathIndex++;
}
return {
match: true,
pathIndex: currentPathIndex,
commandIndex: currentCommandIndex
};
}
function createNewSegmentGroup(segmentGroup, startIndex, commands) {
const paths = segmentGroup.segments.slice(0, startIndex);
let i = 0;
while (i < commands.length) {
const command = commands[i];
if (isCommandWithOutlets(command)) {
const children = createNewSegmentChildren(command.outlets);
return new UrlSegmentGroup(paths, children);
}
if (i === 0 && isMatrixParams(commands[0])) {
const p = segmentGroup.segments[startIndex];
paths.push(new UrlSegment(p.path, stringify(commands[0])));
i++;
continue;
}
const curr = isCommandWithOutlets(command) ? command.outlets[PRIMARY_OUTLET] : `${command}`;
const next = i < commands.length - 1 ? commands[i + 1] : null;
if (curr && next && isMatrixParams(next)) {
paths.push(new UrlSegment(curr, stringify(next)));
i += 2;
} else {
paths.push(new UrlSegment(curr, {}));
i++;
}
}
return new UrlSegmentGroup(paths, {});
}
function createNewSegmentChildren(outlets) {
const children = {};
Object.entries(outlets).forEach(([outlet, commands]) => {
if (typeof commands === 'string') {
commands = [commands];
}
if (commands !== null) {
children[outlet] = createNewSegmentGroup(new UrlSegmentGroup([], {}), 0, commands);
}
});
return children;
}
function stringify(params) {
const res = {};
Object.entries(params).forEach(([k, v]) => res[k] = `${v}`);
return res;
}
function compare(path, params, segment) {
return path == segment.path && shallowEqual(params, segment.parameters);
}
const IMPERATIVE_NAVIGATION = 'imperative';
var EventType;
(function (EventType) {
EventType[EventType["NavigationStart"] = 0] = "NavigationStart";
EventType[EventType["NavigationEnd"] = 1] = "NavigationEnd";
EventType[EventType["NavigationCancel"] = 2] = "NavigationCancel";
EventType[EventType["NavigationError"] = 3] = "NavigationError";
EventType[EventType["RoutesRecognized"] = 4] = "RoutesRecognized";
EventType[EventType["ResolveStart"] = 5] = "ResolveStart";
EventType[EventType["ResolveEnd"] = 6] = "ResolveEnd";
EventType[EventType["GuardsCheckStart"] = 7] = "GuardsCheckStart";
EventType[EventType["GuardsCheckEnd"] = 8] = "GuardsCheckEnd";
EventType[EventType["RouteConfigLoadStart"] = 9] = "RouteConfigLoadStart";
EventType[EventType["RouteConfigLoadEnd"] = 10] = "RouteConfigLoadEnd";
EventType[EventType["ChildActivationStart"] = 11] = "ChildActivationStart";
EventType[EventType["ChildActivationEnd"] = 12] = "ChildActivationEnd";
EventType[EventType["ActivationStart"] = 13] = "ActivationStart";
EventType[EventType["ActivationEnd"] = 14] = "ActivationEnd";
EventType[EventType["Scroll"] = 15] = "Scroll";
EventType[EventType["NavigationSkipped"] = 16] = "NavigationSkipped";
})(EventType || (EventType = {}));
class RouterEvent {
id;
url;
constructor(id, url) {
this.id = id;
this.url = url;
}
}
class NavigationStart extends RouterEvent {
type = EventType.NavigationStart;
navigationTrigger;
restoredState;
constructor(id, url, navigationTrigger = 'imperative', restoredState = null) {
super(id, url);
this.navigationTrigger = navigationTrigger;
this.restoredState = restoredState;
}
toString() {
return `NavigationStart(id: ${this.id}, url: '${this.url}')`;
}
}
class NavigationEnd extends RouterEvent {
urlAfterRedirects;
type = EventType.NavigationEnd;
constructor(id, url, urlAfterRedirects) {
super(id, url);
this.urlAfterRedirects = urlAfterRedirects;
}
toString() {
return `NavigationEnd(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}')`;
}
}
var NavigationCancellationCode;
(function (NavigationCancellationCode) {
NavigationCancellationCode[NavigationCancellationCode["Redirect"] = 0] = "Redirect";
NavigationCancellationCode[NavigationCancellationCode["SupersededByNewNavigation"] = 1] = "SupersededByNewNavigation";
NavigationCancellationCode[NavigationCancellationCode["NoDataFromResolver"] = 2] = "NoDataFromResolver";
NavigationCancellationCode[NavigationCancellationCode["GuardRejected"] = 3] = "GuardRejected";
NavigationCancellationCode[NavigationCancellationCode["Aborted"] = 4] = "Aborted";
})(NavigationCancellationCode || (NavigationCancellationCode = {}));
var NavigationSkippedCode;
(function (NavigationSkippedCode) {
NavigationSkippedCode[NavigationSkippedCode["IgnoredSameUrlNavigation"] = 0] = "IgnoredSameUrlNavigation";
NavigationSkippedCode[NavigationSkippedCode["IgnoredByUrlHandlingStrategy"] = 1] = "IgnoredByUrlHandlingStrategy";
})(NavigationSkippedCode || (NavigationSkippedCode = {}));
class NavigationCancel extends RouterEvent {
reason;
code;
type = EventType.NavigationCancel;
constructor(id, url, reason, code) {
super(id, url);
this.reason = reason;
this.code = code;
}
toString() {
return `NavigationCancel(id: ${this.id}, url: '${this.url}')`;
}
}
class NavigationSkipped extends RouterEvent {
reason;
code;
type = EventType.NavigationSkipped;
constructor(id, url, reason, code) {
super(id, url);
this.reason = reason;
this.code = code;
}
}
class NavigationError extends RouterEvent {
error;
target;
type = EventType.NavigationError;
constructor(id, url, error, target) {
super(id, url);
this.error = error;
this.target = target;
}
toString() {
return `NavigationError(id: ${this.id}, url: '${this.url}', error: ${this.error})`;
}
}
class RoutesRecognized extends RouterEvent {
urlAfterRedirects;
state;
type = EventType.RoutesRecognized;
constructor(id, url, urlAfterRedirects, state) {
super(id, url);
this.urlAfterRedirects = urlAfterRedirects;
this.state = state;
}
toString() {
return `RoutesRecognized(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`;
}
}
class GuardsCheckStart extends RouterEvent {
urlAfterRedirects;
state;
type = EventType.GuardsCheckStart;
constructor(id, url, urlAfterRedirects, state) {
super(id, url);
this.urlAfterRedirects = urlAfterRedirects;
this.state = state;
}
toString() {
return `GuardsCheckStart(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`;
}
}
class GuardsCheckEnd extends RouterEvent {
urlAfterRedirects;
state;
shouldActivate;
type = EventType.GuardsCheckEnd;
constructor(id, url, urlAfterRedirects, state, shouldActivate) {
super(id, url);
this.urlAfterRedirects = urlAfterRedirects;
this.state = state;
this.shouldActivate = shouldActivate;
}
toString() {
return `GuardsCheckEnd(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state}, shouldActivate: ${this.shouldActivate})`;
}
}
class ResolveStart extends RouterEvent {
urlAfterRedirects;
state;
type = EventType.ResolveStart;
constructor(id, url, urlAfterRedirects, state) {
super(id, url);
this.urlAfterRedirects = urlAfterRedirects;
this.state = state;
}
toString() {
return `ResolveStart(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`;
}
}
class ResolveEnd extends RouterEvent {
urlAfterRedirects;
state;
type = EventType.ResolveEnd;
constructor(id, url, urlAfterRedirects, state) {
super(id, url);
this.urlAfterRedirects = urlAfterRedirects;
this.state = state;
}
toString() {
return `ResolveEnd(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`;
}
}
class RouteConfigLoadStart {
route;
type = EventType.RouteConfigLoadStart;
constructor(route) {
this.route = route;
}
toString() {
return `RouteConfigLoadStart(path: ${this.route.path})`;
}
}
class RouteConfigLoadEnd {
route;
type = EventType.RouteConfigLoadEnd;
constructor(route) {
this.route = route;
}
toString() {
return `RouteConfigLoadEnd(path: ${this.route.path})`;
}
}
class ChildActivationStart {
snapshot;
type = EventType.ChildActivationStart;
constructor(snapshot) {
this.snapshot = snapshot;
}
toString() {
const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || '';
return `ChildActivationStart(path: '${path}')`;
}
}
class ChildActivationEnd {
snapshot;
type = EventType.ChildActivationEnd;
constructor(snapshot) {
this.snapshot = snapshot;
}
toString() {
const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || '';
return `ChildActivationEnd(path: '${path}')`;
}
}
class ActivationStart {
snapshot;
type = EventType.ActivationStart;
constructor(snapshot) {
this.snapshot = snapshot;
}
toString() {
const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || '';
return `ActivationStart(path: '${path}')`;
}
}
class ActivationEnd {
snapshot;
type = EventType.ActivationEnd;
constructor(snapshot) {
this.snapshot = snapshot;
}
toString() {
const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || '';
return `ActivationEnd(path: '${path}')`;
}
}
class Scroll {
routerEvent;
position;
anchor;
type = EventType.Scroll;
constructor(routerEvent, position, anchor) {
this.routerEvent = routerEvent;
this.position = position;
this.anchor = anchor;
}
toString() {
const pos = this.position ? `${this.position[0]}, ${this.position[1]}` : null;
return `Scroll(anchor: '${this.anchor}', position: '${pos}')`;
}
}
class BeforeActivateRoutes {}
class RedirectRequest {
url;
navigationBehaviorOptions;
constructor(url, navigationBehaviorOptions) {
this.url = url;
this.navigationBehaviorOptions = navigationBehaviorOptions;
}
}
function isPublicRouterEvent(e) {
return !(e instanceof BeforeActivateRoutes) && !(e instanceof RedirectRequest);
}
function stringifyEvent(routerEvent) {
switch (routerEvent.type) {
case EventType.ActivationEnd:
return `ActivationEnd(path: '${routerEvent.snapshot.routeConfig?.path || ''}')`;
case EventType.ActivationStart:
return `ActivationStart(path: '${routerEvent.snapshot.routeConfig?.path || ''}')`;
case EventType.ChildActivationEnd:
return `ChildActivationEnd(path: '${routerEvent.snapshot.routeConfig?.path || ''}')`;
case EventType.ChildActivationStart:
return `ChildActivationStart(path: '${routerEvent.snapshot.routeConfig?.path || ''}')`;
case EventType.GuardsCheckEnd:
return `GuardsCheckEnd(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state}, shouldActivate: ${routerEvent.shouldActivate})`;
case EventType.GuardsCheckStart:
return `GuardsCheckStart(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`;
case EventType.NavigationCancel:
return `NavigationCancel(id: ${routerEvent.id}, url: '${routerEvent.url}')`;
case EventType.NavigationSkipped:
return `NavigationSkipped(id: ${routerEvent.id}, url: '${routerEvent.url}')`;
case EventType.NavigationEnd:
return `NavigationEnd(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}')`;
case EventType.NavigationError:
return `NavigationError(id: ${routerEvent.id}, url: '${routerEvent.url}', error: ${routerEvent.error})`;
case EventType.NavigationStart:
return `NavigationStart(id: ${routerEvent.id}, url: '${routerEvent.url}')`;
case EventType.ResolveEnd:
return `ResolveEnd(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`;
case EventType.ResolveStart:
return `ResolveStart(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`;
case EventType.RouteConfigLoadEnd:
return `RouteConfigLoadEnd(path: ${routerEvent.route.path})`;
case EventType.RouteConfigLoadStart:
return `RouteConfigLoadStart(path: ${routerEvent.route.path})`;
case EventType.RoutesRecognized:
return `RoutesRecognized(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`;
case EventType.Scroll:
const pos = routerEvent.position ? `${routerEvent.position[0]}, ${routerEvent.position[1]}` : null;
return `Scroll(anchor: '${routerEvent.anchor}', position: '${pos}')`;
}
}
function getOrCreateRouteInjectorIfNeeded(route, currentInjector) {
if (route.providers && !route._injector) {
route._injector = createEnvironmentInjector(route.providers, currentInjector, `Route: ${route.path}`);
}
return route._injector ?? currentInjector;
}
function validateConfig(config, parentPath = '', requireStandaloneComponents = false) {
for (let i = 0; i < config.length; i++) {
const route = config[i];
const fullPath = getFullPath(parentPath, route);
validateNode(route, fullPath, requireStandaloneComponents);
}
}
function assertStandalone(fullPath, component) {
if (component && _isNgModule(component)) {
throw new _RuntimeError(4014, `Invalid configuration of route '${fullPath}'. You are using 'loadComponent' with a module, ` + `but it must be used with standalone components. Use 'loadChildren' instead.`);
} else if (component && !isStandalone(component)) {
throw new _RuntimeError(4014, `Invalid configuration of route '${fullPath}'. The component must be standalone.`);
}
}
function validateNode(route, fullPath, requireStandaloneComponents) {
if (typeof ngDevMode === 'undefined' || ngDevMode) {
if (!route) {
throw new _RuntimeError(4014, `
Invalid configuration of route '${fullPath}': Encountered undefined route.
The reason might be an extra comma.
Example:
const routes: Routes = [
{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },
{ path: 'dashboard', component: DashboardComponent },, << two commas
{ path: 'detail/:id', component: HeroDetailComponent }
];
`);
}
if (Array.isArray(route)) {
throw new _RuntimeError(4014, `Invalid configuration of route '${fullPath}': Array cannot be specified`);
}
if (!route.redirectTo && !route.component && !route.loadComponent && !route.children && !route.loadChildren && route.outlet && route.outlet !== PRIMARY_OUTLET) {
throw new _RuntimeError(4014, `Invalid configuration of route '${fullPath}': a componentless route without children or loadChildren cannot have a named outlet set`);
}
if (route.redirectTo && route.children) {
throw new _RuntimeError(4014, `Invalid configuration of route '${fullPath}': redirectTo and children cannot be used together`);
}
if (route.redirectTo && route.loadChildren) {
throw new _RuntimeError(4014, `Invalid configuration of route '${fullPath}': redirectTo and loadChildren cannot be used together`);
}
if (route.children && route.loadChildren) {
throw new _RuntimeError(4014, `Invalid configuration of route '${fullPath}': children and loadChildren cannot be used together`);
}
if (route.component && route.loadComponent) {
throw new _RuntimeError(4014, `Invalid configuration of route '${fullPath}': component and loadComponent cannot be used together`);
}
if (route.redirectTo) {
if (route.component || route.loadComponent) {
throw new _RuntimeError(4014, `Invalid configuration of route '${fullPath}': redirectTo and component/loadComponent cannot be used together`);
}
if (route.canMatch || route.canActivate) {
throw new _RuntimeError(4014, `Invalid configuration of route '${fullPath}': redirectTo and ${route.canMatch ? 'canMatch' : 'canActivate'} cannot be used together.` + `Redirects happen before guards are executed.`);
}
}
if (route.path && route.matcher) {
throw new _RuntimeError(4014, `Invalid configuration of route '${fullPath}': path and matcher cannot be used together`);
}
if (route.redirectTo === void 0 && !route.component && !route.loadComponent && !route.children && !route.loadChildren) {
throw new _RuntimeError(4014, `Invalid configuration of route '${fullPath}'. One of the following must be provided: component, loadComponent, redirectTo, children or loadChildren`);
}
if (route.path === void 0 && route.matcher === void 0) {
throw new _RuntimeError(4014, `Invalid configuration of route '${fullPath}': routes must have either a path or a matcher specified`);
}
if (typeof route.path === 'string' && route.path.charAt(0) === '/') {
throw new _RuntimeError(4014, `Invalid configuration of route '${fullPath}': path cannot start with a slash`);
}
if (route.path === '' && route.redirectTo !== void 0 && route.pathMatch === void 0) {
const exp = `The default value of 'pathMatch' is 'prefix', but often the intent is to use 'full'.`;
throw new _RuntimeError(4014, `Invalid configuration of route '{path: "${fullPath}", redirectTo: "${route.redirectTo}"}': please provide 'pathMatch'. ${exp}`);
}
if (requireStandaloneComponents) {
assertStandalone(fullPath, route.component);
}
}
if (route.children) {
validateConfig(route.children, fullPath, requireStandaloneComponents);
}
}
function getFullPath(parentPath, currentRoute) {
if (!currentRoute) {
return parentPath;
}
if (!parentPath && !currentRoute.path) {
return '';
} else if (parentPath && !currentRoute.path) {
return `${parentPath}/`;
} else if (!parentPath && currentRoute.path) {
return currentRoute.path;
} else {
return `${parentPath}/${currentRoute.path}`;
}
}
function getOutlet(route) {
return route.outlet || PRIMARY_OUTLET;
}
function sortByMatchingOutlets(routes, outletName) {
const sortedConfig = routes.filter(r => getOutlet(r) === outletName);
sortedConfig.push(...routes.filter(r => getOutlet(r) !== outletName));
return sortedConfig;
}
function getClosestRouteInjector(snapshot) {
if (!snapshot) return null;
if (snapshot.routeConfig?._injector) {
return snapshot.routeConfig._injector;
}
for (let s = snapshot.parent; s; s = s.parent) {
const route = s.routeConfig;
if (route?._loadedInjector) return route._loadedInjector;
if (route?._injector) return route._injector;
}
return null;
}
class OutletContext {
rootInjector;
outlet = null;
route = null;
children;
attachRef = null;
get injector() {
return getClosestRouteInjector(this.route?.snapshot) ?? this.rootInjector;
}
constructor(rootInjector) {
this.rootInjector = rootInjector;
this.children = new ChildrenOutletContexts(this.rootInjector);
}
}
class ChildrenOutletContexts {
rootInjector;
contexts = new Map();
constructor(rootInjector) {
this.rootInjector = rootInjector;
}
onChildOutletCreated(childName, outlet) {
const context = this.getOrCreateContext(childName);
context.outlet = outlet;
this.contexts.set(childName, context);
}
onChildOutletDestroyed(childName) {
const context = this.getContext(childName);
if (context) {
context.outlet = null;
context.attachRef = null;
}
}
onOutletDeactivated() {
const contexts = this.contexts;
this.contexts = new Map();
return contexts;
}
onOutletReAttached(contexts) {
this.contexts = contexts;
}
getOrCreateContext(childName) {
let context = this.getContext(childName);
if (!context) {
context = new OutletContext(this.rootInjector);
this.contexts.set(childName, context);
}
return context;
}
getContext(childName) {
return this.contexts.get(childName) || null;
}
static ɵfac = i0.ɵɵngDeclareFactory({
minVersion: "12.0.0",
version: "21.0.5",
ngImport: i0,
type: ChildrenOutletContexts,
deps: [{
token: i0.EnvironmentInjector
}],
target: i0.ɵɵFactoryTarget.Injectable
});
static ɵprov = i0.ɵɵngDeclareInjectable({
minVersion: "12.0.0",
version: "21.0.5",
ngImport: i0,
type: ChildrenOutletContexts,
providedIn: 'root'
});
}
i0.ɵɵngDeclareClassMetadata({
minVersion: "12.0.0",
version: "21.0.5",
ngImport: i0,
type: ChildrenOutletContexts,
decorators: [{