mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
Revert "feat(router): Support wildcard params with segments trailing"
This reverts commit 0a0cc27aea.
Causes internal failures with route matching. Should investigate and add
tests to prevent future regressions.
This commit is contained in:
committed by
Kristiyan Kostadinov
parent
3032332da0
commit
5a93eeb6c0
@@ -530,6 +530,7 @@
|
||||
"createUrlTreeFromSnapshot",
|
||||
"createViewBlueprint",
|
||||
"createViewRef",
|
||||
"createWildcardMatchResult",
|
||||
"cyclicDependencyError",
|
||||
"deactivateRouteAndItsChildren",
|
||||
"decode",
|
||||
@@ -884,7 +885,6 @@
|
||||
"markedFeatures",
|
||||
"match",
|
||||
"matchMatrixKeySegments",
|
||||
"matchParts",
|
||||
"matchQueryParams",
|
||||
"matchSegments",
|
||||
"matchTemplateAttribute",
|
||||
|
||||
@@ -117,24 +117,6 @@ export function convertToParamMap(params: Params): ParamMap {
|
||||
return new ParamsAsMap(params);
|
||||
}
|
||||
|
||||
function matchParts(
|
||||
routeParts: string[],
|
||||
urlSegments: UrlSegment[],
|
||||
posParams: {[key: string]: UrlSegment},
|
||||
): boolean {
|
||||
for (let i = 0; i < routeParts.length; i++) {
|
||||
const part = routeParts[i];
|
||||
const segment = urlSegments[i];
|
||||
const isParameter = part[0] === ':';
|
||||
if (isParameter) {
|
||||
posParams[part.substring(1)] = segment;
|
||||
} else if (part !== segment.path) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches the route configuration (`route`) against the actual URL (`segments`).
|
||||
*
|
||||
@@ -156,57 +138,15 @@ export function defaultUrlMatcher(
|
||||
route: Route,
|
||||
): UrlMatchResult | null {
|
||||
const parts = route.path!.split('/');
|
||||
const wildcardIndex = parts.indexOf('**');
|
||||
if (wildcardIndex === -1) {
|
||||
// No wildcard, use original logic
|
||||
if (parts.length > segments.length) {
|
||||
// The actual URL is shorter than the config, no match
|
||||
return null;
|
||||
}
|
||||
|
||||
if (
|
||||
route.pathMatch === 'full' &&
|
||||
(segmentGroup.hasChildren() || parts.length < segments.length)
|
||||
) {
|
||||
// The config is longer than the actual URL but we are looking for a full match, return null
|
||||
return null;
|
||||
}
|
||||
|
||||
const posParams: {[key: string]: UrlSegment} = {};
|
||||
const consumed = segments.slice(0, parts.length);
|
||||
if (!matchParts(parts, consumed, posParams)) {
|
||||
return null;
|
||||
}
|
||||
return {consumed, posParams};
|
||||
}
|
||||
|
||||
// Path has a wildcard.
|
||||
if (wildcardIndex !== parts.lastIndexOf('**')) {
|
||||
// We do not support more than one wildcard segment in the path
|
||||
return null;
|
||||
}
|
||||
|
||||
const pre = parts.slice(0, wildcardIndex);
|
||||
const post = parts.slice(wildcardIndex + 1);
|
||||
|
||||
if (pre.length + post.length > segments.length) {
|
||||
if (parts.length > segments.length) {
|
||||
// The actual URL is shorter than the config, no match
|
||||
return null;
|
||||
}
|
||||
if (
|
||||
// If the wildcard is not at the end of the path, it must match at least one segment.
|
||||
// e.g. `foo/**/bar` does not match `foo/bar`.
|
||||
wildcardIndex > -1 &&
|
||||
pre.length > 0 &&
|
||||
post.length > 0 &&
|
||||
pre.length + post.length === segments.length
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (
|
||||
route.pathMatch === 'full' &&
|
||||
(segmentGroup.hasChildren() || segments.length > pre.length + post.length)
|
||||
(segmentGroup.hasChildren() || parts.length < segments.length)
|
||||
) {
|
||||
// The config is longer than the actual URL but we are looking for a full match, return null
|
||||
return null;
|
||||
@@ -214,18 +154,18 @@ export function defaultUrlMatcher(
|
||||
|
||||
const posParams: {[key: string]: UrlSegment} = {};
|
||||
|
||||
// Match the segments before the wildcard
|
||||
if (!matchParts(pre, segments.slice(0, pre.length), posParams)) {
|
||||
return null;
|
||||
}
|
||||
// Match the segments after the wildcard
|
||||
if (!matchParts(post, segments.slice(segments.length - post.length), posParams)) {
|
||||
return null;
|
||||
// Check each config part against the actual URL
|
||||
for (let index = 0; index < parts.length; index++) {
|
||||
const part = parts[index];
|
||||
const segment = segments[index];
|
||||
const isParameter = part[0] === ':';
|
||||
if (isParameter) {
|
||||
posParams[part.substring(1)] = segment;
|
||||
} else if (part !== segment.path) {
|
||||
// The actual URL part does not match the config, no match
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(atscott): put the wildcard segments into a _splat param.
|
||||
// this would require a breaking change to the UrlMatchResult to allow UrlSegment[]
|
||||
// since the splat could be multiple segments.
|
||||
|
||||
return {consumed: segments, posParams};
|
||||
return {consumed: segments.slice(0, parts.length), posParams};
|
||||
}
|
||||
|
||||
@@ -60,6 +60,10 @@ export function match(
|
||||
route: Route,
|
||||
segments: UrlSegment[],
|
||||
): MatchResult {
|
||||
if (route.path === '**') {
|
||||
return createWildcardMatchResult(segments);
|
||||
}
|
||||
|
||||
if (route.path === '') {
|
||||
if (route.pathMatch === 'full' && (segmentGroup.hasChildren() || segments.length > 0)) {
|
||||
return {...noMatch};
|
||||
@@ -97,6 +101,16 @@ export function match(
|
||||
};
|
||||
}
|
||||
|
||||
function createWildcardMatchResult(segments: UrlSegment[]): MatchResult {
|
||||
return {
|
||||
matched: true,
|
||||
parameters: segments.length > 0 ? last(segments)!.parameters : {},
|
||||
consumedSegments: segments,
|
||||
remainingSegments: [],
|
||||
positionalParamSegments: {},
|
||||
};
|
||||
}
|
||||
|
||||
export function split(
|
||||
segmentGroup: UrlSegmentGroup,
|
||||
consumedSegments: UrlSegment[],
|
||||
|
||||
@@ -585,58 +585,6 @@ describe('recognize', () => {
|
||||
const s = await recognize([{path: '**', component: ComponentA}], 'a/b/c/d;a1=11');
|
||||
checkActivatedRoute(s.root.firstChild!, 'a/b/c/d', {a1: '11'}, ComponentA);
|
||||
});
|
||||
|
||||
it('should support segments after a wildcard', async () => {
|
||||
const s = await recognize(
|
||||
[
|
||||
{
|
||||
path: 'a',
|
||||
component: ComponentA,
|
||||
children: [
|
||||
{
|
||||
path: '**/b',
|
||||
component: ComponentB,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
'a/1/2/b',
|
||||
);
|
||||
const a = s.root.firstChild!;
|
||||
checkActivatedRoute(a, 'a', {}, ComponentA);
|
||||
|
||||
const wildcard = a.firstChild!;
|
||||
checkActivatedRoute(wildcard, '1/2/b', {}, ComponentB);
|
||||
});
|
||||
|
||||
describe('with segments after', () => {
|
||||
const recognizer = (url: string) => {
|
||||
const config = [
|
||||
{
|
||||
path: 'foo/**/bar',
|
||||
component: ComponentA,
|
||||
},
|
||||
];
|
||||
return recognize(config, url);
|
||||
};
|
||||
|
||||
it('matches a url with one segment for the wildcard', async () => {
|
||||
const s = await recognizer('foo/a/bar');
|
||||
checkActivatedRoute(s.root.firstChild!, 'foo/a/bar', {}, ComponentA);
|
||||
});
|
||||
|
||||
it('matches a url with multiple segments for the wildcard', async () => {
|
||||
const s = await recognizer('foo/a/b/c/bar');
|
||||
checkActivatedRoute(s.root.firstChild!, 'foo/a/b/c/bar', {}, ComponentA);
|
||||
});
|
||||
it('does not match a url with no segments for the wildcard', async () => {
|
||||
await expectAsync(recognizer('foo/bar')).toBeRejected();
|
||||
});
|
||||
|
||||
it('does not match a url with a wrong suffix', async () => {
|
||||
await expectAsync(recognizer('foo/a/b/baz')).toBeRejected();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('componentless routes', () => {
|
||||
|
||||
Reference in New Issue
Block a user