Skip to content

quick-review - Fix missing emoji in toast notification#9158

Merged
SunsetTechuila merged 1 commit into
mainfrom
em
Apr 4, 2026
Merged

quick-review - Fix missing emoji in toast notification#9158
SunsetTechuila merged 1 commit into
mainfrom
em

Conversation

@SunsetTechuila
Copy link
Copy Markdown
Member

@SunsetTechuila SunsetTechuila commented Apr 4, 2026

Fixes #9156

Test URLs

Screenshot

Comment thread source/features/quick-review.tsx
@SunsetTechuila
Copy link
Copy Markdown
Member Author

Here is a sane explanation:

The Problem: UTF-16 Surrogate Pairs

JavaScript strings are encoded in UTF-16, not Unicode code points. Most emojis require two UTF-16 code units (a surrogate pair) to represent a single character.

The spread operator [...str] is supposed to be Unicode-aware — and it is for simple emojis. That's why most emojis in your result look correct.

Why the count is 17 instead of 14

The 3 extra elements come from multi-codepoint emojis — specifically emojis built from sequences joined by a Zero Width Joiner (ZWJ, U+200D) or variation selectors / modifier sequences.

For example:

  • 🏳️‍🌈 is actually: 🏳 + (variation selector) + (ZWJ) + 🌈 — multiple codepoints
  • 🏁 (checkered flag) can be a flag sequence: two Regional Indicator codepoints combined

[...str] splits by Unicode code points, so it correctly handles surrogate pairs, but it cannot keep ZWJ sequences together — it splits them into their individual constituent codepoints, producing extra array elements.

Quick illustration

const flag = "🏳️‍🌈";
console.log(flag.length);      // 6 (UTF-16 code units)
console.log([...flag].length); // 4 (code points: 🏳 + ️ + ZWJ + 🌈)
// spread still splits the ZWJ sequence into 4 separate elements

The fix: Intl.Segmenter

const str = '🚀🐿⚡🍌🥹🤩😡🤓😎🐻🚢✈️🏁🏁';
const emojis = [...new Intl.Segmenter().segment(str)].map(s => s.segment);
console.log(emojis.length); // 14 ✓

Intl.Segmenter understands grapheme cluster boundaries — it keeps ZWJ sequences, variation selectors, and modifier sequences together as a single perceived character.

Summary

Method Splits on Handles surrogate pairs Handles ZWJ sequences
str[i] / .length UTF-16 code units
[...str] Unicode code points
Intl.Segmenter Grapheme clusters

@fregante
Copy link
Copy Markdown
Member

fregante commented Apr 4, 2026

That still doesn't explain it 😅

The explanation is that those extra characters are asking the renderer to render an emoji instead of the non-colored glyph

@SunsetTechuila SunsetTechuila merged commit 37230c8 into main Apr 4, 2026
14 checks passed
@SunsetTechuila SunsetTechuila deleted the em branch April 4, 2026 14:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Development

Successfully merging this pull request may close these issues.

quick-review - Emoji sometimes missing from toast

2 participants