@@ -1514,11 +1514,16 @@ export function attach(
1514
1514
1515
1515
type OperationsArray = Array < number > ;
1516
1516
1517
+ type StringTableEntry = { |
1518
+ encodedString : Array < number > ,
1519
+ id : number ,
1520
+ | } ;
1521
+
1517
1522
const pendingOperations : OperationsArray = [ ] ;
1518
1523
const pendingRealUnmountedIDs : Array < number > = [ ] ;
1519
1524
const pendingSimulatedUnmountedIDs : Array < number > = [ ] ;
1520
1525
let pendingOperationsQueue : Array < OperationsArray > | null = [ ] ;
1521
- const pendingStringTable : Map < string , number > = new Map ( ) ;
1526
+ const pendingStringTable : Map < string , StringTableEntry > = new Map ( ) ;
1522
1527
let pendingStringTableLength : number = 0 ;
1523
1528
let pendingUnmountedRootID : number | null = null ;
1524
1529
@@ -1736,13 +1741,19 @@ export function attach(
1736
1741
// Now fill in the string table.
1737
1742
// [stringTableLength, str1Length, ...str1, str2Length, ...str2, ...]
1738
1743
operations [ i ++ ] = pendingStringTableLength ;
1739
- pendingStringTable . forEach ( ( value , key ) => {
1740
- operations [ i ++ ] = key . length ;
1741
- const encodedKey = utfEncodeString ( key ) ;
1742
- for ( let j = 0 ; j < encodedKey . length ; j ++ ) {
1743
- operations [ i + j ] = encodedKey [ j ] ;
1744
+ pendingStringTable . forEach ( ( entry , stringKey ) => {
1745
+ const encodedString = entry . encodedString ;
1746
+
1747
+ // Don't use the string length.
1748
+ // It won't work for multibyte characters (like emoji).
1749
+ const length = encodedString . length ;
1750
+
1751
+ operations [ i ++ ] = length ;
1752
+ for ( let j = 0 ; j < length ; j ++ ) {
1753
+ operations [ i + j ] = encodedString [ j ] ;
1744
1754
}
1745
- i += key.length;
1755
+
1756
+ i += length;
1746
1757
} ) ;
1747
1758
1748
1759
if ( numUnmountIDs > 0 ) {
@@ -1789,21 +1800,31 @@ export function attach(
1789
1800
pendingStringTableLength = 0 ;
1790
1801
}
1791
1802
1792
- function getStringID ( str : string | null ) : number {
1793
- if ( str === null ) {
1803
+ function getStringID ( string : string | null ) : number {
1804
+ if ( string === null ) {
1794
1805
return 0 ;
1795
1806
}
1796
- const existingID = pendingStringTable . get ( str ) ;
1797
- if ( existingID !== undefined ) {
1798
- return existingID ;
1799
- }
1800
- const stringID = pendingStringTable . size + 1 ;
1801
- pendingStringTable . set ( str , stringID ) ;
1802
- // The string table total length needs to account
1803
- // both for the string length, and for the array item
1804
- // that contains the length itself. Hence + 1.
1805
- pendingStringTableLength += str . length + 1 ;
1806
- return stringID ;
1807
+ const existingEntry = pendingStringTable . get ( string ) ;
1808
+ if ( existingEntry !== undefined ) {
1809
+ return existingEntry . id ;
1810
+ }
1811
+
1812
+ const id = pendingStringTable . size + 1 ;
1813
+ const encodedString = utfEncodeString ( string ) ;
1814
+
1815
+ pendingStringTable . set ( string , {
1816
+ encodedString ,
1817
+ id ,
1818
+ } ) ;
1819
+
1820
+ // The string table total length needs to account both for the string length,
1821
+ // and for the array item that contains the length itself.
1822
+ //
1823
+ // Don't use string length for this table.
1824
+ // It won't work for multibyte characters (like emoji).
1825
+ pendingStringTableLength += encodedString . length + 1 ;
1826
+
1827
+ return id ;
1807
1828
}
1808
1829
1809
1830
function recordMount ( fiber : Fiber , parentFiber : Fiber | null ) {
0 commit comments