fix(page-tree): map NULL to U+FFFD in escapeCssIdentifier - #309
Open
shuvamk wants to merge 1 commit into
Open
Conversation
escapeCssIdentifier vendors the CSS.escape algorithm but omitted its first step — a NULL (U+0000) must serialize to the U+FFFD replacement character. The control-character branch starts at U+0001, so a NULL fell through to the generic case and was emitted as a backslash followed by a literal NULL byte, diverging from the browser's native CSS.escape. Add the missing branch and cover escapeCssIdentifier directly (it had no tests): NULL, control chars, leading digit, leading dash, and passthrough. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
escapeCssIdentifieris a vendored implementation of the CSS.escape algorithm (CSSOM §serialize-an-identifier), used to build class-kind selectors (styleRule.ts) and class-attribute tokens. It implements every step of the spec except step 1: "If the character is NULL (U+0000), then append U+FFFD REPLACEMENT CHARACTER to result."The control-character branch deliberately starts at
U+0001:so a
U+0000matches no branch and falls through to the genericescaped += '\\' + char, emitting a backslash followed by a literal NULL byte. The browser's nativeCSS.escapemapsU+0000toU+FFFDinstead.Reproduction
CSS.escape/ specU+0000\+ literalU+0000U+FFFDa,U+0000,ba\+U+0000+ba+U+FFFD+bEvery other step (control chars, DEL, leading digit,
-+digit, lone-, allowed set, escape-as-char) already matches the spec — this is a single missing branch.Fix
Add the
U+0000→U+FFFDbranch as the first step of the per-code-unit loop, exactly where the spec places it.The function had no direct test coverage, so this adds one alongside the fix — NULL, control characters, leading digit, digit-after-dash, lone dash, and passthrough — all matching native
CSS.escape. The test is co-located undersrc/core/page-tree/__tests__/and imports the helper relatively, so it neither expands the module barrel nor trips the deep-import gate.Verification
bun run buildbun test(6337 pass, 0 fail; the NULL case fails onmainand passes with the fix)bun run lintChecklist