Conversation
✅ Deploy Preview for eslint-code-explorer ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
amareshsm
left a comment
There was a problem hiding this comment.
LGTM. I’ll keep it open for another day in case anyone else wants to review.
There was a problem hiding this comment.
Pull request overview
Fixes explorer state persistence for Unicode-containing code by switching URL-hash serialization to a UTF-8-safe, versioned format while retaining backward compatibility with legacy hash links.
Changes:
- Add
v2:UTF-8-safe base64 encoding/decoding for persisted state stored in the URL hash, with legacy hash support preserved. - Harden hash reads by validating decoded payloads and falling back to
localStoragewhen malformed. - Add Playwright e2e coverage for Unicode hash persistence, legacy link loading, and malformed-hash fallback.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/hooks/use-explorer.ts | Introduces versioned UTF-8-safe hash encoding/decoding and legacy decoding fallback to prevent btoa Unicode errors. |
| e2e-tests/persistence.test.ts | Adds e2e tests covering Unicode-safe hash persistence, legacy hash compatibility, and malformed hash fallback behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const versionedHashPrefix = "v2:"; | ||
|
|
There was a problem hiding this comment.
Using versionedHashPrefix = "v2:" means URLSearchParams will percent-encode the colon in the hash value (and standard base64 will also trigger percent-encoding for +, /, =). This inflates shared URLs and reduces the maximum amount of state that can fit in the hash. Consider a URL-safe prefix/format (e.g., base64url) to avoid extra encoding overhead.
| let binary = ""; | ||
|
|
||
| for (const byte of bytes) { | ||
| binary += String.fromCharCode(byte); | ||
| } | ||
|
|
There was a problem hiding this comment.
encodeHashStorageValue builds a binary string via repeated binary += String.fromCharCode(byte) concatenation. This allocates/concats once per byte and can become expensive for larger persisted payloads (the editor state can grow quite large). Consider a chunked conversion strategy or a Uint8Array→base64 helper to reduce intermediate string churn.
| let binary = ""; | |
| for (const byte of bytes) { | |
| binary += String.fromCharCode(byte); | |
| } | |
| const chunkSize = 0x8000; // 32KB chunks to limit argument list size | |
| const chunks: string[] = []; | |
| for (let i = 0; i < bytes.length; i += chunkSize) { | |
| const chunk = bytes.subarray(i, i + chunkSize); | |
| chunks.push(String.fromCharCode(...chunk)); | |
| } | |
| const binary = chunks.join(""); |
There was a problem hiding this comment.
I've tested this logic locally, but I'm not sure it really improves performance. Any further thoughts?
lumirlumir
left a comment
There was a problem hiding this comment.
LGTM, thanks. I don't have any further comments, but the Copilot review is worth a look. I'll leave this open to get another opinion before merging.
| const versionedHashPrefix = "v2:"; | ||
|
|
| let binary = ""; | ||
|
|
||
| for (const byte of bytes) { | ||
| binary += String.fromCharCode(byte); | ||
| } | ||
|
|
There was a problem hiding this comment.
I've tested this logic locally, but I'm not sure it really improves performance. Any further thoughts?
Prerequisites checklist
AI acknowledgment
What is the purpose of this pull request?
This PR fixes explorer state persistence when the edited code contains Unicode characters. Previously, writing the shareable URL hash could throw
InvalidCharacterErrorbecause the app usedbtoa(...)on a string containing characters outside the Latin1 range.Steps to reproduce
What changes did you make? (Give an overview)
Related Issues
I ran into this while working on eslint/markdown#640, where I noticed that emojis in the editor were no longer present after a reload.
Is there anything you'd like reviewers to focus on?