fix(router): allow UrlMatcher to return null (#36402)
The matcher is allowed to return null per https://angular.io/api/router/UrlMatcher#usage-notes And run `yarn gulp format` to pick up recent clang format changes. Closes #29824 BREAKING CHANGE: UrlMatcher's type now reflects that it could always return null. If you implemented your own Router or Recognizer class, please update it to handle matcher returning null. PR Close #36402
This commit is contained in:
parent
a555fdba32
commit
568e9df1d6
2
goldens/public-api/router/router.d.ts
vendored
2
goldens/public-api/router/router.d.ts
vendored
@ -500,7 +500,7 @@ export declare abstract class UrlHandlingStrategy {
|
|||||||
abstract shouldProcessUrl(url: UrlTree): boolean;
|
abstract shouldProcessUrl(url: UrlTree): boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export declare type UrlMatcher = (segments: UrlSegment[], group: UrlSegmentGroup, route: Route) => UrlMatchResult;
|
export declare type UrlMatcher = (segments: UrlSegment[], group: UrlSegmentGroup, route: Route) => UrlMatchResult | null;
|
||||||
|
|
||||||
export declare type UrlMatchResult = {
|
export declare type UrlMatchResult = {
|
||||||
consumed: UrlSegment[];
|
consumed: UrlSegment[];
|
||||||
|
@ -36,7 +36,8 @@ export type Routes = Route[];
|
|||||||
* @publicApi
|
* @publicApi
|
||||||
*/
|
*/
|
||||||
export type UrlMatchResult = {
|
export type UrlMatchResult = {
|
||||||
consumed: UrlSegment[]; posParams?: {[name: string]: UrlSegment};
|
consumed: UrlSegment[];
|
||||||
|
posParams?: {[name: string]: UrlSegment};
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -64,7 +65,7 @@ export type UrlMatchResult = {
|
|||||||
* @publicApi
|
* @publicApi
|
||||||
*/
|
*/
|
||||||
export type UrlMatcher = (segments: UrlSegment[], group: UrlSegmentGroup, route: Route) =>
|
export type UrlMatcher = (segments: UrlSegment[], group: UrlSegmentGroup, route: Route) =>
|
||||||
UrlMatchResult;
|
UrlMatchResult|null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -156,9 +157,9 @@ export type QueryParamsHandling = 'merge' | 'preserve' | '';
|
|||||||
* @see `Route#runGuardsAndResolvers`
|
* @see `Route#runGuardsAndResolvers`
|
||||||
* @publicApi
|
* @publicApi
|
||||||
*/
|
*/
|
||||||
export type RunGuardsAndResolvers = 'pathParamsChange' | 'pathParamsOrQueryParamsChange' |
|
export type RunGuardsAndResolvers =
|
||||||
'paramsChange' | 'paramsOrQueryParamsChange' | 'always' |
|
'pathParamsChange'|'pathParamsOrQueryParamsChange'|'paramsChange'|'paramsOrQueryParamsChange'|
|
||||||
((from: ActivatedRouteSnapshot, to: ActivatedRouteSnapshot) => boolean);
|
'always'|((from: ActivatedRouteSnapshot, to: ActivatedRouteSnapshot) => boolean);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A configuration object that defines a single route.
|
* A configuration object that defines a single route.
|
||||||
@ -519,36 +520,36 @@ function validateNode(route: Route, fullPath: string): void {
|
|||||||
}
|
}
|
||||||
if (!route.component && !route.children && !route.loadChildren &&
|
if (!route.component && !route.children && !route.loadChildren &&
|
||||||
(route.outlet && route.outlet !== PRIMARY_OUTLET)) {
|
(route.outlet && route.outlet !== PRIMARY_OUTLET)) {
|
||||||
throw new Error(
|
throw new Error(`Invalid configuration of route '${
|
||||||
`Invalid configuration of route '${fullPath}': a componentless route without children or loadChildren cannot have a named outlet set`);
|
fullPath}': a componentless route without children or loadChildren cannot have a named outlet set`);
|
||||||
}
|
}
|
||||||
if (route.redirectTo && route.children) {
|
if (route.redirectTo && route.children) {
|
||||||
throw new Error(
|
throw new Error(`Invalid configuration of route '${
|
||||||
`Invalid configuration of route '${fullPath}': redirectTo and children cannot be used together`);
|
fullPath}': redirectTo and children cannot be used together`);
|
||||||
}
|
}
|
||||||
if (route.redirectTo && route.loadChildren) {
|
if (route.redirectTo && route.loadChildren) {
|
||||||
throw new Error(
|
throw new Error(`Invalid configuration of route '${
|
||||||
`Invalid configuration of route '${fullPath}': redirectTo and loadChildren cannot be used together`);
|
fullPath}': redirectTo and loadChildren cannot be used together`);
|
||||||
}
|
}
|
||||||
if (route.children && route.loadChildren) {
|
if (route.children && route.loadChildren) {
|
||||||
throw new Error(
|
throw new Error(`Invalid configuration of route '${
|
||||||
`Invalid configuration of route '${fullPath}': children and loadChildren cannot be used together`);
|
fullPath}': children and loadChildren cannot be used together`);
|
||||||
}
|
}
|
||||||
if (route.redirectTo && route.component) {
|
if (route.redirectTo && route.component) {
|
||||||
throw new Error(
|
throw new Error(`Invalid configuration of route '${
|
||||||
`Invalid configuration of route '${fullPath}': redirectTo and component cannot be used together`);
|
fullPath}': redirectTo and component cannot be used together`);
|
||||||
}
|
}
|
||||||
if (route.path && route.matcher) {
|
if (route.path && route.matcher) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Invalid configuration of route '${fullPath}': path and matcher cannot be used together`);
|
`Invalid configuration of route '${fullPath}': path and matcher cannot be used together`);
|
||||||
}
|
}
|
||||||
if (route.redirectTo === void 0 && !route.component && !route.children && !route.loadChildren) {
|
if (route.redirectTo === void 0 && !route.component && !route.children && !route.loadChildren) {
|
||||||
throw new Error(
|
throw new Error(`Invalid configuration of route '${
|
||||||
`Invalid configuration of route '${fullPath}'. One of the following must be provided: component, redirectTo, children or loadChildren`);
|
fullPath}'. One of the following must be provided: component, redirectTo, children or loadChildren`);
|
||||||
}
|
}
|
||||||
if (route.path === void 0 && route.matcher === void 0) {
|
if (route.path === void 0 && route.matcher === void 0) {
|
||||||
throw new Error(
|
throw new Error(`Invalid configuration of route '${
|
||||||
`Invalid configuration of route '${fullPath}': routes must have either a path or a matcher specified`);
|
fullPath}': routes must have either a path or a matcher specified`);
|
||||||
}
|
}
|
||||||
if (typeof route.path === 'string' && route.path.charAt(0) === '/') {
|
if (typeof route.path === 'string' && route.path.charAt(0) === '/') {
|
||||||
throw new Error(`Invalid configuration of route '${fullPath}': path cannot start with a slash`);
|
throw new Error(`Invalid configuration of route '${fullPath}': path cannot start with a slash`);
|
||||||
@ -556,12 +557,12 @@ function validateNode(route: Route, fullPath: string): void {
|
|||||||
if (route.path === '' && route.redirectTo !== void 0 && route.pathMatch === void 0) {
|
if (route.path === '' && route.redirectTo !== void 0 && route.pathMatch === void 0) {
|
||||||
const exp =
|
const exp =
|
||||||
`The default value of 'pathMatch' is 'prefix', but often the intent is to use 'full'.`;
|
`The default value of 'pathMatch' is 'prefix', but often the intent is to use 'full'.`;
|
||||||
throw new Error(
|
throw new Error(`Invalid configuration of route '{path: "${fullPath}", redirectTo: "${
|
||||||
`Invalid configuration of route '{path: "${fullPath}", redirectTo: "${route.redirectTo}"}': please provide 'pathMatch'. ${exp}`);
|
route.redirectTo}"}': please provide 'pathMatch'. ${exp}`);
|
||||||
}
|
}
|
||||||
if (route.pathMatch !== void 0 && route.pathMatch !== 'full' && route.pathMatch !== 'prefix') {
|
if (route.pathMatch !== void 0 && route.pathMatch !== 'full' && route.pathMatch !== 'prefix') {
|
||||||
throw new Error(
|
throw new Error(`Invalid configuration of route '${
|
||||||
`Invalid configuration of route '${fullPath}': pathMatch can only be set to 'prefix' or 'full'`);
|
fullPath}': pathMatch can only be set to 'prefix' or 'full'`);
|
||||||
}
|
}
|
||||||
if (route.children) {
|
if (route.children) {
|
||||||
validateConfig(route.children, fullPath);
|
validateConfig(route.children, fullPath);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user