@angular/router 14.0.0-next.13 → 14.0.0-next.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2020/src/apply_redirects.mjs +56 -46
- package/esm2020/src/components/empty_outlet.mjs +3 -3
- package/esm2020/src/directives/router_link.mjs +6 -6
- package/esm2020/src/directives/router_link_active.mjs +3 -3
- package/esm2020/src/directives/router_outlet.mjs +24 -15
- package/esm2020/src/models.mjs +2 -7
- package/esm2020/src/operators/activate_routes.mjs +7 -14
- package/esm2020/src/operators/apply_redirects.mjs +3 -3
- package/esm2020/src/operators/resolve_data.mjs +5 -12
- package/esm2020/src/page_title_strategy.mjs +3 -3
- package/esm2020/src/recognize.mjs +2 -2
- package/esm2020/src/router.mjs +9 -6
- package/esm2020/src/router_config_loader.mjs +29 -18
- package/esm2020/src/router_module.mjs +10 -9
- package/esm2020/src/router_outlet_context.mjs +6 -1
- package/esm2020/src/router_preloader.mjs +31 -24
- package/esm2020/src/router_scroller.mjs +3 -3
- package/esm2020/src/router_state.mjs +1 -2
- package/esm2020/src/utils/config.mjs +44 -1
- package/esm2020/src/utils/preactivation.mjs +5 -14
- package/esm2020/src/version.mjs +1 -1
- package/esm2020/testing/src/router_testing_module.mjs +4 -4
- package/fesm2015/router.mjs +667 -613
- package/fesm2015/router.mjs.map +1 -1
- package/fesm2015/testing.mjs +5 -5
- package/fesm2015/upgrade.mjs +1 -1
- package/fesm2020/router.mjs +661 -613
- package/fesm2020/router.mjs.map +1 -1
- package/fesm2020/testing.mjs +5 -5
- package/fesm2020/upgrade.mjs +1 -1
- package/package.json +4 -4
- package/router.d.ts +53 -13
- package/testing/testing.d.ts +1 -1
- package/upgrade/upgrade.d.ts +1 -1
package/fesm2015/router.mjs
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular v14.0.0-next.
|
|
2
|
+
* @license Angular v14.0.0-next.14
|
|
3
3
|
* (c) 2010-2022 Google LLC. https://angular.io/
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import * as i0 from '@angular/core';
|
|
8
|
-
import { ɵisObservable, ɵisPromise, EventEmitter, Directive, Attribute, Output, Component,
|
|
8
|
+
import { ɵisObservable, ɵisPromise, EventEmitter, Directive, Attribute, Output, Component, ComponentFactoryResolver, createEnvironmentInjector, InjectionToken, InjectFlags, NgModuleFactory, Injectable, NgModuleRef, ɵConsole, NgZone, ɵcoerceToBoolean, Input, HostListener, HostBinding, Optional, ContentChildren, Injector, Compiler, NgProbeToken, ANALYZE_FOR_ENTRY_COMPONENTS, SkipSelf, Inject, APP_INITIALIZER, APP_BOOTSTRAP_LISTENER, NgModule, ApplicationRef, Version } from '@angular/core';
|
|
9
9
|
import { from, of, BehaviorSubject, combineLatest, throwError, EmptyError, concat, defer, Observable, EMPTY, ConnectableObservable, Subject } from 'rxjs';
|
|
10
|
-
import { map, switchMap, take, startWith, scan, filter, catchError, concatMap, last as last$1, first, mergeMap, tap, takeLast,
|
|
10
|
+
import { map, switchMap, take, startWith, scan, filter, catchError, concatMap, last as last$1, first, mergeMap, tap, takeLast, mapTo, finalize, refCount, mergeAll } from 'rxjs/operators';
|
|
11
11
|
import * as i3 from '@angular/common';
|
|
12
12
|
import { Location, LocationStrategy, PlatformLocation, APP_BASE_HREF, ViewportScroller, HashLocationStrategy, PathLocationStrategy, LOCATION_INITIALIZED } from '@angular/common';
|
|
13
13
|
import * as i1 from '@angular/platform-browser';
|
|
@@ -1362,7 +1362,6 @@ class ActivatedRoute {
|
|
|
1362
1362
|
/** The outlet name of the route, a constant. */
|
|
1363
1363
|
outlet,
|
|
1364
1364
|
/** The component of the route, a constant. */
|
|
1365
|
-
// TODO(vsavkin): remove |string
|
|
1366
1365
|
component, futureSnapshot) {
|
|
1367
1366
|
this.url = url;
|
|
1368
1367
|
this.params = params;
|
|
@@ -2023,181 +2022,76 @@ function compare(path, params, segment) {
|
|
|
2023
2022
|
* Use of this source code is governed by an MIT-style license that can be
|
|
2024
2023
|
* found in the LICENSE file at https://angular.io/license
|
|
2025
2024
|
*/
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
class
|
|
2032
|
-
constructor(
|
|
2033
|
-
this.
|
|
2034
|
-
this.
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
this.
|
|
2042
|
-
|
|
2043
|
-
this.activateChildRoutes(futureRoot, currRoot, parentContexts);
|
|
2044
|
-
}
|
|
2045
|
-
// De-activate the child route that are not re-used for the future state
|
|
2046
|
-
deactivateChildRoutes(futureNode, currNode, contexts) {
|
|
2047
|
-
const children = nodeChildrenAsMap(currNode);
|
|
2048
|
-
// Recurse on the routes active in the future state to de-activate deeper children
|
|
2049
|
-
futureNode.children.forEach(futureChild => {
|
|
2050
|
-
const childOutletName = futureChild.value.outlet;
|
|
2051
|
-
this.deactivateRoutes(futureChild, children[childOutletName], contexts);
|
|
2052
|
-
delete children[childOutletName];
|
|
2053
|
-
});
|
|
2054
|
-
// De-activate the routes that will not be re-used
|
|
2055
|
-
forEach(children, (v, childName) => {
|
|
2056
|
-
this.deactivateRouteAndItsChildren(v, contexts);
|
|
2057
|
-
});
|
|
2058
|
-
}
|
|
2059
|
-
deactivateRoutes(futureNode, currNode, parentContext) {
|
|
2060
|
-
const future = futureNode.value;
|
|
2061
|
-
const curr = currNode ? currNode.value : null;
|
|
2062
|
-
if (future === curr) {
|
|
2063
|
-
// Reusing the node, check to see if the children need to be de-activated
|
|
2064
|
-
if (future.component) {
|
|
2065
|
-
// If we have a normal route, we need to go through an outlet.
|
|
2066
|
-
const context = parentContext.getContext(future.outlet);
|
|
2067
|
-
if (context) {
|
|
2068
|
-
this.deactivateChildRoutes(futureNode, currNode, context.children);
|
|
2069
|
-
}
|
|
2070
|
-
}
|
|
2071
|
-
else {
|
|
2072
|
-
// if we have a componentless route, we recurse but keep the same outlet map.
|
|
2073
|
-
this.deactivateChildRoutes(futureNode, currNode, parentContext);
|
|
2074
|
-
}
|
|
2075
|
-
}
|
|
2076
|
-
else {
|
|
2077
|
-
if (curr) {
|
|
2078
|
-
// Deactivate the current route which will not be re-used
|
|
2079
|
-
this.deactivateRouteAndItsChildren(currNode, parentContext);
|
|
2080
|
-
}
|
|
2081
|
-
}
|
|
2025
|
+
/**
|
|
2026
|
+
* Store contextual information about a `RouterOutlet`
|
|
2027
|
+
*
|
|
2028
|
+
* @publicApi
|
|
2029
|
+
*/
|
|
2030
|
+
class OutletContext {
|
|
2031
|
+
constructor() {
|
|
2032
|
+
this.outlet = null;
|
|
2033
|
+
this.route = null;
|
|
2034
|
+
/**
|
|
2035
|
+
* @deprecated Passing a resolver to retrieve a component factory is not required and is
|
|
2036
|
+
* deprecated since v14.
|
|
2037
|
+
*/
|
|
2038
|
+
this.resolver = null;
|
|
2039
|
+
this.injector = null;
|
|
2040
|
+
this.children = new ChildrenOutletContexts();
|
|
2041
|
+
this.attachRef = null;
|
|
2082
2042
|
}
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2043
|
+
}
|
|
2044
|
+
/**
|
|
2045
|
+
* Store contextual information about the children (= nested) `RouterOutlet`
|
|
2046
|
+
*
|
|
2047
|
+
* @publicApi
|
|
2048
|
+
*/
|
|
2049
|
+
class ChildrenOutletContexts {
|
|
2050
|
+
constructor() {
|
|
2051
|
+
// contexts for child outlets, by name.
|
|
2052
|
+
this.contexts = new Map();
|
|
2092
2053
|
}
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
const
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
this.deactivateRouteAndItsChildren(children[childOutlet], contexts);
|
|
2099
|
-
}
|
|
2100
|
-
if (context && context.outlet) {
|
|
2101
|
-
const componentRef = context.outlet.detach();
|
|
2102
|
-
const contexts = context.children.onOutletDeactivated();
|
|
2103
|
-
this.routeReuseStrategy.store(route.value.snapshot, { componentRef, route, contexts });
|
|
2104
|
-
}
|
|
2054
|
+
/** Called when a `RouterOutlet` directive is instantiated */
|
|
2055
|
+
onChildOutletCreated(childName, outlet) {
|
|
2056
|
+
const context = this.getOrCreateContext(childName);
|
|
2057
|
+
context.outlet = outlet;
|
|
2058
|
+
this.contexts.set(childName, context);
|
|
2105
2059
|
}
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
if (context && context.outlet) {
|
|
2116
|
-
// Destroy the component
|
|
2117
|
-
context.outlet.deactivate();
|
|
2118
|
-
// Destroy the contexts for all the outlets that were in the component
|
|
2119
|
-
context.children.onOutletDeactivated();
|
|
2120
|
-
// Clear the information about the attached component on the context but keep the reference to
|
|
2121
|
-
// the outlet.
|
|
2060
|
+
/**
|
|
2061
|
+
* Called when a `RouterOutlet` directive is destroyed.
|
|
2062
|
+
* We need to keep the context as the outlet could be destroyed inside a NgIf and might be
|
|
2063
|
+
* re-created later.
|
|
2064
|
+
*/
|
|
2065
|
+
onChildOutletDestroyed(childName) {
|
|
2066
|
+
const context = this.getContext(childName);
|
|
2067
|
+
if (context) {
|
|
2068
|
+
context.outlet = null;
|
|
2122
2069
|
context.attachRef = null;
|
|
2123
|
-
context.resolver = null;
|
|
2124
|
-
context.route = null;
|
|
2125
2070
|
}
|
|
2126
2071
|
}
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
}
|
|
2072
|
+
/**
|
|
2073
|
+
* Called when the corresponding route is deactivated during navigation.
|
|
2074
|
+
* Because the component get destroyed, all children outlet are destroyed.
|
|
2075
|
+
*/
|
|
2076
|
+
onOutletDeactivated() {
|
|
2077
|
+
const contexts = this.contexts;
|
|
2078
|
+
this.contexts = new Map();
|
|
2079
|
+
return contexts;
|
|
2136
2080
|
}
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
if (
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
const context = parentContexts.getOrCreateContext(future.outlet);
|
|
2146
|
-
this.activateChildRoutes(futureNode, currNode, context.children);
|
|
2147
|
-
}
|
|
2148
|
-
else {
|
|
2149
|
-
// if we have a componentless route, we recurse but keep the same outlet map.
|
|
2150
|
-
this.activateChildRoutes(futureNode, currNode, parentContexts);
|
|
2151
|
-
}
|
|
2152
|
-
}
|
|
2153
|
-
else {
|
|
2154
|
-
if (future.component) {
|
|
2155
|
-
// if we have a normal route, we need to place the component into the outlet and recurse.
|
|
2156
|
-
const context = parentContexts.getOrCreateContext(future.outlet);
|
|
2157
|
-
if (this.routeReuseStrategy.shouldAttach(future.snapshot)) {
|
|
2158
|
-
const stored = this.routeReuseStrategy.retrieve(future.snapshot);
|
|
2159
|
-
this.routeReuseStrategy.store(future.snapshot, null);
|
|
2160
|
-
context.children.onOutletReAttached(stored.contexts);
|
|
2161
|
-
context.attachRef = stored.componentRef;
|
|
2162
|
-
context.route = stored.route.value;
|
|
2163
|
-
if (context.outlet) {
|
|
2164
|
-
// Attach right away when the outlet has already been instantiated
|
|
2165
|
-
// Otherwise attach from `RouterOutlet.ngOnInit` when it is instantiated
|
|
2166
|
-
context.outlet.attach(stored.componentRef, stored.route.value);
|
|
2167
|
-
}
|
|
2168
|
-
advanceActivatedRoute(stored.route.value);
|
|
2169
|
-
this.activateChildRoutes(futureNode, null, context.children);
|
|
2170
|
-
}
|
|
2171
|
-
else {
|
|
2172
|
-
const config = parentLoadedConfig(future.snapshot);
|
|
2173
|
-
const cmpFactoryResolver = config ? config.module.componentFactoryResolver : null;
|
|
2174
|
-
context.attachRef = null;
|
|
2175
|
-
context.route = future;
|
|
2176
|
-
context.resolver = cmpFactoryResolver;
|
|
2177
|
-
if (context.outlet) {
|
|
2178
|
-
// Activate the outlet when it has already been instantiated
|
|
2179
|
-
// Otherwise it will get activated from its `ngOnInit` when instantiated
|
|
2180
|
-
context.outlet.activateWith(future, cmpFactoryResolver);
|
|
2181
|
-
}
|
|
2182
|
-
this.activateChildRoutes(futureNode, null, context.children);
|
|
2183
|
-
}
|
|
2184
|
-
}
|
|
2185
|
-
else {
|
|
2186
|
-
// if we have a componentless route, we recurse but keep the same outlet map.
|
|
2187
|
-
this.activateChildRoutes(futureNode, null, parentContexts);
|
|
2188
|
-
}
|
|
2081
|
+
onOutletReAttached(contexts) {
|
|
2082
|
+
this.contexts = contexts;
|
|
2083
|
+
}
|
|
2084
|
+
getOrCreateContext(childName) {
|
|
2085
|
+
let context = this.getContext(childName);
|
|
2086
|
+
if (!context) {
|
|
2087
|
+
context = new OutletContext();
|
|
2088
|
+
this.contexts.set(childName, context);
|
|
2189
2089
|
}
|
|
2090
|
+
return context;
|
|
2190
2091
|
}
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
for (let s = snapshot.parent; s; s = s.parent) {
|
|
2194
|
-
const route = s.routeConfig;
|
|
2195
|
-
if (route && route._loadedConfig)
|
|
2196
|
-
return route._loadedConfig;
|
|
2197
|
-
if (route && route.component)
|
|
2198
|
-
return null;
|
|
2092
|
+
getContext(childName) {
|
|
2093
|
+
return this.contexts.get(childName) || null;
|
|
2199
2094
|
}
|
|
2200
|
-
return null;
|
|
2201
2095
|
}
|
|
2202
2096
|
|
|
2203
2097
|
/**
|
|
@@ -2207,182 +2101,13 @@ function parentLoadedConfig(snapshot) {
|
|
|
2207
2101
|
* Use of this source code is governed by an MIT-style license that can be
|
|
2208
2102
|
* found in the LICENSE file at https://angular.io/license
|
|
2209
2103
|
*/
|
|
2210
|
-
class LoadedRouterConfig {
|
|
2211
|
-
constructor(routes, module) {
|
|
2212
|
-
this.routes = routes;
|
|
2213
|
-
this.module = module;
|
|
2214
|
-
}
|
|
2215
|
-
}
|
|
2216
|
-
|
|
2217
2104
|
/**
|
|
2218
|
-
* @
|
|
2219
|
-
* Copyright Google LLC All Rights Reserved.
|
|
2105
|
+
* @description
|
|
2220
2106
|
*
|
|
2221
|
-
*
|
|
2222
|
-
* found in the LICENSE file at https://angular.io/license
|
|
2223
|
-
*/
|
|
2224
|
-
/**
|
|
2225
|
-
* Simple function check, but generic so type inference will flow. Example:
|
|
2107
|
+
* Acts as a placeholder that Angular dynamically fills based on the current router state.
|
|
2226
2108
|
*
|
|
2227
|
-
*
|
|
2228
|
-
*
|
|
2229
|
-
* }
|
|
2230
|
-
*
|
|
2231
|
-
* if (isFunction<product>(fn)) {
|
|
2232
|
-
* return fn(1, 2);
|
|
2233
|
-
* } else {
|
|
2234
|
-
* throw "Must provide the `product` function";
|
|
2235
|
-
* }
|
|
2236
|
-
*/
|
|
2237
|
-
function isFunction(v) {
|
|
2238
|
-
return typeof v === 'function';
|
|
2239
|
-
}
|
|
2240
|
-
function isBoolean(v) {
|
|
2241
|
-
return typeof v === 'boolean';
|
|
2242
|
-
}
|
|
2243
|
-
function isUrlTree(v) {
|
|
2244
|
-
return v instanceof UrlTree;
|
|
2245
|
-
}
|
|
2246
|
-
function isCanLoad(guard) {
|
|
2247
|
-
return guard && isFunction(guard.canLoad);
|
|
2248
|
-
}
|
|
2249
|
-
function isCanActivate(guard) {
|
|
2250
|
-
return guard && isFunction(guard.canActivate);
|
|
2251
|
-
}
|
|
2252
|
-
function isCanActivateChild(guard) {
|
|
2253
|
-
return guard && isFunction(guard.canActivateChild);
|
|
2254
|
-
}
|
|
2255
|
-
function isCanDeactivate(guard) {
|
|
2256
|
-
return guard && isFunction(guard.canDeactivate);
|
|
2257
|
-
}
|
|
2258
|
-
|
|
2259
|
-
/**
|
|
2260
|
-
* @license
|
|
2261
|
-
* Copyright Google LLC All Rights Reserved.
|
|
2262
|
-
*
|
|
2263
|
-
* Use of this source code is governed by an MIT-style license that can be
|
|
2264
|
-
* found in the LICENSE file at https://angular.io/license
|
|
2265
|
-
*/
|
|
2266
|
-
const INITIAL_VALUE = Symbol('INITIAL_VALUE');
|
|
2267
|
-
function prioritizedGuardValue() {
|
|
2268
|
-
return switchMap(obs => {
|
|
2269
|
-
return combineLatest(obs.map(o => o.pipe(take(1), startWith(INITIAL_VALUE))))
|
|
2270
|
-
.pipe(scan((acc, list) => {
|
|
2271
|
-
let isPending = false;
|
|
2272
|
-
return list.reduce((innerAcc, val, i) => {
|
|
2273
|
-
if (innerAcc !== INITIAL_VALUE)
|
|
2274
|
-
return innerAcc;
|
|
2275
|
-
// Toggle pending flag if any values haven't been set yet
|
|
2276
|
-
if (val === INITIAL_VALUE)
|
|
2277
|
-
isPending = true;
|
|
2278
|
-
// Any other return values are only valid if we haven't yet hit a pending
|
|
2279
|
-
// call. This guarantees that in the case of a guard at the bottom of the
|
|
2280
|
-
// tree that returns a redirect, we will wait for the higher priority
|
|
2281
|
-
// guard at the top to finish before performing the redirect.
|
|
2282
|
-
if (!isPending) {
|
|
2283
|
-
// Early return when we hit a `false` value as that should always
|
|
2284
|
-
// cancel navigation
|
|
2285
|
-
if (val === false)
|
|
2286
|
-
return val;
|
|
2287
|
-
if (i === list.length - 1 || isUrlTree(val)) {
|
|
2288
|
-
return val;
|
|
2289
|
-
}
|
|
2290
|
-
}
|
|
2291
|
-
return innerAcc;
|
|
2292
|
-
}, acc);
|
|
2293
|
-
}, INITIAL_VALUE), filter(item => item !== INITIAL_VALUE), map(item => isUrlTree(item) ? item : item === true), //
|
|
2294
|
-
take(1));
|
|
2295
|
-
});
|
|
2296
|
-
}
|
|
2297
|
-
|
|
2298
|
-
/**
|
|
2299
|
-
* @license
|
|
2300
|
-
* Copyright Google LLC All Rights Reserved.
|
|
2301
|
-
*
|
|
2302
|
-
* Use of this source code is governed by an MIT-style license that can be
|
|
2303
|
-
* found in the LICENSE file at https://angular.io/license
|
|
2304
|
-
*/
|
|
2305
|
-
/**
|
|
2306
|
-
* Store contextual information about a `RouterOutlet`
|
|
2307
|
-
*
|
|
2308
|
-
* @publicApi
|
|
2309
|
-
*/
|
|
2310
|
-
class OutletContext {
|
|
2311
|
-
constructor() {
|
|
2312
|
-
this.outlet = null;
|
|
2313
|
-
this.route = null;
|
|
2314
|
-
this.resolver = null;
|
|
2315
|
-
this.children = new ChildrenOutletContexts();
|
|
2316
|
-
this.attachRef = null;
|
|
2317
|
-
}
|
|
2318
|
-
}
|
|
2319
|
-
/**
|
|
2320
|
-
* Store contextual information about the children (= nested) `RouterOutlet`
|
|
2321
|
-
*
|
|
2322
|
-
* @publicApi
|
|
2323
|
-
*/
|
|
2324
|
-
class ChildrenOutletContexts {
|
|
2325
|
-
constructor() {
|
|
2326
|
-
// contexts for child outlets, by name.
|
|
2327
|
-
this.contexts = new Map();
|
|
2328
|
-
}
|
|
2329
|
-
/** Called when a `RouterOutlet` directive is instantiated */
|
|
2330
|
-
onChildOutletCreated(childName, outlet) {
|
|
2331
|
-
const context = this.getOrCreateContext(childName);
|
|
2332
|
-
context.outlet = outlet;
|
|
2333
|
-
this.contexts.set(childName, context);
|
|
2334
|
-
}
|
|
2335
|
-
/**
|
|
2336
|
-
* Called when a `RouterOutlet` directive is destroyed.
|
|
2337
|
-
* We need to keep the context as the outlet could be destroyed inside a NgIf and might be
|
|
2338
|
-
* re-created later.
|
|
2339
|
-
*/
|
|
2340
|
-
onChildOutletDestroyed(childName) {
|
|
2341
|
-
const context = this.getContext(childName);
|
|
2342
|
-
if (context) {
|
|
2343
|
-
context.outlet = null;
|
|
2344
|
-
context.attachRef = null;
|
|
2345
|
-
}
|
|
2346
|
-
}
|
|
2347
|
-
/**
|
|
2348
|
-
* Called when the corresponding route is deactivated during navigation.
|
|
2349
|
-
* Because the component get destroyed, all children outlet are destroyed.
|
|
2350
|
-
*/
|
|
2351
|
-
onOutletDeactivated() {
|
|
2352
|
-
const contexts = this.contexts;
|
|
2353
|
-
this.contexts = new Map();
|
|
2354
|
-
return contexts;
|
|
2355
|
-
}
|
|
2356
|
-
onOutletReAttached(contexts) {
|
|
2357
|
-
this.contexts = contexts;
|
|
2358
|
-
}
|
|
2359
|
-
getOrCreateContext(childName) {
|
|
2360
|
-
let context = this.getContext(childName);
|
|
2361
|
-
if (!context) {
|
|
2362
|
-
context = new OutletContext();
|
|
2363
|
-
this.contexts.set(childName, context);
|
|
2364
|
-
}
|
|
2365
|
-
return context;
|
|
2366
|
-
}
|
|
2367
|
-
getContext(childName) {
|
|
2368
|
-
return this.contexts.get(childName) || null;
|
|
2369
|
-
}
|
|
2370
|
-
}
|
|
2371
|
-
|
|
2372
|
-
/**
|
|
2373
|
-
* @license
|
|
2374
|
-
* Copyright Google LLC All Rights Reserved.
|
|
2375
|
-
*
|
|
2376
|
-
* Use of this source code is governed by an MIT-style license that can be
|
|
2377
|
-
* found in the LICENSE file at https://angular.io/license
|
|
2378
|
-
*/
|
|
2379
|
-
/**
|
|
2380
|
-
* @description
|
|
2381
|
-
*
|
|
2382
|
-
* Acts as a placeholder that Angular dynamically fills based on the current router state.
|
|
2383
|
-
*
|
|
2384
|
-
* Each outlet can have a unique name, determined by the optional `name` attribute.
|
|
2385
|
-
* The name cannot be set or changed dynamically. If not set, default value is "primary".
|
|
2109
|
+
* Each outlet can have a unique name, determined by the optional `name` attribute.
|
|
2110
|
+
* The name cannot be set or changed dynamically. If not set, default value is "primary".
|
|
2386
2111
|
*
|
|
2387
2112
|
* ```
|
|
2388
2113
|
* <router-outlet></router-outlet>
|
|
@@ -2428,11 +2153,11 @@ class ChildrenOutletContexts {
|
|
|
2428
2153
|
* @publicApi
|
|
2429
2154
|
*/
|
|
2430
2155
|
class RouterOutlet {
|
|
2431
|
-
constructor(parentContexts, location,
|
|
2156
|
+
constructor(parentContexts, location, name, changeDetector, environmentInjector) {
|
|
2432
2157
|
this.parentContexts = parentContexts;
|
|
2433
2158
|
this.location = location;
|
|
2434
|
-
this.resolver = resolver;
|
|
2435
2159
|
this.changeDetector = changeDetector;
|
|
2160
|
+
this.environmentInjector = environmentInjector;
|
|
2436
2161
|
this.activated = null;
|
|
2437
2162
|
this._activatedRoute = null;
|
|
2438
2163
|
this.activateEvents = new EventEmitter();
|
|
@@ -2467,7 +2192,7 @@ class RouterOutlet {
|
|
|
2467
2192
|
}
|
|
2468
2193
|
else {
|
|
2469
2194
|
// otherwise the component defined in the configuration is created
|
|
2470
|
-
this.activateWith(context.route, context.
|
|
2195
|
+
this.activateWith(context.route, context.injector);
|
|
2471
2196
|
}
|
|
2472
2197
|
}
|
|
2473
2198
|
}
|
|
@@ -2526,34 +2251,40 @@ class RouterOutlet {
|
|
|
2526
2251
|
this.deactivateEvents.emit(c);
|
|
2527
2252
|
}
|
|
2528
2253
|
}
|
|
2529
|
-
activateWith(activatedRoute,
|
|
2254
|
+
activateWith(activatedRoute, resolverOrInjector) {
|
|
2530
2255
|
if (this.isActivated) {
|
|
2531
2256
|
throw new Error('Cannot activate an already activated outlet');
|
|
2532
2257
|
}
|
|
2533
2258
|
this._activatedRoute = activatedRoute;
|
|
2259
|
+
const location = this.location;
|
|
2534
2260
|
const snapshot = activatedRoute._futureSnapshot;
|
|
2535
2261
|
const component = snapshot.routeConfig.component;
|
|
2536
|
-
resolver = resolver || this.resolver;
|
|
2537
|
-
const factory = resolver.resolveComponentFactory(component);
|
|
2538
2262
|
const childContexts = this.parentContexts.getOrCreateContext(this.name).children;
|
|
2539
|
-
const injector = new OutletInjector(activatedRoute, childContexts,
|
|
2540
|
-
|
|
2263
|
+
const injector = new OutletInjector(activatedRoute, childContexts, location.injector);
|
|
2264
|
+
if (resolverOrInjector && isComponentFactoryResolver(resolverOrInjector)) {
|
|
2265
|
+
const factory = resolverOrInjector.resolveComponentFactory(component);
|
|
2266
|
+
this.activated = location.createComponent(factory, location.length, injector);
|
|
2267
|
+
}
|
|
2268
|
+
else {
|
|
2269
|
+
const environmentInjector = resolverOrInjector !== null && resolverOrInjector !== void 0 ? resolverOrInjector : this.environmentInjector;
|
|
2270
|
+
this.activated = location.createComponent(component, { index: location.length, injector, environmentInjector });
|
|
2271
|
+
}
|
|
2541
2272
|
// Calling `markForCheck` to make sure we will run the change detection when the
|
|
2542
2273
|
// `RouterOutlet` is inside a `ChangeDetectionStrategy.OnPush` component.
|
|
2543
2274
|
this.changeDetector.markForCheck();
|
|
2544
2275
|
this.activateEvents.emit(this.activated.instance);
|
|
2545
2276
|
}
|
|
2546
2277
|
}
|
|
2547
|
-
RouterOutlet.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
2548
|
-
RouterOutlet.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
2549
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
2278
|
+
RouterOutlet.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterOutlet, deps: [{ token: ChildrenOutletContexts }, { token: i0.ViewContainerRef }, { token: 'name', attribute: true }, { token: i0.ChangeDetectorRef }, { token: i0.EnvironmentInjector }], target: i0.ɵɵFactoryTarget.Directive });
|
|
2279
|
+
RouterOutlet.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.14", type: RouterOutlet, selector: "router-outlet", outputs: { activateEvents: "activate", deactivateEvents: "deactivate", attachEvents: "attach", detachEvents: "detach" }, exportAs: ["outlet"], ngImport: i0 });
|
|
2280
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterOutlet, decorators: [{
|
|
2550
2281
|
type: Directive,
|
|
2551
2282
|
args: [{ selector: 'router-outlet', exportAs: 'outlet' }]
|
|
2552
2283
|
}], ctorParameters: function () {
|
|
2553
|
-
return [{ type: ChildrenOutletContexts }, { type: i0.ViewContainerRef }, { type:
|
|
2284
|
+
return [{ type: ChildrenOutletContexts }, { type: i0.ViewContainerRef }, { type: undefined, decorators: [{
|
|
2554
2285
|
type: Attribute,
|
|
2555
2286
|
args: ['name']
|
|
2556
|
-
}] }, { type: i0.ChangeDetectorRef }];
|
|
2287
|
+
}] }, { type: i0.ChangeDetectorRef }, { type: i0.EnvironmentInjector }];
|
|
2557
2288
|
}, propDecorators: { activateEvents: [{
|
|
2558
2289
|
type: Output,
|
|
2559
2290
|
args: ['activate']
|
|
@@ -2573,14 +2304,378 @@ class OutletInjector {
|
|
|
2573
2304
|
this.childContexts = childContexts;
|
|
2574
2305
|
this.parent = parent;
|
|
2575
2306
|
}
|
|
2576
|
-
get(token, notFoundValue) {
|
|
2577
|
-
if (token === ActivatedRoute) {
|
|
2578
|
-
return this.route;
|
|
2307
|
+
get(token, notFoundValue) {
|
|
2308
|
+
if (token === ActivatedRoute) {
|
|
2309
|
+
return this.route;
|
|
2310
|
+
}
|
|
2311
|
+
if (token === ChildrenOutletContexts) {
|
|
2312
|
+
return this.childContexts;
|
|
2313
|
+
}
|
|
2314
|
+
return this.parent.get(token, notFoundValue);
|
|
2315
|
+
}
|
|
2316
|
+
}
|
|
2317
|
+
function isComponentFactoryResolver(item) {
|
|
2318
|
+
return !!item.resolveComponentFactory;
|
|
2319
|
+
}
|
|
2320
|
+
|
|
2321
|
+
/**
|
|
2322
|
+
* @license
|
|
2323
|
+
* Copyright Google LLC All Rights Reserved.
|
|
2324
|
+
*
|
|
2325
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
2326
|
+
* found in the LICENSE file at https://angular.io/license
|
|
2327
|
+
*/
|
|
2328
|
+
/**
|
|
2329
|
+
* This component is used internally within the router to be a placeholder when an empty
|
|
2330
|
+
* router-outlet is needed. For example, with a config such as:
|
|
2331
|
+
*
|
|
2332
|
+
* `{path: 'parent', outlet: 'nav', children: [...]}`
|
|
2333
|
+
*
|
|
2334
|
+
* In order to render, there needs to be a component on this config, which will default
|
|
2335
|
+
* to this `EmptyOutletComponent`.
|
|
2336
|
+
*/
|
|
2337
|
+
class ɵEmptyOutletComponent {
|
|
2338
|
+
}
|
|
2339
|
+
ɵEmptyOutletComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: ɵEmptyOutletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2340
|
+
ɵEmptyOutletComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "14.0.0-next.14", type: ɵEmptyOutletComponent, selector: "ng-component", ngImport: i0, template: `<router-outlet></router-outlet>`, isInline: true, dependencies: [{ kind: "directive", type: RouterOutlet, selector: "router-outlet", outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }] });
|
|
2341
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: ɵEmptyOutletComponent, decorators: [{
|
|
2342
|
+
type: Component,
|
|
2343
|
+
args: [{ template: `<router-outlet></router-outlet>` }]
|
|
2344
|
+
}] });
|
|
2345
|
+
|
|
2346
|
+
/**
|
|
2347
|
+
* @license
|
|
2348
|
+
* Copyright Google LLC All Rights Reserved.
|
|
2349
|
+
*
|
|
2350
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
2351
|
+
* found in the LICENSE file at https://angular.io/license
|
|
2352
|
+
*/
|
|
2353
|
+
function getLoadedRoutes(route) {
|
|
2354
|
+
return route._loadedRoutes;
|
|
2355
|
+
}
|
|
2356
|
+
function getLoadedInjector(route) {
|
|
2357
|
+
return route._loadedInjector;
|
|
2358
|
+
}
|
|
2359
|
+
function getProvidersInjector(route) {
|
|
2360
|
+
return route._injector;
|
|
2361
|
+
}
|
|
2362
|
+
function validateConfig(config, parentPath = '') {
|
|
2363
|
+
// forEach doesn't iterate undefined values
|
|
2364
|
+
for (let i = 0; i < config.length; i++) {
|
|
2365
|
+
const route = config[i];
|
|
2366
|
+
const fullPath = getFullPath(parentPath, route);
|
|
2367
|
+
validateNode(route, fullPath);
|
|
2368
|
+
}
|
|
2369
|
+
}
|
|
2370
|
+
function validateNode(route, fullPath) {
|
|
2371
|
+
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
2372
|
+
if (!route) {
|
|
2373
|
+
throw new Error(`
|
|
2374
|
+
Invalid configuration of route '${fullPath}': Encountered undefined route.
|
|
2375
|
+
The reason might be an extra comma.
|
|
2376
|
+
|
|
2377
|
+
Example:
|
|
2378
|
+
const routes: Routes = [
|
|
2379
|
+
{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },
|
|
2380
|
+
{ path: 'dashboard', component: DashboardComponent },, << two commas
|
|
2381
|
+
{ path: 'detail/:id', component: HeroDetailComponent }
|
|
2382
|
+
];
|
|
2383
|
+
`);
|
|
2384
|
+
}
|
|
2385
|
+
if (Array.isArray(route)) {
|
|
2386
|
+
throw new Error(`Invalid configuration of route '${fullPath}': Array cannot be specified`);
|
|
2387
|
+
}
|
|
2388
|
+
if (!route.component && !route.children && !route.loadChildren &&
|
|
2389
|
+
(route.outlet && route.outlet !== PRIMARY_OUTLET)) {
|
|
2390
|
+
throw new Error(`Invalid configuration of route '${fullPath}': a componentless route without children or loadChildren cannot have a named outlet set`);
|
|
2391
|
+
}
|
|
2392
|
+
if (route.redirectTo && route.children) {
|
|
2393
|
+
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and children cannot be used together`);
|
|
2394
|
+
}
|
|
2395
|
+
if (route.redirectTo && route.loadChildren) {
|
|
2396
|
+
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and loadChildren cannot be used together`);
|
|
2397
|
+
}
|
|
2398
|
+
if (route.children && route.loadChildren) {
|
|
2399
|
+
throw new Error(`Invalid configuration of route '${fullPath}': children and loadChildren cannot be used together`);
|
|
2400
|
+
}
|
|
2401
|
+
if (route.redirectTo && route.component) {
|
|
2402
|
+
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and component cannot be used together`);
|
|
2403
|
+
}
|
|
2404
|
+
if (route.redirectTo && route.canActivate) {
|
|
2405
|
+
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and canActivate cannot be used together. Redirects happen before activation ` +
|
|
2406
|
+
`so canActivate will never be executed.`);
|
|
2407
|
+
}
|
|
2408
|
+
if (route.path && route.matcher) {
|
|
2409
|
+
throw new Error(`Invalid configuration of route '${fullPath}': path and matcher cannot be used together`);
|
|
2410
|
+
}
|
|
2411
|
+
if (route.redirectTo === void 0 && !route.component && !route.children && !route.loadChildren) {
|
|
2412
|
+
throw new Error(`Invalid configuration of route '${fullPath}'. One of the following must be provided: component, redirectTo, children or loadChildren`);
|
|
2413
|
+
}
|
|
2414
|
+
if (route.path === void 0 && route.matcher === void 0) {
|
|
2415
|
+
throw new Error(`Invalid configuration of route '${fullPath}': routes must have either a path or a matcher specified`);
|
|
2416
|
+
}
|
|
2417
|
+
if (typeof route.path === 'string' && route.path.charAt(0) === '/') {
|
|
2418
|
+
throw new Error(`Invalid configuration of route '${fullPath}': path cannot start with a slash`);
|
|
2419
|
+
}
|
|
2420
|
+
if (route.path === '' && route.redirectTo !== void 0 && route.pathMatch === void 0) {
|
|
2421
|
+
const exp = `The default value of 'pathMatch' is 'prefix', but often the intent is to use 'full'.`;
|
|
2422
|
+
throw new Error(`Invalid configuration of route '{path: "${fullPath}", redirectTo: "${route.redirectTo}"}': please provide 'pathMatch'. ${exp}`);
|
|
2423
|
+
}
|
|
2424
|
+
}
|
|
2425
|
+
if (route.children) {
|
|
2426
|
+
validateConfig(route.children, fullPath);
|
|
2427
|
+
}
|
|
2428
|
+
}
|
|
2429
|
+
function getFullPath(parentPath, currentRoute) {
|
|
2430
|
+
if (!currentRoute) {
|
|
2431
|
+
return parentPath;
|
|
2432
|
+
}
|
|
2433
|
+
if (!parentPath && !currentRoute.path) {
|
|
2434
|
+
return '';
|
|
2435
|
+
}
|
|
2436
|
+
else if (parentPath && !currentRoute.path) {
|
|
2437
|
+
return `${parentPath}/`;
|
|
2438
|
+
}
|
|
2439
|
+
else if (!parentPath && currentRoute.path) {
|
|
2440
|
+
return currentRoute.path;
|
|
2441
|
+
}
|
|
2442
|
+
else {
|
|
2443
|
+
return `${parentPath}/${currentRoute.path}`;
|
|
2444
|
+
}
|
|
2445
|
+
}
|
|
2446
|
+
/**
|
|
2447
|
+
* Makes a copy of the config and adds any default required properties.
|
|
2448
|
+
*/
|
|
2449
|
+
function standardizeConfig(r) {
|
|
2450
|
+
const children = r.children && r.children.map(standardizeConfig);
|
|
2451
|
+
const c = children ? Object.assign(Object.assign({}, r), { children }) : Object.assign({}, r);
|
|
2452
|
+
if (!c.component && (children || c.loadChildren) && (c.outlet && c.outlet !== PRIMARY_OUTLET)) {
|
|
2453
|
+
c.component = ɵEmptyOutletComponent;
|
|
2454
|
+
}
|
|
2455
|
+
return c;
|
|
2456
|
+
}
|
|
2457
|
+
/** Returns the `route.outlet` or PRIMARY_OUTLET if none exists. */
|
|
2458
|
+
function getOutlet(route) {
|
|
2459
|
+
return route.outlet || PRIMARY_OUTLET;
|
|
2460
|
+
}
|
|
2461
|
+
/**
|
|
2462
|
+
* Sorts the `routes` such that the ones with an outlet matching `outletName` come first.
|
|
2463
|
+
* The order of the configs is otherwise preserved.
|
|
2464
|
+
*/
|
|
2465
|
+
function sortByMatchingOutlets(routes, outletName) {
|
|
2466
|
+
const sortedConfig = routes.filter(r => getOutlet(r) === outletName);
|
|
2467
|
+
sortedConfig.push(...routes.filter(r => getOutlet(r) !== outletName));
|
|
2468
|
+
return sortedConfig;
|
|
2469
|
+
}
|
|
2470
|
+
/**
|
|
2471
|
+
* Gets the first injector in the snapshot's parent tree.
|
|
2472
|
+
*
|
|
2473
|
+
* If the `Route` has a static list of providers, the returned injector will be the one created from
|
|
2474
|
+
* those. If it does not exist, the returned injector may come from the parents, which may be from a
|
|
2475
|
+
* loaded config or their static providers.
|
|
2476
|
+
*
|
|
2477
|
+
* Returns `null` if there is neither this nor any parents have a stored injector.
|
|
2478
|
+
*
|
|
2479
|
+
* Generally used for retrieving the injector to use for getting tokens for guards/resolvers and
|
|
2480
|
+
* also used for getting the correct injector to use for creating components.
|
|
2481
|
+
*/
|
|
2482
|
+
function getClosestRouteInjector(snapshot) {
|
|
2483
|
+
var _a;
|
|
2484
|
+
if (!snapshot)
|
|
2485
|
+
return null;
|
|
2486
|
+
// If the current route has its own injector, which is created from the static providers on the
|
|
2487
|
+
// route itself, we should use that. Otherwise, we start at the parent since we do not want to
|
|
2488
|
+
// include the lazy loaded injector from this route.
|
|
2489
|
+
if ((_a = snapshot.routeConfig) === null || _a === void 0 ? void 0 : _a._injector) {
|
|
2490
|
+
return snapshot.routeConfig._injector;
|
|
2491
|
+
}
|
|
2492
|
+
for (let s = snapshot.parent; s; s = s.parent) {
|
|
2493
|
+
const route = s.routeConfig;
|
|
2494
|
+
// Note that the order here is important. `_loadedInjector` stored on the route with
|
|
2495
|
+
// `loadChildren: () => NgModule` so it applies to child routes with priority. The `_injector`
|
|
2496
|
+
// is created from the static providers on that parent route, so it applies to the children as
|
|
2497
|
+
// well, but only if there is no lazy loaded NgModuleRef injector.
|
|
2498
|
+
if (route === null || route === void 0 ? void 0 : route._loadedInjector)
|
|
2499
|
+
return route._loadedInjector;
|
|
2500
|
+
if (route === null || route === void 0 ? void 0 : route._injector)
|
|
2501
|
+
return route._injector;
|
|
2502
|
+
}
|
|
2503
|
+
return null;
|
|
2504
|
+
}
|
|
2505
|
+
|
|
2506
|
+
/**
|
|
2507
|
+
* @license
|
|
2508
|
+
* Copyright Google LLC All Rights Reserved.
|
|
2509
|
+
*
|
|
2510
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
2511
|
+
* found in the LICENSE file at https://angular.io/license
|
|
2512
|
+
*/
|
|
2513
|
+
const activateRoutes = (rootContexts, routeReuseStrategy, forwardEvent) => map(t => {
|
|
2514
|
+
new ActivateRoutes(routeReuseStrategy, t.targetRouterState, t.currentRouterState, forwardEvent)
|
|
2515
|
+
.activate(rootContexts);
|
|
2516
|
+
return t;
|
|
2517
|
+
});
|
|
2518
|
+
class ActivateRoutes {
|
|
2519
|
+
constructor(routeReuseStrategy, futureState, currState, forwardEvent) {
|
|
2520
|
+
this.routeReuseStrategy = routeReuseStrategy;
|
|
2521
|
+
this.futureState = futureState;
|
|
2522
|
+
this.currState = currState;
|
|
2523
|
+
this.forwardEvent = forwardEvent;
|
|
2524
|
+
}
|
|
2525
|
+
activate(parentContexts) {
|
|
2526
|
+
const futureRoot = this.futureState._root;
|
|
2527
|
+
const currRoot = this.currState ? this.currState._root : null;
|
|
2528
|
+
this.deactivateChildRoutes(futureRoot, currRoot, parentContexts);
|
|
2529
|
+
advanceActivatedRoute(this.futureState.root);
|
|
2530
|
+
this.activateChildRoutes(futureRoot, currRoot, parentContexts);
|
|
2531
|
+
}
|
|
2532
|
+
// De-activate the child route that are not re-used for the future state
|
|
2533
|
+
deactivateChildRoutes(futureNode, currNode, contexts) {
|
|
2534
|
+
const children = nodeChildrenAsMap(currNode);
|
|
2535
|
+
// Recurse on the routes active in the future state to de-activate deeper children
|
|
2536
|
+
futureNode.children.forEach(futureChild => {
|
|
2537
|
+
const childOutletName = futureChild.value.outlet;
|
|
2538
|
+
this.deactivateRoutes(futureChild, children[childOutletName], contexts);
|
|
2539
|
+
delete children[childOutletName];
|
|
2540
|
+
});
|
|
2541
|
+
// De-activate the routes that will not be re-used
|
|
2542
|
+
forEach(children, (v, childName) => {
|
|
2543
|
+
this.deactivateRouteAndItsChildren(v, contexts);
|
|
2544
|
+
});
|
|
2545
|
+
}
|
|
2546
|
+
deactivateRoutes(futureNode, currNode, parentContext) {
|
|
2547
|
+
const future = futureNode.value;
|
|
2548
|
+
const curr = currNode ? currNode.value : null;
|
|
2549
|
+
if (future === curr) {
|
|
2550
|
+
// Reusing the node, check to see if the children need to be de-activated
|
|
2551
|
+
if (future.component) {
|
|
2552
|
+
// If we have a normal route, we need to go through an outlet.
|
|
2553
|
+
const context = parentContext.getContext(future.outlet);
|
|
2554
|
+
if (context) {
|
|
2555
|
+
this.deactivateChildRoutes(futureNode, currNode, context.children);
|
|
2556
|
+
}
|
|
2557
|
+
}
|
|
2558
|
+
else {
|
|
2559
|
+
// if we have a componentless route, we recurse but keep the same outlet map.
|
|
2560
|
+
this.deactivateChildRoutes(futureNode, currNode, parentContext);
|
|
2561
|
+
}
|
|
2562
|
+
}
|
|
2563
|
+
else {
|
|
2564
|
+
if (curr) {
|
|
2565
|
+
// Deactivate the current route which will not be re-used
|
|
2566
|
+
this.deactivateRouteAndItsChildren(currNode, parentContext);
|
|
2567
|
+
}
|
|
2568
|
+
}
|
|
2569
|
+
}
|
|
2570
|
+
deactivateRouteAndItsChildren(route, parentContexts) {
|
|
2571
|
+
// If there is no component, the Route is never attached to an outlet (because there is no
|
|
2572
|
+
// component to attach).
|
|
2573
|
+
if (route.value.component && this.routeReuseStrategy.shouldDetach(route.value.snapshot)) {
|
|
2574
|
+
this.detachAndStoreRouteSubtree(route, parentContexts);
|
|
2575
|
+
}
|
|
2576
|
+
else {
|
|
2577
|
+
this.deactivateRouteAndOutlet(route, parentContexts);
|
|
2578
|
+
}
|
|
2579
|
+
}
|
|
2580
|
+
detachAndStoreRouteSubtree(route, parentContexts) {
|
|
2581
|
+
const context = parentContexts.getContext(route.value.outlet);
|
|
2582
|
+
const contexts = context && route.value.component ? context.children : parentContexts;
|
|
2583
|
+
const children = nodeChildrenAsMap(route);
|
|
2584
|
+
for (const childOutlet of Object.keys(children)) {
|
|
2585
|
+
this.deactivateRouteAndItsChildren(children[childOutlet], contexts);
|
|
2586
|
+
}
|
|
2587
|
+
if (context && context.outlet) {
|
|
2588
|
+
const componentRef = context.outlet.detach();
|
|
2589
|
+
const contexts = context.children.onOutletDeactivated();
|
|
2590
|
+
this.routeReuseStrategy.store(route.value.snapshot, { componentRef, route, contexts });
|
|
2591
|
+
}
|
|
2592
|
+
}
|
|
2593
|
+
deactivateRouteAndOutlet(route, parentContexts) {
|
|
2594
|
+
const context = parentContexts.getContext(route.value.outlet);
|
|
2595
|
+
// The context could be `null` if we are on a componentless route but there may still be
|
|
2596
|
+
// children that need deactivating.
|
|
2597
|
+
const contexts = context && route.value.component ? context.children : parentContexts;
|
|
2598
|
+
const children = nodeChildrenAsMap(route);
|
|
2599
|
+
for (const childOutlet of Object.keys(children)) {
|
|
2600
|
+
this.deactivateRouteAndItsChildren(children[childOutlet], contexts);
|
|
2601
|
+
}
|
|
2602
|
+
if (context && context.outlet) {
|
|
2603
|
+
// Destroy the component
|
|
2604
|
+
context.outlet.deactivate();
|
|
2605
|
+
// Destroy the contexts for all the outlets that were in the component
|
|
2606
|
+
context.children.onOutletDeactivated();
|
|
2607
|
+
// Clear the information about the attached component on the context but keep the reference to
|
|
2608
|
+
// the outlet.
|
|
2609
|
+
context.attachRef = null;
|
|
2610
|
+
context.resolver = null;
|
|
2611
|
+
context.route = null;
|
|
2612
|
+
}
|
|
2613
|
+
}
|
|
2614
|
+
activateChildRoutes(futureNode, currNode, contexts) {
|
|
2615
|
+
const children = nodeChildrenAsMap(currNode);
|
|
2616
|
+
futureNode.children.forEach(c => {
|
|
2617
|
+
this.activateRoutes(c, children[c.value.outlet], contexts);
|
|
2618
|
+
this.forwardEvent(new ActivationEnd(c.value.snapshot));
|
|
2619
|
+
});
|
|
2620
|
+
if (futureNode.children.length) {
|
|
2621
|
+
this.forwardEvent(new ChildActivationEnd(futureNode.value.snapshot));
|
|
2622
|
+
}
|
|
2623
|
+
}
|
|
2624
|
+
activateRoutes(futureNode, currNode, parentContexts) {
|
|
2625
|
+
var _a;
|
|
2626
|
+
const future = futureNode.value;
|
|
2627
|
+
const curr = currNode ? currNode.value : null;
|
|
2628
|
+
advanceActivatedRoute(future);
|
|
2629
|
+
// reusing the node
|
|
2630
|
+
if (future === curr) {
|
|
2631
|
+
if (future.component) {
|
|
2632
|
+
// If we have a normal route, we need to go through an outlet.
|
|
2633
|
+
const context = parentContexts.getOrCreateContext(future.outlet);
|
|
2634
|
+
this.activateChildRoutes(futureNode, currNode, context.children);
|
|
2635
|
+
}
|
|
2636
|
+
else {
|
|
2637
|
+
// if we have a componentless route, we recurse but keep the same outlet map.
|
|
2638
|
+
this.activateChildRoutes(futureNode, currNode, parentContexts);
|
|
2639
|
+
}
|
|
2579
2640
|
}
|
|
2580
|
-
|
|
2581
|
-
|
|
2641
|
+
else {
|
|
2642
|
+
if (future.component) {
|
|
2643
|
+
// if we have a normal route, we need to place the component into the outlet and recurse.
|
|
2644
|
+
const context = parentContexts.getOrCreateContext(future.outlet);
|
|
2645
|
+
if (this.routeReuseStrategy.shouldAttach(future.snapshot)) {
|
|
2646
|
+
const stored = this.routeReuseStrategy.retrieve(future.snapshot);
|
|
2647
|
+
this.routeReuseStrategy.store(future.snapshot, null);
|
|
2648
|
+
context.children.onOutletReAttached(stored.contexts);
|
|
2649
|
+
context.attachRef = stored.componentRef;
|
|
2650
|
+
context.route = stored.route.value;
|
|
2651
|
+
if (context.outlet) {
|
|
2652
|
+
// Attach right away when the outlet has already been instantiated
|
|
2653
|
+
// Otherwise attach from `RouterOutlet.ngOnInit` when it is instantiated
|
|
2654
|
+
context.outlet.attach(stored.componentRef, stored.route.value);
|
|
2655
|
+
}
|
|
2656
|
+
advanceActivatedRoute(stored.route.value);
|
|
2657
|
+
this.activateChildRoutes(futureNode, null, context.children);
|
|
2658
|
+
}
|
|
2659
|
+
else {
|
|
2660
|
+
const injector = getClosestRouteInjector(future.snapshot);
|
|
2661
|
+
const cmpFactoryResolver = (_a = injector === null || injector === void 0 ? void 0 : injector.get(ComponentFactoryResolver)) !== null && _a !== void 0 ? _a : null;
|
|
2662
|
+
context.attachRef = null;
|
|
2663
|
+
context.route = future;
|
|
2664
|
+
context.resolver = cmpFactoryResolver;
|
|
2665
|
+
context.injector = injector;
|
|
2666
|
+
if (context.outlet) {
|
|
2667
|
+
// Activate the outlet when it has already been instantiated
|
|
2668
|
+
// Otherwise it will get activated from its `ngOnInit` when instantiated
|
|
2669
|
+
context.outlet.activateWith(future, context.injector);
|
|
2670
|
+
}
|
|
2671
|
+
this.activateChildRoutes(futureNode, null, context.children);
|
|
2672
|
+
}
|
|
2673
|
+
}
|
|
2674
|
+
else {
|
|
2675
|
+
// if we have a componentless route, we recurse but keep the same outlet map.
|
|
2676
|
+
this.activateChildRoutes(futureNode, null, parentContexts);
|
|
2677
|
+
}
|
|
2582
2678
|
}
|
|
2583
|
-
return this.parent.get(token, notFoundValue);
|
|
2584
2679
|
}
|
|
2585
2680
|
}
|
|
2586
2681
|
|
|
@@ -2592,22 +2687,39 @@ class OutletInjector {
|
|
|
2592
2687
|
* found in the LICENSE file at https://angular.io/license
|
|
2593
2688
|
*/
|
|
2594
2689
|
/**
|
|
2595
|
-
*
|
|
2596
|
-
* router-outlet is needed. For example, with a config such as:
|
|
2690
|
+
* Simple function check, but generic so type inference will flow. Example:
|
|
2597
2691
|
*
|
|
2598
|
-
*
|
|
2692
|
+
* function product(a: number, b: number) {
|
|
2693
|
+
* return a * b;
|
|
2694
|
+
* }
|
|
2599
2695
|
*
|
|
2600
|
-
*
|
|
2601
|
-
*
|
|
2696
|
+
* if (isFunction<product>(fn)) {
|
|
2697
|
+
* return fn(1, 2);
|
|
2698
|
+
* } else {
|
|
2699
|
+
* throw "Must provide the `product` function";
|
|
2700
|
+
* }
|
|
2602
2701
|
*/
|
|
2603
|
-
|
|
2702
|
+
function isFunction(v) {
|
|
2703
|
+
return typeof v === 'function';
|
|
2704
|
+
}
|
|
2705
|
+
function isBoolean(v) {
|
|
2706
|
+
return typeof v === 'boolean';
|
|
2707
|
+
}
|
|
2708
|
+
function isUrlTree(v) {
|
|
2709
|
+
return v instanceof UrlTree;
|
|
2710
|
+
}
|
|
2711
|
+
function isCanLoad(guard) {
|
|
2712
|
+
return guard && isFunction(guard.canLoad);
|
|
2713
|
+
}
|
|
2714
|
+
function isCanActivate(guard) {
|
|
2715
|
+
return guard && isFunction(guard.canActivate);
|
|
2716
|
+
}
|
|
2717
|
+
function isCanActivateChild(guard) {
|
|
2718
|
+
return guard && isFunction(guard.canActivateChild);
|
|
2719
|
+
}
|
|
2720
|
+
function isCanDeactivate(guard) {
|
|
2721
|
+
return guard && isFunction(guard.canDeactivate);
|
|
2604
2722
|
}
|
|
2605
|
-
ɵEmptyOutletComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: ɵEmptyOutletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2606
|
-
ɵEmptyOutletComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "14.0.0-next.13", type: ɵEmptyOutletComponent, selector: "ng-component", ngImport: i0, template: `<router-outlet></router-outlet>`, isInline: true, directives: [{ type: RouterOutlet, selector: "router-outlet", outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }] });
|
|
2607
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: ɵEmptyOutletComponent, decorators: [{
|
|
2608
|
-
type: Component,
|
|
2609
|
-
args: [{ template: `<router-outlet></router-outlet>` }]
|
|
2610
|
-
}] });
|
|
2611
2723
|
|
|
2612
2724
|
/**
|
|
2613
2725
|
* @license
|
|
@@ -2616,113 +2728,36 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.13",
|
|
|
2616
2728
|
* Use of this source code is governed by an MIT-style license that can be
|
|
2617
2729
|
* found in the LICENSE file at https://angular.io/license
|
|
2618
2730
|
*/
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
if (route.redirectTo && route.children) {
|
|
2650
|
-
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and children cannot be used together`);
|
|
2651
|
-
}
|
|
2652
|
-
if (route.redirectTo && route.loadChildren) {
|
|
2653
|
-
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and loadChildren cannot be used together`);
|
|
2654
|
-
}
|
|
2655
|
-
if (route.children && route.loadChildren) {
|
|
2656
|
-
throw new Error(`Invalid configuration of route '${fullPath}': children and loadChildren cannot be used together`);
|
|
2657
|
-
}
|
|
2658
|
-
if (route.redirectTo && route.component) {
|
|
2659
|
-
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and component cannot be used together`);
|
|
2660
|
-
}
|
|
2661
|
-
if (route.redirectTo && route.canActivate) {
|
|
2662
|
-
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and canActivate cannot be used together. Redirects happen before activation ` +
|
|
2663
|
-
`so canActivate will never be executed.`);
|
|
2664
|
-
}
|
|
2665
|
-
if (route.path && route.matcher) {
|
|
2666
|
-
throw new Error(`Invalid configuration of route '${fullPath}': path and matcher cannot be used together`);
|
|
2667
|
-
}
|
|
2668
|
-
if (route.redirectTo === void 0 && !route.component && !route.children && !route.loadChildren) {
|
|
2669
|
-
throw new Error(`Invalid configuration of route '${fullPath}'. One of the following must be provided: component, redirectTo, children or loadChildren`);
|
|
2670
|
-
}
|
|
2671
|
-
if (route.path === void 0 && route.matcher === void 0) {
|
|
2672
|
-
throw new Error(`Invalid configuration of route '${fullPath}': routes must have either a path or a matcher specified`);
|
|
2673
|
-
}
|
|
2674
|
-
if (typeof route.path === 'string' && route.path.charAt(0) === '/') {
|
|
2675
|
-
throw new Error(`Invalid configuration of route '${fullPath}': path cannot start with a slash`);
|
|
2676
|
-
}
|
|
2677
|
-
if (route.path === '' && route.redirectTo !== void 0 && route.pathMatch === void 0) {
|
|
2678
|
-
const exp = `The default value of 'pathMatch' is 'prefix', but often the intent is to use 'full'.`;
|
|
2679
|
-
throw new Error(`Invalid configuration of route '{path: "${fullPath}", redirectTo: "${route.redirectTo}"}': please provide 'pathMatch'. ${exp}`);
|
|
2680
|
-
}
|
|
2681
|
-
}
|
|
2682
|
-
if (route.children) {
|
|
2683
|
-
validateConfig(route.children, fullPath);
|
|
2684
|
-
}
|
|
2685
|
-
}
|
|
2686
|
-
function getFullPath(parentPath, currentRoute) {
|
|
2687
|
-
if (!currentRoute) {
|
|
2688
|
-
return parentPath;
|
|
2689
|
-
}
|
|
2690
|
-
if (!parentPath && !currentRoute.path) {
|
|
2691
|
-
return '';
|
|
2692
|
-
}
|
|
2693
|
-
else if (parentPath && !currentRoute.path) {
|
|
2694
|
-
return `${parentPath}/`;
|
|
2695
|
-
}
|
|
2696
|
-
else if (!parentPath && currentRoute.path) {
|
|
2697
|
-
return currentRoute.path;
|
|
2698
|
-
}
|
|
2699
|
-
else {
|
|
2700
|
-
return `${parentPath}/${currentRoute.path}`;
|
|
2701
|
-
}
|
|
2702
|
-
}
|
|
2703
|
-
/**
|
|
2704
|
-
* Makes a copy of the config and adds any default required properties.
|
|
2705
|
-
*/
|
|
2706
|
-
function standardizeConfig(r) {
|
|
2707
|
-
const children = r.children && r.children.map(standardizeConfig);
|
|
2708
|
-
const c = children ? Object.assign(Object.assign({}, r), { children }) : Object.assign({}, r);
|
|
2709
|
-
if (!c.component && (children || c.loadChildren) && (c.outlet && c.outlet !== PRIMARY_OUTLET)) {
|
|
2710
|
-
c.component = ɵEmptyOutletComponent;
|
|
2711
|
-
}
|
|
2712
|
-
return c;
|
|
2713
|
-
}
|
|
2714
|
-
/** Returns the `route.outlet` or PRIMARY_OUTLET if none exists. */
|
|
2715
|
-
function getOutlet(route) {
|
|
2716
|
-
return route.outlet || PRIMARY_OUTLET;
|
|
2717
|
-
}
|
|
2718
|
-
/**
|
|
2719
|
-
* Sorts the `routes` such that the ones with an outlet matching `outletName` come first.
|
|
2720
|
-
* The order of the configs is otherwise preserved.
|
|
2721
|
-
*/
|
|
2722
|
-
function sortByMatchingOutlets(routes, outletName) {
|
|
2723
|
-
const sortedConfig = routes.filter(r => getOutlet(r) === outletName);
|
|
2724
|
-
sortedConfig.push(...routes.filter(r => getOutlet(r) !== outletName));
|
|
2725
|
-
return sortedConfig;
|
|
2731
|
+
const INITIAL_VALUE = Symbol('INITIAL_VALUE');
|
|
2732
|
+
function prioritizedGuardValue() {
|
|
2733
|
+
return switchMap(obs => {
|
|
2734
|
+
return combineLatest(obs.map(o => o.pipe(take(1), startWith(INITIAL_VALUE))))
|
|
2735
|
+
.pipe(scan((acc, list) => {
|
|
2736
|
+
let isPending = false;
|
|
2737
|
+
return list.reduce((innerAcc, val, i) => {
|
|
2738
|
+
if (innerAcc !== INITIAL_VALUE)
|
|
2739
|
+
return innerAcc;
|
|
2740
|
+
// Toggle pending flag if any values haven't been set yet
|
|
2741
|
+
if (val === INITIAL_VALUE)
|
|
2742
|
+
isPending = true;
|
|
2743
|
+
// Any other return values are only valid if we haven't yet hit a pending
|
|
2744
|
+
// call. This guarantees that in the case of a guard at the bottom of the
|
|
2745
|
+
// tree that returns a redirect, we will wait for the higher priority
|
|
2746
|
+
// guard at the top to finish before performing the redirect.
|
|
2747
|
+
if (!isPending) {
|
|
2748
|
+
// Early return when we hit a `false` value as that should always
|
|
2749
|
+
// cancel navigation
|
|
2750
|
+
if (val === false)
|
|
2751
|
+
return val;
|
|
2752
|
+
if (i === list.length - 1 || isUrlTree(val)) {
|
|
2753
|
+
return val;
|
|
2754
|
+
}
|
|
2755
|
+
}
|
|
2756
|
+
return innerAcc;
|
|
2757
|
+
}, acc);
|
|
2758
|
+
}, INITIAL_VALUE), filter(item => item !== INITIAL_VALUE), map(item => isUrlTree(item) ? item : item === true), //
|
|
2759
|
+
take(1));
|
|
2760
|
+
});
|
|
2726
2761
|
}
|
|
2727
2762
|
|
|
2728
2763
|
/**
|
|
@@ -2903,17 +2938,17 @@ function canLoadFails(route) {
|
|
|
2903
2938
|
*
|
|
2904
2939
|
* Lazy modules are loaded along the way.
|
|
2905
2940
|
*/
|
|
2906
|
-
function applyRedirects$1(
|
|
2907
|
-
return new ApplyRedirects(
|
|
2941
|
+
function applyRedirects$1(injector, configLoader, urlSerializer, urlTree, config) {
|
|
2942
|
+
return new ApplyRedirects(injector, configLoader, urlSerializer, urlTree, config).apply();
|
|
2908
2943
|
}
|
|
2909
2944
|
class ApplyRedirects {
|
|
2910
|
-
constructor(
|
|
2945
|
+
constructor(injector, configLoader, urlSerializer, urlTree, config) {
|
|
2946
|
+
this.injector = injector;
|
|
2911
2947
|
this.configLoader = configLoader;
|
|
2912
2948
|
this.urlSerializer = urlSerializer;
|
|
2913
2949
|
this.urlTree = urlTree;
|
|
2914
2950
|
this.config = config;
|
|
2915
2951
|
this.allowRedirects = true;
|
|
2916
|
-
this.ngModule = moduleInjector.get(NgModuleRef);
|
|
2917
2952
|
}
|
|
2918
2953
|
apply() {
|
|
2919
2954
|
const splitGroup = split(this.urlTree.root, [], [], this.config).segmentGroup;
|
|
@@ -2924,7 +2959,7 @@ class ApplyRedirects {
|
|
|
2924
2959
|
// them. We should be able to remove this logic as a "breaking change" but should do some more
|
|
2925
2960
|
// investigation into the failures first.
|
|
2926
2961
|
const rootSegmentGroup = new UrlSegmentGroup(splitGroup.segments, splitGroup.children);
|
|
2927
|
-
const expanded$ = this.expandSegmentGroup(this.
|
|
2962
|
+
const expanded$ = this.expandSegmentGroup(this.injector, this.config, rootSegmentGroup, PRIMARY_OUTLET);
|
|
2928
2963
|
const urlTrees$ = expanded$.pipe(map((rootSegmentGroup) => {
|
|
2929
2964
|
return this.createUrlTree(squashSegmentGroup(rootSegmentGroup), this.urlTree.queryParams, this.urlTree.fragment);
|
|
2930
2965
|
}));
|
|
@@ -2943,7 +2978,7 @@ class ApplyRedirects {
|
|
|
2943
2978
|
}));
|
|
2944
2979
|
}
|
|
2945
2980
|
match(tree) {
|
|
2946
|
-
const expanded$ = this.expandSegmentGroup(this.
|
|
2981
|
+
const expanded$ = this.expandSegmentGroup(this.injector, this.config, tree.root, PRIMARY_OUTLET);
|
|
2947
2982
|
const mapped$ = expanded$.pipe(map((rootSegmentGroup) => {
|
|
2948
2983
|
return this.createUrlTree(squashSegmentGroup(rootSegmentGroup), tree.queryParams, tree.fragment);
|
|
2949
2984
|
}));
|
|
@@ -2963,15 +2998,15 @@ class ApplyRedirects {
|
|
|
2963
2998
|
rootCandidate;
|
|
2964
2999
|
return new UrlTree(root, queryParams, fragment);
|
|
2965
3000
|
}
|
|
2966
|
-
expandSegmentGroup(
|
|
3001
|
+
expandSegmentGroup(injector, routes, segmentGroup, outlet) {
|
|
2967
3002
|
if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) {
|
|
2968
|
-
return this.expandChildren(
|
|
3003
|
+
return this.expandChildren(injector, routes, segmentGroup)
|
|
2969
3004
|
.pipe(map((children) => new UrlSegmentGroup([], children)));
|
|
2970
3005
|
}
|
|
2971
|
-
return this.expandSegment(
|
|
3006
|
+
return this.expandSegment(injector, segmentGroup, routes, segmentGroup.segments, outlet, true);
|
|
2972
3007
|
}
|
|
2973
3008
|
// Recursively expand segment groups for all the child outlets
|
|
2974
|
-
expandChildren(
|
|
3009
|
+
expandChildren(injector, routes, segmentGroup) {
|
|
2975
3010
|
// Expand outlets one at a time, starting with the primary outlet. We need to do it this way
|
|
2976
3011
|
// because an absolute redirect from the primary outlet takes precedence.
|
|
2977
3012
|
const childOutlets = [];
|
|
@@ -2990,16 +3025,26 @@ class ApplyRedirects {
|
|
|
2990
3025
|
// first, followed by routes for other outlets, which might match if they have an
|
|
2991
3026
|
// empty path.
|
|
2992
3027
|
const sortedRoutes = sortByMatchingOutlets(routes, childOutlet);
|
|
2993
|
-
return this.expandSegmentGroup(
|
|
3028
|
+
return this.expandSegmentGroup(injector, sortedRoutes, child, childOutlet)
|
|
2994
3029
|
.pipe(map(s => ({ segment: s, outlet: childOutlet })));
|
|
2995
3030
|
}), scan((children, expandedChild) => {
|
|
2996
3031
|
children[expandedChild.outlet] = expandedChild.segment;
|
|
2997
3032
|
return children;
|
|
2998
3033
|
}, {}), last$1());
|
|
2999
3034
|
}
|
|
3000
|
-
expandSegment(
|
|
3001
|
-
return from(routes).pipe(concatMap(
|
|
3002
|
-
|
|
3035
|
+
expandSegment(injector, segmentGroup, routes, segments, outlet, allowRedirects) {
|
|
3036
|
+
return from(routes).pipe(concatMap(r => {
|
|
3037
|
+
var _a;
|
|
3038
|
+
if (r.providers && !r._injector) {
|
|
3039
|
+
r._injector = createEnvironmentInjector(r.providers, injector, `Route: ${r.path}`);
|
|
3040
|
+
}
|
|
3041
|
+
// We specifically _do not_ want to include the _loadedInjector here. The loaded injector
|
|
3042
|
+
// only applies to the route's children, not the route itself. Note that this distinction
|
|
3043
|
+
// only applies here to any tokens we try to retrieve during this phase. At the moment,
|
|
3044
|
+
// that only includes `canLoad`, which won't run again once the child module is loaded. As
|
|
3045
|
+
// a result, this makes no difference right now, but could in the future if there are more
|
|
3046
|
+
// actions here that need DI (for example, a canMatch guard).
|
|
3047
|
+
const expanded$ = this.expandSegmentAgainstRoute((_a = r._injector) !== null && _a !== void 0 ? _a : injector, segmentGroup, routes, r, segments, outlet, allowRedirects);
|
|
3003
3048
|
return expanded$.pipe(catchError((e) => {
|
|
3004
3049
|
if (e instanceof NoMatch$1) {
|
|
3005
3050
|
return of(null);
|
|
@@ -3016,35 +3061,35 @@ class ApplyRedirects {
|
|
|
3016
3061
|
throw e;
|
|
3017
3062
|
}));
|
|
3018
3063
|
}
|
|
3019
|
-
expandSegmentAgainstRoute(
|
|
3064
|
+
expandSegmentAgainstRoute(injector, segmentGroup, routes, route, paths, outlet, allowRedirects) {
|
|
3020
3065
|
if (!isImmediateMatch(route, segmentGroup, paths, outlet)) {
|
|
3021
3066
|
return noMatch(segmentGroup);
|
|
3022
3067
|
}
|
|
3023
3068
|
if (route.redirectTo === undefined) {
|
|
3024
|
-
return this.matchSegmentAgainstRoute(
|
|
3069
|
+
return this.matchSegmentAgainstRoute(injector, segmentGroup, route, paths, outlet);
|
|
3025
3070
|
}
|
|
3026
3071
|
if (allowRedirects && this.allowRedirects) {
|
|
3027
|
-
return this.expandSegmentAgainstRouteUsingRedirect(
|
|
3072
|
+
return this.expandSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, paths, outlet);
|
|
3028
3073
|
}
|
|
3029
3074
|
return noMatch(segmentGroup);
|
|
3030
3075
|
}
|
|
3031
|
-
expandSegmentAgainstRouteUsingRedirect(
|
|
3076
|
+
expandSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet) {
|
|
3032
3077
|
if (route.path === '**') {
|
|
3033
|
-
return this.expandWildCardWithParamsAgainstRouteUsingRedirect(
|
|
3078
|
+
return this.expandWildCardWithParamsAgainstRouteUsingRedirect(injector, routes, route, outlet);
|
|
3034
3079
|
}
|
|
3035
|
-
return this.expandRegularSegmentAgainstRouteUsingRedirect(
|
|
3080
|
+
return this.expandRegularSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet);
|
|
3036
3081
|
}
|
|
3037
|
-
expandWildCardWithParamsAgainstRouteUsingRedirect(
|
|
3082
|
+
expandWildCardWithParamsAgainstRouteUsingRedirect(injector, routes, route, outlet) {
|
|
3038
3083
|
const newTree = this.applyRedirectCommands([], route.redirectTo, {});
|
|
3039
3084
|
if (route.redirectTo.startsWith('/')) {
|
|
3040
3085
|
return absoluteRedirect(newTree);
|
|
3041
3086
|
}
|
|
3042
3087
|
return this.lineralizeSegments(route, newTree).pipe(mergeMap((newSegments) => {
|
|
3043
3088
|
const group = new UrlSegmentGroup(newSegments, {});
|
|
3044
|
-
return this.expandSegment(
|
|
3089
|
+
return this.expandSegment(injector, group, routes, newSegments, outlet, false);
|
|
3045
3090
|
}));
|
|
3046
3091
|
}
|
|
3047
|
-
expandRegularSegmentAgainstRouteUsingRedirect(
|
|
3092
|
+
expandRegularSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet) {
|
|
3048
3093
|
const { matched, consumedSegments, remainingSegments, positionalParamSegments } = match(segmentGroup, route, segments);
|
|
3049
3094
|
if (!matched)
|
|
3050
3095
|
return noMatch(segmentGroup);
|
|
@@ -3053,16 +3098,18 @@ class ApplyRedirects {
|
|
|
3053
3098
|
return absoluteRedirect(newTree);
|
|
3054
3099
|
}
|
|
3055
3100
|
return this.lineralizeSegments(route, newTree).pipe(mergeMap((newSegments) => {
|
|
3056
|
-
return this.expandSegment(
|
|
3101
|
+
return this.expandSegment(injector, segmentGroup, routes, newSegments.concat(remainingSegments), outlet, false);
|
|
3057
3102
|
}));
|
|
3058
3103
|
}
|
|
3059
|
-
matchSegmentAgainstRoute(
|
|
3104
|
+
matchSegmentAgainstRoute(injector, rawSegmentGroup, route, segments, outlet) {
|
|
3060
3105
|
if (route.path === '**') {
|
|
3061
3106
|
if (route.loadChildren) {
|
|
3062
|
-
const loaded$ = route.
|
|
3063
|
-
|
|
3107
|
+
const loaded$ = route._loadedRoutes ?
|
|
3108
|
+
of({ routes: route._loadedRoutes, injector: route._loadedInjector }) :
|
|
3109
|
+
this.configLoader.load(injector, route);
|
|
3064
3110
|
return loaded$.pipe(map((cfg) => {
|
|
3065
|
-
route.
|
|
3111
|
+
route._loadedRoutes = cfg.routes;
|
|
3112
|
+
route._loadedInjector = cfg.injector;
|
|
3066
3113
|
return new UrlSegmentGroup(segments, {});
|
|
3067
3114
|
}));
|
|
3068
3115
|
}
|
|
@@ -3071,55 +3118,56 @@ class ApplyRedirects {
|
|
|
3071
3118
|
const { matched, consumedSegments, remainingSegments } = match(rawSegmentGroup, route, segments);
|
|
3072
3119
|
if (!matched)
|
|
3073
3120
|
return noMatch(rawSegmentGroup);
|
|
3074
|
-
const childConfig$ = this.getChildConfig(
|
|
3121
|
+
const childConfig$ = this.getChildConfig(injector, route, segments);
|
|
3075
3122
|
return childConfig$.pipe(mergeMap((routerConfig) => {
|
|
3076
|
-
|
|
3123
|
+
var _a;
|
|
3124
|
+
const childInjector = (_a = routerConfig.injector) !== null && _a !== void 0 ? _a : injector;
|
|
3077
3125
|
const childConfig = routerConfig.routes;
|
|
3078
3126
|
const { segmentGroup: splitSegmentGroup, slicedSegments } = split(rawSegmentGroup, consumedSegments, remainingSegments, childConfig);
|
|
3079
3127
|
// See comment on the other call to `split` about why this is necessary.
|
|
3080
3128
|
const segmentGroup = new UrlSegmentGroup(splitSegmentGroup.segments, splitSegmentGroup.children);
|
|
3081
3129
|
if (slicedSegments.length === 0 && segmentGroup.hasChildren()) {
|
|
3082
|
-
const expanded$ = this.expandChildren(
|
|
3130
|
+
const expanded$ = this.expandChildren(childInjector, childConfig, segmentGroup);
|
|
3083
3131
|
return expanded$.pipe(map((children) => new UrlSegmentGroup(consumedSegments, children)));
|
|
3084
3132
|
}
|
|
3085
3133
|
if (childConfig.length === 0 && slicedSegments.length === 0) {
|
|
3086
3134
|
return of(new UrlSegmentGroup(consumedSegments, {}));
|
|
3087
3135
|
}
|
|
3088
3136
|
const matchedOnOutlet = getOutlet(route) === outlet;
|
|
3089
|
-
const expanded$ = this.expandSegment(
|
|
3137
|
+
const expanded$ = this.expandSegment(childInjector, segmentGroup, childConfig, slicedSegments, matchedOnOutlet ? PRIMARY_OUTLET : outlet, true);
|
|
3090
3138
|
return expanded$.pipe(map((cs) => new UrlSegmentGroup(consumedSegments.concat(cs.segments), cs.children)));
|
|
3091
3139
|
}));
|
|
3092
3140
|
}
|
|
3093
|
-
getChildConfig(
|
|
3141
|
+
getChildConfig(injector, route, segments) {
|
|
3094
3142
|
if (route.children) {
|
|
3095
3143
|
// The children belong to the same module
|
|
3096
|
-
return of(
|
|
3144
|
+
return of({ routes: route.children, injector });
|
|
3097
3145
|
}
|
|
3098
3146
|
if (route.loadChildren) {
|
|
3099
3147
|
// lazy children belong to the loaded module
|
|
3100
|
-
if (route.
|
|
3101
|
-
return of(route.
|
|
3148
|
+
if (route._loadedRoutes !== undefined) {
|
|
3149
|
+
return of({ routes: route._loadedRoutes, injector: route._loadedInjector });
|
|
3102
3150
|
}
|
|
3103
|
-
return this.runCanLoadGuards(
|
|
3151
|
+
return this.runCanLoadGuards(injector, route, segments)
|
|
3104
3152
|
.pipe(mergeMap((shouldLoadResult) => {
|
|
3105
3153
|
if (shouldLoadResult) {
|
|
3106
|
-
return this.configLoader.load(
|
|
3107
|
-
.
|
|
3108
|
-
route.
|
|
3154
|
+
return this.configLoader.load(injector, route).pipe(map((cfg) => {
|
|
3155
|
+
route._loadedRoutes = cfg.routes;
|
|
3156
|
+
route._loadedInjector = cfg.injector;
|
|
3109
3157
|
return cfg;
|
|
3110
3158
|
}));
|
|
3111
3159
|
}
|
|
3112
3160
|
return canLoadFails(route);
|
|
3113
3161
|
}));
|
|
3114
3162
|
}
|
|
3115
|
-
return of(
|
|
3163
|
+
return of({ routes: [], injector });
|
|
3116
3164
|
}
|
|
3117
|
-
runCanLoadGuards(
|
|
3165
|
+
runCanLoadGuards(injector, route, segments) {
|
|
3118
3166
|
const canLoad = route.canLoad;
|
|
3119
3167
|
if (!canLoad || canLoad.length === 0)
|
|
3120
3168
|
return of(true);
|
|
3121
3169
|
const canLoadObservables = canLoad.map((injectionToken) => {
|
|
3122
|
-
const guard =
|
|
3170
|
+
const guard = injector.get(injectionToken);
|
|
3123
3171
|
let guardVal;
|
|
3124
3172
|
if (isCanLoad(guard)) {
|
|
3125
3173
|
guardVal = guard.canLoad(route, segments);
|
|
@@ -3247,8 +3295,8 @@ function squashSegmentGroup(segmentGroup) {
|
|
|
3247
3295
|
* Use of this source code is governed by an MIT-style license that can be
|
|
3248
3296
|
* found in the LICENSE file at https://angular.io/license
|
|
3249
3297
|
*/
|
|
3250
|
-
function applyRedirects(
|
|
3251
|
-
return switchMap(t => applyRedirects$1(
|
|
3298
|
+
function applyRedirects(environmentInjector, configLoader, urlSerializer, config) {
|
|
3299
|
+
return switchMap(t => applyRedirects$1(environmentInjector, configLoader, urlSerializer, t.extractedUrl, config)
|
|
3252
3300
|
.pipe(map(urlAfterRedirects => (Object.assign(Object.assign({}, t), { urlAfterRedirects })))));
|
|
3253
3301
|
}
|
|
3254
3302
|
|
|
@@ -3282,21 +3330,11 @@ function getCanActivateChild(p) {
|
|
|
3282
3330
|
return null;
|
|
3283
3331
|
return { node: p, guards: canActivateChild };
|
|
3284
3332
|
}
|
|
3285
|
-
function getToken(token, snapshot,
|
|
3286
|
-
const
|
|
3287
|
-
const injector =
|
|
3333
|
+
function getToken(token, snapshot, fallbackInjector) {
|
|
3334
|
+
const routeInjector = getClosestRouteInjector(snapshot);
|
|
3335
|
+
const injector = routeInjector !== null && routeInjector !== void 0 ? routeInjector : fallbackInjector;
|
|
3288
3336
|
return injector.get(token);
|
|
3289
3337
|
}
|
|
3290
|
-
function getClosestLoadedConfig(snapshot) {
|
|
3291
|
-
if (!snapshot)
|
|
3292
|
-
return null;
|
|
3293
|
-
for (let s = snapshot.parent; s; s = s.parent) {
|
|
3294
|
-
const route = s.routeConfig;
|
|
3295
|
-
if (route && route._loadedConfig)
|
|
3296
|
-
return route._loadedConfig;
|
|
3297
|
-
}
|
|
3298
|
-
return null;
|
|
3299
|
-
}
|
|
3300
3338
|
function getChildRouteGuards(futureNode, currNode, contexts, futurePath, checks = {
|
|
3301
3339
|
canDeactivateChecks: [],
|
|
3302
3340
|
canActivateChecks: []
|
|
@@ -3540,7 +3578,7 @@ function runCanDeactivate(component, currARS, currRSS, futureRSS, moduleInjector
|
|
|
3540
3578
|
* Use of this source code is governed by an MIT-style license that can be
|
|
3541
3579
|
* found in the LICENSE file at https://angular.io/license
|
|
3542
3580
|
*/
|
|
3543
|
-
const NG_DEV_MODE = typeof ngDevMode === 'undefined' || !!ngDevMode;
|
|
3581
|
+
const NG_DEV_MODE$2 = typeof ngDevMode === 'undefined' || !!ngDevMode;
|
|
3544
3582
|
class NoMatch {
|
|
3545
3583
|
}
|
|
3546
3584
|
function newObservableError(e) {
|
|
@@ -3661,7 +3699,7 @@ class Recognizer {
|
|
|
3661
3699
|
// NG_DEV_MODE is used to prevent the getCorrectedPathIndexShift function from affecting
|
|
3662
3700
|
// production bundle size. This value is intended only to surface a warning to users
|
|
3663
3701
|
// depending on `relativeLinkResolution: 'legacy'` in dev mode.
|
|
3664
|
-
(NG_DEV_MODE ? getCorrectedPathIndexShift(rawSegment) + segments.length :
|
|
3702
|
+
(NG_DEV_MODE$2 ? getCorrectedPathIndexShift(rawSegment) + segments.length :
|
|
3665
3703
|
pathIndexShift));
|
|
3666
3704
|
}
|
|
3667
3705
|
else {
|
|
@@ -3672,7 +3710,7 @@ class Recognizer {
|
|
|
3672
3710
|
consumedSegments = result.consumedSegments;
|
|
3673
3711
|
remainingSegments = result.remainingSegments;
|
|
3674
3712
|
const pathIndexShift = getPathIndexShift(rawSegment) + consumedSegments.length;
|
|
3675
|
-
snapshot = new ActivatedRouteSnapshot(consumedSegments, result.parameters, Object.freeze(Object.assign({}, this.urlTree.queryParams)), this.urlTree.fragment, getData(route), getOutlet(route), route.component, route, getSourceSegmentGroup(rawSegment), pathIndexShift, getResolve(route), (NG_DEV_MODE ? getCorrectedPathIndexShift(rawSegment) + consumedSegments.length :
|
|
3713
|
+
snapshot = new ActivatedRouteSnapshot(consumedSegments, result.parameters, Object.freeze(Object.assign({}, this.urlTree.queryParams)), this.urlTree.fragment, getData(route), getOutlet(route), route.component, route, getSourceSegmentGroup(rawSegment), pathIndexShift, getResolve(route), (NG_DEV_MODE$2 ? getCorrectedPathIndexShift(rawSegment) + consumedSegments.length :
|
|
3676
3714
|
pathIndexShift));
|
|
3677
3715
|
}
|
|
3678
3716
|
const childConfig = getChildConfig(route);
|
|
@@ -3721,7 +3759,7 @@ function getChildConfig(route) {
|
|
|
3721
3759
|
return route.children;
|
|
3722
3760
|
}
|
|
3723
3761
|
if (route.loadChildren) {
|
|
3724
|
-
return route.
|
|
3762
|
+
return route._loadedRoutes;
|
|
3725
3763
|
}
|
|
3726
3764
|
return [];
|
|
3727
3765
|
}
|
|
@@ -3867,16 +3905,9 @@ function resolveNode(resolve, futureARS, futureRSS, moduleInjector) {
|
|
|
3867
3905
|
}
|
|
3868
3906
|
const data = {};
|
|
3869
3907
|
return from(keys).pipe(mergeMap(key => getResolver(resolve[key], futureARS, futureRSS, moduleInjector)
|
|
3870
|
-
.pipe(
|
|
3908
|
+
.pipe(first(), tap((value) => {
|
|
3871
3909
|
data[key] = value;
|
|
3872
|
-
}))), takeLast(1),
|
|
3873
|
-
// Ensure all resolvers returned values, otherwise don't emit any "next" and just complete
|
|
3874
|
-
// the chain which will cancel navigation
|
|
3875
|
-
if (getDataKeys(data).length === keys.length) {
|
|
3876
|
-
return of(data);
|
|
3877
|
-
}
|
|
3878
|
-
return EMPTY;
|
|
3879
|
-
}));
|
|
3910
|
+
}))), takeLast(1), mapTo(data), catchError((e) => e instanceof EmptyError ? EMPTY : throwError(e)));
|
|
3880
3911
|
}
|
|
3881
3912
|
function getDataKeys(obj) {
|
|
3882
3913
|
return [...Object.keys(obj), ...Object.getOwnPropertySymbols(obj)];
|
|
@@ -3985,6 +4016,7 @@ class DefaultRouteReuseStrategy extends BaseRouteReuseStrategy {
|
|
|
3985
4016
|
* Use of this source code is governed by an MIT-style license that can be
|
|
3986
4017
|
* found in the LICENSE file at https://angular.io/license
|
|
3987
4018
|
*/
|
|
4019
|
+
const NG_DEV_MODE$1 = typeof ngDevMode === 'undefined' || !!ngDevMode;
|
|
3988
4020
|
/**
|
|
3989
4021
|
* The [DI token](guide/glossary/#di-token) for a router configuration.
|
|
3990
4022
|
*
|
|
@@ -3997,15 +4029,17 @@ class DefaultRouteReuseStrategy extends BaseRouteReuseStrategy {
|
|
|
3997
4029
|
*/
|
|
3998
4030
|
const ROUTES = new InjectionToken('ROUTES');
|
|
3999
4031
|
class RouterConfigLoader {
|
|
4000
|
-
constructor(injector, compiler
|
|
4032
|
+
constructor(injector, compiler) {
|
|
4001
4033
|
this.injector = injector;
|
|
4002
4034
|
this.compiler = compiler;
|
|
4003
|
-
this.
|
|
4004
|
-
this.onLoadEndListener = onLoadEndListener;
|
|
4035
|
+
this.routeLoaders = new WeakMap();
|
|
4005
4036
|
}
|
|
4006
4037
|
load(parentInjector, route) {
|
|
4007
|
-
if (route
|
|
4008
|
-
return route
|
|
4038
|
+
if (this.routeLoaders.get(route)) {
|
|
4039
|
+
return this.routeLoaders.get(route);
|
|
4040
|
+
}
|
|
4041
|
+
else if (route._loadedRoutes) {
|
|
4042
|
+
return of({ routes: route._loadedRoutes, injector: route._loadedInjector });
|
|
4009
4043
|
}
|
|
4010
4044
|
if (this.onLoadStartListener) {
|
|
4011
4045
|
this.onLoadStartListener(route);
|
|
@@ -4015,21 +4049,24 @@ class RouterConfigLoader {
|
|
|
4015
4049
|
if (this.onLoadEndListener) {
|
|
4016
4050
|
this.onLoadEndListener(route);
|
|
4017
4051
|
}
|
|
4018
|
-
const
|
|
4052
|
+
const injector = factory.create(parentInjector).injector;
|
|
4053
|
+
const routes =
|
|
4019
4054
|
// When loading a module that doesn't provide `RouterModule.forChild()` preloader
|
|
4020
4055
|
// will get stuck in an infinite loop. The child module's Injector will look to
|
|
4021
4056
|
// its parent `Injector` when it doesn't find any ROUTES so it will return routes
|
|
4022
4057
|
// for it's parent module instead.
|
|
4023
|
-
|
|
4024
|
-
.map(standardizeConfig)
|
|
4025
|
-
|
|
4026
|
-
|
|
4027
|
-
|
|
4058
|
+
flatten(injector.get(ROUTES, [], InjectFlags.Self | InjectFlags.Optional))
|
|
4059
|
+
.map(standardizeConfig);
|
|
4060
|
+
NG_DEV_MODE$1 && validateConfig(routes);
|
|
4061
|
+
return { routes, injector };
|
|
4062
|
+
}), finalize(() => {
|
|
4063
|
+
this.routeLoaders.delete(route);
|
|
4028
4064
|
}));
|
|
4029
4065
|
// Use custom ConnectableObservable as share in runners pipe increasing the bundle size too much
|
|
4030
|
-
|
|
4066
|
+
const loader = new ConnectableObservable(loadRunner, () => new Subject())
|
|
4031
4067
|
.pipe(refCount());
|
|
4032
|
-
|
|
4068
|
+
this.routeLoaders.set(route, loader);
|
|
4069
|
+
return loader;
|
|
4033
4070
|
}
|
|
4034
4071
|
loadModuleFactory(loadChildren) {
|
|
4035
4072
|
return wrapIntoObservable(loadChildren()).pipe(mergeMap((t) => {
|
|
@@ -4042,6 +4079,11 @@ class RouterConfigLoader {
|
|
|
4042
4079
|
}));
|
|
4043
4080
|
}
|
|
4044
4081
|
}
|
|
4082
|
+
RouterConfigLoader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterConfigLoader, deps: [{ token: i0.Injector }, { token: i0.Compiler }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
4083
|
+
RouterConfigLoader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterConfigLoader });
|
|
4084
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterConfigLoader, decorators: [{
|
|
4085
|
+
type: Injectable
|
|
4086
|
+
}], ctorParameters: function () { return [{ type: i0.Injector }, { type: i0.Compiler }]; } });
|
|
4045
4087
|
|
|
4046
4088
|
/**
|
|
4047
4089
|
* @license
|
|
@@ -4074,6 +4116,7 @@ class DefaultUrlHandlingStrategy {
|
|
|
4074
4116
|
}
|
|
4075
4117
|
}
|
|
4076
4118
|
|
|
4119
|
+
const NG_DEV_MODE = typeof ngDevMode === 'undefined' || !!ngDevMode;
|
|
4077
4120
|
function defaultErrorHandler(error) {
|
|
4078
4121
|
throw error;
|
|
4079
4122
|
}
|
|
@@ -4245,6 +4288,9 @@ class Router {
|
|
|
4245
4288
|
this.canceledNavigationResolution = 'replace';
|
|
4246
4289
|
const onLoadStart = (r) => this.triggerEvent(new RouteConfigLoadStart(r));
|
|
4247
4290
|
const onLoadEnd = (r) => this.triggerEvent(new RouteConfigLoadEnd(r));
|
|
4291
|
+
this.configLoader = injector.get(RouterConfigLoader);
|
|
4292
|
+
this.configLoader.onLoadEndListener = onLoadEnd;
|
|
4293
|
+
this.configLoader.onLoadStartListener = onLoadStart;
|
|
4248
4294
|
this.ngModule = injector.get(NgModuleRef);
|
|
4249
4295
|
this.console = injector.get(ɵConsole);
|
|
4250
4296
|
const ngZone = injector.get(NgZone);
|
|
@@ -4253,7 +4299,6 @@ class Router {
|
|
|
4253
4299
|
this.currentUrlTree = createEmptyUrlTree();
|
|
4254
4300
|
this.rawUrlTree = this.currentUrlTree;
|
|
4255
4301
|
this.browserUrlTree = this.currentUrlTree;
|
|
4256
|
-
this.configLoader = new RouterConfigLoader(injector, compiler, onLoadStart, onLoadEnd);
|
|
4257
4302
|
this.routerState = createEmptyState(this.currentUrlTree, this.rootComponentType);
|
|
4258
4303
|
this.transitions = new BehaviorSubject({
|
|
4259
4304
|
id: 0,
|
|
@@ -4657,7 +4702,7 @@ class Router {
|
|
|
4657
4702
|
* ```
|
|
4658
4703
|
*/
|
|
4659
4704
|
resetConfig(config) {
|
|
4660
|
-
validateConfig(config);
|
|
4705
|
+
NG_DEV_MODE && validateConfig(config);
|
|
4661
4706
|
this.config = config.map(standardizeConfig);
|
|
4662
4707
|
this.navigated = false;
|
|
4663
4708
|
this.lastSuccessfulId = -1;
|
|
@@ -5015,9 +5060,9 @@ class Router {
|
|
|
5015
5060
|
return { navigationId };
|
|
5016
5061
|
}
|
|
5017
5062
|
}
|
|
5018
|
-
Router.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5019
|
-
Router.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5020
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5063
|
+
Router.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: Router, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
|
|
5064
|
+
Router.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: Router });
|
|
5065
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: Router, decorators: [{
|
|
5021
5066
|
type: Injectable
|
|
5022
5067
|
}], ctorParameters: function () { return [{ type: i0.Type }, { type: UrlSerializer }, { type: ChildrenOutletContexts }, { type: i3.Location }, { type: i0.Injector }, { type: i0.Compiler }, { type: undefined }]; } });
|
|
5023
5068
|
function validateCommands(commands) {
|
|
@@ -5209,9 +5254,9 @@ class RouterLink {
|
|
|
5209
5254
|
});
|
|
5210
5255
|
}
|
|
5211
5256
|
}
|
|
5212
|
-
RouterLink.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5213
|
-
RouterLink.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5214
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5257
|
+
RouterLink.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterLink, deps: [{ token: Router }, { token: ActivatedRoute }, { token: 'tabindex', attribute: true }, { token: i0.Renderer2 }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
|
|
5258
|
+
RouterLink.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.14", type: RouterLink, selector: ":not(a):not(area)[routerLink]", inputs: { queryParams: "queryParams", fragment: "fragment", queryParamsHandling: "queryParamsHandling", preserveFragment: "preserveFragment", skipLocationChange: "skipLocationChange", replaceUrl: "replaceUrl", state: "state", relativeTo: "relativeTo", routerLink: "routerLink" }, host: { listeners: { "click": "onClick()" } }, usesOnChanges: true, ngImport: i0 });
|
|
5259
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterLink, decorators: [{
|
|
5215
5260
|
type: Directive,
|
|
5216
5261
|
args: [{ selector: ':not(a):not(area)[routerLink]' }]
|
|
5217
5262
|
}], ctorParameters: function () {
|
|
@@ -5330,9 +5375,9 @@ class RouterLinkWithHref {
|
|
|
5330
5375
|
});
|
|
5331
5376
|
}
|
|
5332
5377
|
}
|
|
5333
|
-
RouterLinkWithHref.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5334
|
-
RouterLinkWithHref.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5335
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5378
|
+
RouterLinkWithHref.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterLinkWithHref, deps: [{ token: Router }, { token: ActivatedRoute }, { token: i3.LocationStrategy }], target: i0.ɵɵFactoryTarget.Directive });
|
|
5379
|
+
RouterLinkWithHref.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.14", type: RouterLinkWithHref, selector: "a[routerLink],area[routerLink]", inputs: { target: "target", queryParams: "queryParams", fragment: "fragment", queryParamsHandling: "queryParamsHandling", preserveFragment: "preserveFragment", skipLocationChange: "skipLocationChange", replaceUrl: "replaceUrl", state: "state", relativeTo: "relativeTo", routerLink: "routerLink" }, host: { listeners: { "click": "onClick($event.button,$event.ctrlKey,$event.shiftKey,$event.altKey,$event.metaKey)" }, properties: { "attr.target": "this.target", "attr.href": "this.href" } }, usesOnChanges: true, ngImport: i0 });
|
|
5380
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterLinkWithHref, decorators: [{
|
|
5336
5381
|
type: Directive,
|
|
5337
5382
|
args: [{ selector: 'a[routerLink],area[routerLink]' }]
|
|
5338
5383
|
}], ctorParameters: function () { return [{ type: Router }, { type: ActivatedRoute }, { type: i3.LocationStrategy }]; }, propDecorators: { target: [{
|
|
@@ -5543,9 +5588,9 @@ class RouterLinkActive {
|
|
|
5543
5588
|
this.links.some(isActiveCheckFn) || this.linksWithHrefs.some(isActiveCheckFn);
|
|
5544
5589
|
}
|
|
5545
5590
|
}
|
|
5546
|
-
RouterLinkActive.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5547
|
-
RouterLinkActive.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5548
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5591
|
+
RouterLinkActive.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterLinkActive, deps: [{ token: Router }, { token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }, { token: RouterLink, optional: true }, { token: RouterLinkWithHref, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
|
|
5592
|
+
RouterLinkActive.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.14", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: { routerLinkActiveOptions: "routerLinkActiveOptions", routerLinkActive: "routerLinkActive" }, outputs: { isActiveChange: "isActiveChange" }, queries: [{ propertyName: "links", predicate: RouterLink, descendants: true }, { propertyName: "linksWithHrefs", predicate: RouterLinkWithHref, descendants: true }], exportAs: ["routerLinkActive"], usesOnChanges: true, ngImport: i0 });
|
|
5593
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterLinkActive, decorators: [{
|
|
5549
5594
|
type: Directive,
|
|
5550
5595
|
args: [{
|
|
5551
5596
|
selector: '[routerLinkActive]',
|
|
@@ -5649,9 +5694,9 @@ class DefaultTitleStrategy extends TitleStrategy {
|
|
|
5649
5694
|
}
|
|
5650
5695
|
}
|
|
5651
5696
|
}
|
|
5652
|
-
DefaultTitleStrategy.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5653
|
-
DefaultTitleStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5654
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5697
|
+
DefaultTitleStrategy.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: DefaultTitleStrategy, deps: [{ token: i1.Title }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
5698
|
+
DefaultTitleStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: DefaultTitleStrategy, providedIn: 'root' });
|
|
5699
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: DefaultTitleStrategy, decorators: [{
|
|
5655
5700
|
type: Injectable,
|
|
5656
5701
|
args: [{ providedIn: 'root' }]
|
|
5657
5702
|
}], ctorParameters: function () { return [{ type: i1.Title }]; } });
|
|
@@ -5715,13 +5760,11 @@ class NoPreloading {
|
|
|
5715
5760
|
* @publicApi
|
|
5716
5761
|
*/
|
|
5717
5762
|
class RouterPreloader {
|
|
5718
|
-
constructor(router, compiler, injector, preloadingStrategy) {
|
|
5763
|
+
constructor(router, compiler, injector, preloadingStrategy, loader) {
|
|
5719
5764
|
this.router = router;
|
|
5720
5765
|
this.injector = injector;
|
|
5721
5766
|
this.preloadingStrategy = preloadingStrategy;
|
|
5722
|
-
|
|
5723
|
-
const onEndLoad = (r) => router.triggerEvent(new RouteConfigLoadEnd(r));
|
|
5724
|
-
this.loader = new RouterConfigLoader(injector, compiler, onStartLoad, onEndLoad);
|
|
5767
|
+
this.loader = loader;
|
|
5725
5768
|
}
|
|
5726
5769
|
setUpPreloading() {
|
|
5727
5770
|
this.subscription =
|
|
@@ -5730,8 +5773,7 @@ class RouterPreloader {
|
|
|
5730
5773
|
.subscribe(() => { });
|
|
5731
5774
|
}
|
|
5732
5775
|
preload() {
|
|
5733
|
-
|
|
5734
|
-
return this.processRoutes(ngModule, this.router.config);
|
|
5776
|
+
return this.processRoutes(this.injector, this.router.config);
|
|
5735
5777
|
}
|
|
5736
5778
|
/** @nodoc */
|
|
5737
5779
|
ngOnDestroy() {
|
|
@@ -5739,41 +5781,52 @@ class RouterPreloader {
|
|
|
5739
5781
|
this.subscription.unsubscribe();
|
|
5740
5782
|
}
|
|
5741
5783
|
}
|
|
5742
|
-
processRoutes(
|
|
5784
|
+
processRoutes(injector, routes) {
|
|
5785
|
+
var _a, _b;
|
|
5743
5786
|
const res = [];
|
|
5744
5787
|
for (const route of routes) {
|
|
5788
|
+
if (route.providers && !route._injector) {
|
|
5789
|
+
route._injector =
|
|
5790
|
+
createEnvironmentInjector(route.providers, injector, `Route: ${route.path}`);
|
|
5791
|
+
}
|
|
5792
|
+
const injectorForCurrentRoute = (_a = route._injector) !== null && _a !== void 0 ? _a : injector;
|
|
5793
|
+
const injectorForChildren = (_b = route._loadedInjector) !== null && _b !== void 0 ? _b : injectorForCurrentRoute;
|
|
5745
5794
|
// we already have the config loaded, just recurse
|
|
5746
|
-
if (route.loadChildren && !route.canLoad && route.
|
|
5747
|
-
|
|
5748
|
-
res.push(this.processRoutes(childConfig.module, childConfig.routes));
|
|
5795
|
+
if (route.loadChildren && !route.canLoad && route._loadedRoutes) {
|
|
5796
|
+
res.push(this.processRoutes(injectorForChildren, route._loadedRoutes));
|
|
5749
5797
|
// no config loaded, fetch the config
|
|
5750
5798
|
}
|
|
5751
5799
|
else if (route.loadChildren && !route.canLoad) {
|
|
5752
|
-
res.push(this.preloadConfig(
|
|
5800
|
+
res.push(this.preloadConfig(injectorForCurrentRoute, route));
|
|
5753
5801
|
// recurse into children
|
|
5754
5802
|
}
|
|
5755
5803
|
else if (route.children) {
|
|
5756
|
-
res.push(this.processRoutes(
|
|
5804
|
+
res.push(this.processRoutes(injectorForChildren, route.children));
|
|
5757
5805
|
}
|
|
5758
5806
|
}
|
|
5759
5807
|
return from(res).pipe(mergeAll(), map((_) => void 0));
|
|
5760
5808
|
}
|
|
5761
|
-
preloadConfig(
|
|
5809
|
+
preloadConfig(injector, route) {
|
|
5762
5810
|
return this.preloadingStrategy.preload(route, () => {
|
|
5763
|
-
const loaded$ = route.
|
|
5764
|
-
|
|
5811
|
+
const loaded$ = route._loadedRoutes ?
|
|
5812
|
+
of({ routes: route._loadedRoutes, injector: route._loadedInjector }) :
|
|
5813
|
+
this.loader.load(injector, route);
|
|
5765
5814
|
return loaded$.pipe(mergeMap((config) => {
|
|
5766
|
-
|
|
5767
|
-
|
|
5815
|
+
var _a;
|
|
5816
|
+
route._loadedRoutes = config.routes;
|
|
5817
|
+
route._loadedInjector = config.injector;
|
|
5818
|
+
// If the loaded config was a module, use that as the module/module injector going forward.
|
|
5819
|
+
// Otherwise, continue using the current module/module injector.
|
|
5820
|
+
return this.processRoutes((_a = config.injector) !== null && _a !== void 0 ? _a : injector, config.routes);
|
|
5768
5821
|
}));
|
|
5769
5822
|
});
|
|
5770
5823
|
}
|
|
5771
5824
|
}
|
|
5772
|
-
RouterPreloader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5773
|
-
RouterPreloader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5774
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5825
|
+
RouterPreloader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterPreloader, deps: [{ token: Router }, { token: i0.Compiler }, { token: i0.EnvironmentInjector }, { token: PreloadingStrategy }, { token: RouterConfigLoader }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
5826
|
+
RouterPreloader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterPreloader });
|
|
5827
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterPreloader, decorators: [{
|
|
5775
5828
|
type: Injectable
|
|
5776
|
-
}], ctorParameters: function () { return [{ type: Router }, { type: i0.Compiler }, { type: i0.
|
|
5829
|
+
}], ctorParameters: function () { return [{ type: Router }, { type: i0.Compiler }, { type: i0.EnvironmentInjector }, { type: PreloadingStrategy }, { type: RouterConfigLoader }]; } });
|
|
5777
5830
|
|
|
5778
5831
|
class RouterScroller {
|
|
5779
5832
|
constructor(router,
|
|
@@ -5850,9 +5903,9 @@ class RouterScroller {
|
|
|
5850
5903
|
}
|
|
5851
5904
|
}
|
|
5852
5905
|
}
|
|
5853
|
-
RouterScroller.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5854
|
-
RouterScroller.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5855
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5906
|
+
RouterScroller.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterScroller, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
|
|
5907
|
+
RouterScroller.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterScroller });
|
|
5908
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterScroller, decorators: [{
|
|
5856
5909
|
type: Injectable
|
|
5857
5910
|
}], ctorParameters: function () { return [{ type: Router }, { type: i3.ViewportScroller }, { type: undefined }]; } });
|
|
5858
5911
|
|
|
@@ -5895,6 +5948,7 @@ const ROUTER_PROVIDERS = [
|
|
|
5895
5948
|
NoPreloading,
|
|
5896
5949
|
PreloadAllModules,
|
|
5897
5950
|
{ provide: ROUTER_CONFIGURATION, useValue: { enableTracing: false } },
|
|
5951
|
+
RouterConfigLoader,
|
|
5898
5952
|
];
|
|
5899
5953
|
function routerNgProbeToken() {
|
|
5900
5954
|
return new NgProbeToken('Router', Router);
|
|
@@ -5993,10 +6047,10 @@ class RouterModule {
|
|
|
5993
6047
|
return { ngModule: RouterModule, providers: [provideRoutes(routes)] };
|
|
5994
6048
|
}
|
|
5995
6049
|
}
|
|
5996
|
-
RouterModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5997
|
-
RouterModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5998
|
-
RouterModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5999
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
6050
|
+
RouterModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterModule, deps: [{ token: ROUTER_FORROOT_GUARD, optional: true }, { token: Router, optional: true }], target: i0.ɵɵFactoryTarget.NgModule });
|
|
6051
|
+
RouterModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterModule, declarations: [RouterOutlet, RouterLink, RouterLinkWithHref, RouterLinkActive, ɵEmptyOutletComponent], exports: [RouterOutlet, RouterLink, RouterLinkWithHref, RouterLinkActive, ɵEmptyOutletComponent] });
|
|
6052
|
+
RouterModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterModule });
|
|
6053
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterModule, decorators: [{
|
|
6000
6054
|
type: NgModule,
|
|
6001
6055
|
args: [{
|
|
6002
6056
|
declarations: ROUTER_DIRECTIVES,
|
|
@@ -6178,9 +6232,9 @@ class RouterInitializer {
|
|
|
6178
6232
|
this.destroyed = true;
|
|
6179
6233
|
}
|
|
6180
6234
|
}
|
|
6181
|
-
RouterInitializer.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
6182
|
-
RouterInitializer.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
6183
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
6235
|
+
RouterInitializer.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterInitializer, deps: [{ token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
6236
|
+
RouterInitializer.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterInitializer });
|
|
6237
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterInitializer, decorators: [{
|
|
6184
6238
|
type: Injectable
|
|
6185
6239
|
}], ctorParameters: function () { return [{ type: i0.Injector }]; } });
|
|
6186
6240
|
function getAppInitializer(r) {
|
|
@@ -6220,7 +6274,7 @@ function provideRouterInitializer() {
|
|
|
6220
6274
|
/**
|
|
6221
6275
|
* @publicApi
|
|
6222
6276
|
*/
|
|
6223
|
-
const VERSION = new Version('14.0.0-next.
|
|
6277
|
+
const VERSION = new Version('14.0.0-next.14');
|
|
6224
6278
|
|
|
6225
6279
|
/**
|
|
6226
6280
|
* @license
|