diff --git a/packages/router/src/index.ts b/packages/router/src/index.ts index cd45ac9..6b6221c 100644 --- a/packages/router/src/index.ts +++ b/packages/router/src/index.ts @@ -313,30 +313,39 @@ export function createPrefixMatcher(prefix: `/${string}`): (pathname: `/${string ) } - let start = 1 + return matchesHead(head, pathname) + } +} - for (const expected of head) { - // At the end, or at a trailing slash, the path has no more segments. - if (start >= pathname.length) { - return false - } +/** + * Whether `pathname` starts with the segments in `head`, `undefined` standing + * for a param. Kept out of the prefix matcher, so that a cold start compiles it + * only for a prefix with params or a path with `%`. + */ +function matchesHead(head: readonly (string | undefined)[], pathname: string): boolean { + let start = 1 - let end = pathname.indexOf('/', start) - if (end === -1) { - end = pathname.length - } + for (const expected of head) { + // At the end, or at a trailing slash, the path has no more segments. + if (start >= pathname.length) { + return false + } - // `undefined` stands for a param, which needs a non-empty segment. - const segment = decode(pathname.slice(start, end)) - if (expected === undefined ? segment === '' : segment !== expected) { - return false - } + let end = pathname.indexOf('/', start) + if (end === -1) { + end = pathname.length + } - start = end + 1 + // `undefined` stands for a param, which needs a non-empty segment. + const segment = decode(pathname.slice(start, end)) + if (expected === undefined ? segment === '' : segment !== expected) { + return false } - return true + start = end + 1 } + + return true } function filterOf(statics: Map): Uint8Array {