Pytanie Jak dobrze obsługuje Node.js w Unicode?


Według jego specyfikacja językowa JavaScript ma pewne problemy z Unicode (jeśli rozumiem to poprawnie), ponieważ tekst jest zawsze traktowany jako jeden znak składający się z 16 bitów wewnętrznie.

JavaScript: dobre części mówi w podobny sposób.

Gdy wyszukujesz wsparcie Google dla V8 dla UTF-8, dostajesz sprzeczne stwierdzenia.

A więc: Jaki jest stan obsługi Unicode w Node.js (0.10.26 była aktualną wersją po zadaniu tego pytania)? Czy obsługuje on kodowanie UTF-8 poprawnie we wszystkich możliwych punktach, czy nie?

Jeśli nie: Jakie są możliwe rozwiązania?


11
2018-03-20 19:36


pochodzenie




Odpowiedzi:


Dwa źródła, które cytujesz, specyfikacja językowa "JavaScript: dobre części" Crockforda (strona 103) mówią to samo, chociaż ten drugi mówi o wiele bardziej zwięźle (i oczywiście, jeśli już znasz temat). Dla odniesienia przytoczę Crockford:

JavaScript został zaprojektowany w czasie, gdy oczekiwano, że kod Unicode będzie mieć najwyżej 65 536 znaków. Od tego czasu ma pojemność ponad 1 miliona znaków.

Skrypty JavaScript mają 16 bitów. To wystarcza, aby pokryć oryginalną 65.536 (która jest teraz znana jako Podstawowa płaszczyzna wielojęzyczna). Każdy z pozostałych milionów znaków może być przedstawiony jako para znaków. Unicode uważa, że ​​para jest pojedynczym znakiem. JavaScript uważa, że ​​para to dwa odrębne znaki.

Specyfikacja języka określa jednostkę 16-bitową jako "znak" i "jednostkę kodu". Z drugiej strony "znak Unicode" lub "punkt kodowy" może (w rzadkich przypadkach) wymagać przedstawienia dwóch 16-bitowych "jednostek kodu".

Wszystkie właściwości i metody łańcuchów JavaScript, takie jak length, substr()itp., pracują z 16-bitowymi "znakami" (praca z 16-bitowymi / 32-bitowymi znakami Unicode, tzn. ze znakami UTF-16 byłaby bardzo nieefektywna). Np. Oznacza to, że jeśli nie jesteś ostrożny, z substr() możesz zostawić jedną połowę 32-bitowego znaku Unicode UTF-16. JavaScript nie będzie narzekać, dopóki go nie wyświetlisz, a może nawet nie będzie narzekać, jeśli to zrobisz. Dzieje się tak, ponieważ zgodnie ze specyfikacją JavaScript działa nie sprawdź, czy znaki są poprawne tylko w UTF-16 zakłada oni są.

W pytaniu pytasz

Czy [Node.js] obsługuje UTF-8 poprawnie we wszystkich możliwych punktach kodowania, czy nie?

Ponieważ wszystkie możliwe codepointy UTF-8 są konwertowane na UTF-16 (jako jeden lub dwa 16-bitowe "znaki") w danych wejściowych zanim cokolwiek innego się stanie, i odwrotnie na wyjściu, odpowiedź zależy od tego, co masz na myśli przez "poprawnie", ale jeśli zaakceptujesz interpretację JavaScriptu tego "poprawnie", odpowiedź brzmi "tak".


9
2018-03-26 23:50





Typ ciągu JavaScript to UTF-16, więc obsługa Unicode jest w 100%. Wszystko UTF formularze obsługują wszystkie punkty kodowe Unicode.

Oto ogólny podział wspólnych formularzy:

  • UTF-8 - 8-bitowe jednostki kodowe; zmienna szerokość (punkty kodowe to 1-4 jednostki kodu)
  • UTF-16 - 16-bitowe jednostki kodowe; zmienna szerokość (punkty kodowe to 1-2 jednostki kodu); duży-endian lub little-endian
  • UTF-32 - 32-bitowe jednostki kodowe; stała szerokość; big-endian lub little endian

UTF-16 został spopularyzowany, gdy uznano, że każdy kod pasowałby do 16 bitów. Tak nie było. UTF-16 został później przeprojektowany, aby umożliwić punktom kodowym pobranie dwóch jednostek kodu, a stara wersja została zmieniona na UCS-2. 

Okazuje się jednak, że widoczne szerokości nie są zbyt dobre dla jednostek pamięci, więc zarówno UTF-16, jak i UTF-32 mają ograniczoną użyteczność. Język naturalny jest złożony iw wielu przypadkach sekwencje punktów kodowych łączą się w zaskakujący sposób.

Pomiar szerokości dla "znaku" zależy od kontekstu. Pamięć? Liczba widocznych grafemów? Szerokość renderowania w pikselach?

UTF-16 pozostaje w powszechnym użyciu, ponieważ wiele dzisiejszych popularnych języków / środowisk (Java / JavaScript / Windows NT) urodziło się w latach dziewięćdziesiątych. Nie jest zepsuty. Jednak zwykle preferowane jest UTF-8.

Jeśli masz problem z utratą danych / korupcją, jest to zwykle spowodowane wadą transkodera lub niewłaściwym użyciem jednego z nich.


0
2018-03-20 20:12



Ale UTF-16 jest czymś zupełnie innym niż 16 bitów dla każdego znaku: UTF-16 dynamicznie używa 16 lub 32 bitów, podczas gdy JavaScript AFAIK używa statycznie 16 bitów. A więc: IMHO JavaScript nie używa UTF-16, a wszystkie linki, które podałem, również tak mówią. Czy masz jakieś zaktualizowane źródła? - Golo Roden
Długość łańcucha znaków w kodzie JavaScript to liczba kodu jednostki (z których każdy ma 16 bitów szerokości w UTF-16.) Kod punkt (Znak Unicode, jeśli chcesz) może być jednym lub dwoma kodami jednostki w UTF-16. Tak więc pojedynczy kod punkt może mieć długość 2 w JavaScript. Tak działa UTF-16. JavaScript obsługuje kodowanie UTF-16 zgodnie z sekcją 4.3.16 Wartości ciągów w ECMA 262. Myślę, że autorzy, których cytujesz, krytykują UTF-16, a nie zgodność z JavaScriptem UTF-16. W ten sposób łańcuchy działają również w językach C # i Java. - McDowell