feat(experimental): never decode the hash, protect-only encoding - #2760
feat(experimental): never decode the hash, protect-only encoding#2760posva wants to merge 1 commit into
Conversation
The hash is now kept as it appears in the URL, like location.hash. encodeHash only protects unsafe characters and keeps existing percent sequences and lone % as they are, making it idempotent and resolve round-trips lossless. Also removes the now-unused NEW_stringifyURL from src/location.ts.
✅ Deploy Preview for vue-router canceled.
|
📝 WalkthroughWalkthroughThe experimental router now preserves raw hash encoding during parsing, adds an idempotent ChangesHash encoding and routing
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant Router
participant Resolver
participant encodeHash
participant stringifyURL
Router->>Resolver: resolve location
Resolver->>encodeHash: encode hash
encodeHash-->>Resolver: stable encoded hash
Resolver->>stringifyURL: build fullPath
stringifyURL-->>Router: resolved URL and hash
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
commit: |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2760 +/- ##
==========================================
+ Coverage 86.99% 87.01% +0.01%
==========================================
Files 93 94 +1
Lines 10722 10738 +16
Branches 2478 2479 +1
==========================================
+ Hits 9328 9344 +16
Misses 1388 1388
Partials 6 6 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
packages/router/src/experimental/route-resolver/resolver-fixed.ts (1)
305-305: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueUse nullish coalescing for consistency.
For consistency with the identical assignment on line 221 (
to.hash ?? ''), consider using the nullish coalescing operator??here instead of the logical OR||.♻️ Proposed refactor
- const hash = encodeHash(to.hash || '') + const hash = encodeHash(to.hash ?? '')🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/router/src/experimental/route-resolver/resolver-fixed.ts` at line 305, Update the hash assignment in the resolver flow to use nullish coalescing (`??`) instead of logical OR (`||`), matching the existing `to.hash ?? ''` assignment and preserving non-nullish hash values.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/router/src/experimental/encoding.ts`:
- Around line 32-36: Reorder the replacement chain in the encoding logic so
ENC_CURLY_OPEN_RE, ENC_CURLY_CLOSE_RE, and ENC_CARET_RE are restored before
ENC_PERCENT_RE. Keep percent restoration last, ensuring values such as %257B
become %7B without being decoded into literal characters.
---
Nitpick comments:
In `@packages/router/src/experimental/route-resolver/resolver-fixed.ts`:
- Line 305: Update the hash assignment in the resolver flow to use nullish
coalescing (`??`) instead of logical OR (`||`), matching the existing `to.hash
?? ''` assignment and preserving non-nullish hash values.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 29d91d0e-6975-44c9-ada1-8d7aec9c74e2
📒 Files selected for processing (11)
packages/router/src/experimental/encoding.spec.tspackages/router/src/experimental/encoding.tspackages/router/src/experimental/location.spec.tspackages/router/src/experimental/location.tspackages/router/src/experimental/query.tspackages/router/src/experimental/route-resolver/matchers/matcher-pattern.tspackages/router/src/experimental/route-resolver/resolver-abstract.tspackages/router/src/experimental/route-resolver/resolver-fixed.spec.tspackages/router/src/experimental/route-resolver/resolver-fixed.tspackages/router/src/experimental/router.spec.tspackages/router/src/location.ts
| // restore every original %, so pre-encoded sequences pass through | ||
| .replace(ENC_PERCENT_RE, '%') | ||
| .replace(ENC_CURLY_OPEN_RE, '{') | ||
| .replace(ENC_CURLY_CLOSE_RE, '}') | ||
| .replace(ENC_CARET_RE, '^') |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Reorder regex replacements to prevent accidental decoding.
By restoring %25 to % before restoring {, }, and ^, explicitly encoded characters like %7B will be unintentionally decoded into {, violating the "never decoding" contract.
For example:
- Input:
%7B commonEncodeencodes it to%257B.replace(ENC_PERCENT_RE, '%')restores it to%7B.replace(ENC_CURLY_OPEN_RE, '{')matches the restored%7Band replaces it with{.
By moving the % restoration to the end of the chain, commonEncode's %257B will safely bypass the curly-brace replace (since it doesn't match %7B) and then correctly restore to %7B.
🐛 Proposed fix
commonEncode(text)
- // restore every original %, so pre-encoded sequences pass through
- .replace(ENC_PERCENT_RE, '%')
.replace(ENC_CURLY_OPEN_RE, '{')
.replace(ENC_CURLY_CLOSE_RE, '}')
.replace(ENC_CARET_RE, '^')
+ // restore every original %, so pre-encoded sequences pass through.
+ // done last so explicitly encoded chars like %7B bypass the replaces above
+ .replace(ENC_PERCENT_RE, '%')📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // restore every original %, so pre-encoded sequences pass through | |
| .replace(ENC_PERCENT_RE, '%') | |
| .replace(ENC_CURLY_OPEN_RE, '{') | |
| .replace(ENC_CURLY_CLOSE_RE, '}') | |
| .replace(ENC_CARET_RE, '^') | |
| // restore every original %, so pre-encoded sequences pass through | |
| .replace(ENC_CURLY_OPEN_RE, '{') | |
| .replace(ENC_CURLY_CLOSE_RE, '}') | |
| .replace(ENC_CARET_RE, '^') | |
| // restore every original %, so pre-encoded sequences pass through. | |
| // done last so explicitly encoded chars like %7B bypass the replaces above | |
| .replace(ENC_PERCENT_RE, '%') |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/router/src/experimental/encoding.ts` around lines 32 - 36, Reorder
the replacement chain in the encoding logic so ENC_CURLY_OPEN_RE,
ENC_CURLY_CLOSE_RE, and ENC_CARET_RE are restored before ENC_PERCENT_RE. Keep
percent restoration last, ensuring values such as %257B become %7B without being
decoded into literal characters.
The experimental router no longer decodes the hash.
route.hashis exactly what appears in the URL, likelocation.hash.encodeHashonly escapes unsafe characters (space,",<,>, backtick, non-ASCII). Existing percent sequences and lone%are kept, so it never double-encodes and resolving a resolved location changes nothing.This keeps
%26and&distinct and avoids the bug behind nuxt/nuxt#32774 / #2756 (experimental only, v4 unchanged).src/experimental/encoding.ts: definesencodeHash, re-exports the rest from the legacy module to avoid bundle duplication.decodeURIComponent(route.hash).NEW_stringifyURLfromsrc/location.ts.Size:
webRouter_experimental.jsmin 16.43kb -> 16.52kb.