Насколько хорошо поддерживается Node.js для Unicode?

В соответствии со спецификацией JavaScript имеет некоторые проблемы с Unicode (если я правильно понимаю), поскольку текст всегда обрабатывается как один символ, состоящий из из 16 бит внутри.

JavaScript: Хорошие части говорят аналогичным образом.

При поиске в Google для поддержки V8 UTF-8 вы получаете противоречивые заявления.

Итак: Каково состояние поддержки Unicode в Node.js(0.10.26 была текущей версией, когда задавался этот вопрос)? Он обрабатывает UTF-8 все возможные кодовые точки правильно или не так?

Если нет: какие возможные обходные пути?

Ответ 1

Два источника, которые вы цитируете, спецификация языка и Crockford "JavaScript: Хорошие детали" (стр. 103) говорят то же самое, хотя последний говорит это гораздо более кратко (и, очевидно, если вы уже знаете предмет). Для справки я приведу Крокфорда:

JavaScript был разработан в то время, когда Unicode должен был иметь не более 65 536 символов. С тех пор он вырос до 1 миллиона символов.

Знаки JavaScript - 16 бит. Этого достаточно, чтобы покрыть оригинал 65 536 (который теперь известен как базовый многоязычный самолет). Каждый из оставшихся миллионов символов может быть представлен как пара символов. Unicode считает пару единственным символом. JavaScript считает, что пара представляет собой два разных символа.

Спецификация языка называет 16-битный блок "символом" и "блоком кода". С другой стороны, символ "Юникод" или "кодовая точка" может (в редких случаях) нуждаться в двух 16-битных "кодовых единицах", которые должны быть представлены.

Все свойства и методы строки JavaScript, такие как length, substr() и т.д., работают с 16-разрядными "символами" (было бы очень неэффективно работать с 16-битными/32-разрядными символами Unicode, т.е. символы UTF-16). Например, это означает, что если вы не будете осторожны, с substr() вы можете оставить одну половину только 32-битного символа Unicode UTF-16. JavaScript не будет жаловаться, пока вы его не отобразите, и, возможно, даже не пожалуется, если вы это сделаете. Это связано с тем, что, как указано в спецификации, JavaScript не проверяет правильность символов UTF-16, он предполагает, что они есть.

В своем вопросе вы спрашиваете

Выполняет ли [ Node.js] UTF-8 все возможные кодовые точки правильно или не так?

Поскольку все возможные кодовые точки UTF-8 преобразуются в UTF-16 (как один или два 16-разрядных "символа" ) во входном сигнале до того, как что-либо еще происходит, и наоборот, на выходе, ответ зависит от того, что вы подразумеваете под "правильно", но если вы принимаете JavaScript-интерпретацию этого "правильно", ответ "да".

Ответ 2

Тип строки JavaScript - это UTF-16, поэтому его поддержка Unicode составляет 100%. Все UTF формы поддерживают все кодовые точки Unicode.

Вот общий разбив общих форм:

  • UTF-8 - 8-битные кодовые единицы; переменная ширина (кодовые точки составляют 1-4 кода)
  • UTF-16 - 16-разрядные коды; переменная ширина (кодовые точки - 1-2 единицы кода); big- endian или little-endian
  • UTF-32 - 32-битные коды; фиксированная ширина; big-endian или little endian

UTF-16 был популяризирован, когда считалось, что каждая точка кода будет соответствовать 16 бит. Это был не тот случай. UTF-16 был позже переработан, чтобы позволить кодовым точкам принимать два блока кода, а старая версия была переименована в UCS-2.

Однако оказывается, что видимые ширины не очень хорошо приравниваются к блокам памяти, так что UTF-16 и UTF-32 имеют ограниченную полезность. Естественный язык является сложным, и во многих случаях последовательности кодовых точек объединяются удивительным образом.

Измерение ширины для символа зависит от контекста. Память? Количество видимых графем? Ширина рендеринга в пикселях?

UTF-16 остается общепринятым, потому что многие из современных популярных языков/сред (Java/JavaScript/Windows NT) родились в 90-х годах. Он не сломан. Однако предпочтительным является UTF-8.

Если вы страдаете от проблемы потери/повреждения данных, это обычно происходит из-за дефекта транскодера или неправильного использования одного из них.