Skip to content

bug: Router mutates pathname/internal URL before route match succeeds — unknown paths corrupt state #18

Description

@lucas-spin

Summary

In handleRoute(), this.url = url.pathname is committed to state before matchRoute() runs. If the path doesn't match any route, the URL is already mutated and the 404 page is shown with the wrong internal URL persisted — meaning Router.pathname reflects the failed path even after the match fails.

Affected code

src/core/router/Router.tshandleRoute():

private handleRoute() {
  // ...
  const url = new URL("http://localhost" + urlPath);
  this.url = url.pathname;              // ← URL committed unconditionally
  this.buildRoutePage(matchRoute(url, this.routes));  // ← match runs AFTER
}

If matchRoute() returns null (no match), the code goes to pageNotFound, but this.url is already set to the unmatched path. The next call to Router.pathname will return the 404 path.

Impact

await Router.go('/valid-route');
// Router.pathname === 'valid-route' ✓

await Router.go('/this-does-not-exist');
// Match fails → 404 page shown
// But:
expect(Router.pathname).toBe('valid-route'); // ← FAILS — pathname was mutated

This also means:

  • Router.reload() after a failed navigation will re-show the 404 page.
  • Navigation guards that call Router.go(Router.#router.urlValid) on failure may not restore the correct URL if the invalid URL was already committed.

Reproduction

await Router.go('/about');
const safePath = Router.pathname; // 'about'

await Router.go('/nonexistent-path');
// Router.pathname is now 'nonexistent-path' — not 'about'

Recommendation

Only commit this.url after a successful match:

private handleRoute() {
  // ...
  const url = new URL("http://localhost" + urlPath);
  const match = matchRoute(url, this.routes);
  if (match) {
    this.url = url.pathname;  // ← only commit on success
  }
  this.buildRoutePage(match);
}

cc @zico15

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions