AssemblyScript が WebAssembly グループから非推奨にされてしまう可能性があるという話で、その前提の話になるUnicodeとサロゲートの話を聞く機会があったが全くわからなかったので自分なりに復習してみた
Unicodeとかサロゲートペアは以前調べてたが、特にサロゲートペアをつくるときにでてくるビッグエンディアンとかがわからなかった
Unicode
世界中の文字に2バイトの文字コード(符号化文字集合:文字の集合に符号を対応づけたもの)を割り当てて文字の表現を統一しようと作成された(1991年にv1.0リリース)
2バイトなので、65,536通り(U+0000~U+FFFF)の文字が表現できるが、文字を追加するうちに全然足りなくなった
そこでコードポイントを2バイト=16bitから21bit(U+0000~U+10FFFF)に拡張して、約100文字を収録可能にした
追加前と後で名前がついている
ただ、既にUnicdeは様々な言語で利用されていたので、21bitに拡張されたものを16bitとして扱わなければならない
サロゲートペア
非BMPを2つの16bitでエンコードすることにした(UTF-16エンコーディング)
具体的には従来のUnicodeで未使用だった0xD800~0xDBFF(1024通り)を「上位サロゲート」、0xDC00~0xDFFF(1024通り)を「下位サロゲート」と規定し、「上位サロゲート+下位サロゲート」の4バイトで文字を表現する
このサロゲートペアの導入により1024×1024=1,048,576字の領域が追加されることになった
エンコーディング
Unicode Scalar Values(USV)
コードポイントからサロゲート領域を除いたもの(文字が割り当てられているコードポイントの集合)
USVにはサロゲート領域を含まないが、UTF-16エンコードするとサロゲートペアが出現する
このとき、概念ではサロゲートペアは上位サロゲートと下位サロゲートのペアになっているはず(well-formed UTF-16)
ところが文字列にUTF-16を採用している一部のプログラミング言語では上位サロゲートと下位サロゲートが単独で出現できてしまう
> '𠮷野家'.substring(1) "\udfb7野家"
つまり、ペアになっていないサロゲート領域のコードユニットを含むUTF-16(ill-formed UTF-16)が存在する可能性がある
これはデコードしてもUSVにならない
WTF-16(WobblyTransformation Format - 16)
ill-formed UTF-16になる(単独のサロゲートを含む)可能性があるエンコーディングの通称
Java, JavaScript, C#などは実際はWTF-16(上記のsubstringの処理のようにill-formed UTF-16が存在できる)
WTFからUTFへの変換はできないので置換されることが多い(REPLACEMENT CHARACTER (U+FFFD))
これがやっかいなので、データのやりとりではWTFは扱わないようにしたいが、DOMやJsonのStoring型、JavaScriptなどはWTFなので、新しいWeb APIやデータ交換で問題になる可能性があるので注意が必要
まとめ
自分なりに咀嚼したらかなり理解できた
AssemblyScriptの話はこのWTF -> USV するとReplacementされる(もしくはエラーになる)よねという話で議論になったことをなんとなく理解した
他参考
https://blog.jxck.io/entries/2017-03-02/unicode-in-javascript.html