9

Google Chromeとnodejsの両方を駆動するjavascript vmであるGoogle v8でUnicodeの「アストラルプレーン」キャラクター(CIDが0xffffを超えている)をレンダリングする方法を知っている人はいますか?

おかしなことに、Google Chrome(ubuntu 10.4で実行されている11.0.696.71として識別されます)に次のようなhtmlページを与えると:

<script>document.write( "helo" )
document.write( " ⿸子" );
</script>

「幅の広い」文字と「幅の狭い」文字を正しくレンダリングしますが、nodejs で (を使用してconsole.log()) 同等のものを試すと、代わりに「幅の広い」文字に対して 1 つの � (0xfffd, REPLACEMENT CHARACTER) が取得されます。

また、理解できない理由で、Googleが16ビット幅のデータ型を使用して文字を実装することを決定したとも言われました。ばかげていると思いますが、サロゲート コードポイントは、16 ビットの挑戦的な経路を介して「アストラル コードポイント」の「チャネリング」を可能にするように正確に設計されています。どういうわけか、クロム 11.0.696.71 内で実行されている v8 は、このビットの unicode-foo または他の魔法を使用してその作業を行っているようです (何年も前に、静的ページでも代わりに常にボックスを取得していたことを覚えているようです)。

ああ、そうです、node --versionレポートv0.4.10、そこから v8 バージョン番号を取得する方法を見つけなければなりません。

更新私はコーヒースクリプトで次のことを行いました:

a = String.fromCharCode( 0xd801 )
b = String.fromCharCode( 0xdc00 )
c = a + b
console.log a
console.log b
console.log c
console.log String.fromCharCode( 0xd835, 0xdc9c )

しかし、それは私に与えるだけです

���
���
������
������

この背後にある考え方は、Unicode を扱う JavaScript 仕様の脳死部分が義務付けられているように見えるからですか? /まったく禁止されていませんか?/許可しますか?サロゲート ペアを使用している場合、ソース ファイルのエンコーディング (utf-8) が問題の一部である可能性があります。結局、utf-8 で 32 ビット コードポイントをエンコードする方法は 2 つあります。もう 1 つの方法 (utf-8 仕様に従って推奨される方法) は、結果のコードポイントを計算し、そのコードポイントに必要なオクテットを書き出すことです。ここでは、数値のみを扱うことで、ソース ファイルのエンコーディングの問題を完全に除外します。上記のコードはdocument.write()クロムで動作し、 を与えるので、数字が正しいことがわかります。

はぁ。

編集私はいくつかの実験を行い、私が行うときにそれを発見しました

var f = function( text ) {
  document.write( '<h1>',  text,                                '</h1>'  );
  document.write( '<div>', text.length,                         '</div>' );
  document.write( '<div>0x', text.charCodeAt(0).toString( 16 ), '</div>' );
  document.write( '<div>0x', text.charCodeAt(1).toString( 16 ), '</div>' );
  console.log( '<h1>',  text,                                 '</h1>'  );
  console.log( '<div>', text.length,                          '</div>' );
  console.log( '<div>0x', text.charCodeAt(0).toString( 16 ),  '</div>' );
  console.log( '<div>0x', text.charCodeAt(1).toString( 16 ),  '</div>' ); };

f( '' );
f( String.fromCharCode( 0xd864, 0xdd0e ) );

私はGoogle Chromeで正しい結果を得ます---ブラウザウィンドウ内とコンソールの両方で:


2
0xd864
0xdd0e

2
0xd864
0xdd0e

ただし、これは nodejs' を使用したときに得られるものですconsole.log:

<h1> � </h1>
<div> 1 </div>
<div>0x fffd </div>
<div>0x NaN </div>
<h1> �����&lt;/h1>
<div> 2 </div>
<div>0x d864 </div>
<div>0x dd0e </div>

これは、CID を超える utf-8 の解析0xffffとそれらの文字のコンソールへの出力の両方が壊れていることを示しているようです。ちなみに、python 3.1 は文字をサロゲート ペアとして扱い、その文字をコンソールに出力できます。

: この質問をv8-users メーリング リストに相互投稿しま​​した。

4

2 に答える 2

10

この最近のプレゼンテーションでは、一般的な言語での Unicode に関するあらゆる種類の問題を取り上げており、Javascript には優しくありません: 良い点、悪い点、および (ほとんどの場合) 醜い点

彼は、Javascript での Unicode の 2 バイト表現に関する問題を取り上げています。

UTF-16旧UCS-2呪い

他のいくつかの言語と同様に、Javascript は UTF-16 の呪いに悩まされています。ただし、Javascript にはさらに悪い形である UCS-2 の呪いがあります。charCodeAt や fromCharCode などは、実際の 21 ビット Unicode コード ポイントではなく、16 ビット量のみを扱います。したがって、 , U+1D49C, MATHEMATICAL SCRIPT CAPITAL A のようなものを出力したい場合は、1 文字ではなく 2 つの「文字単位」を指定する必要があります: "\uD835\uDC9C".

// ERROR!! 
document.write(String.fromCharCode(0x1D49C));
// needed bogosity
document.write(String.fromCharCode(0xD835,0xDC9C));
于 2011-08-08T17:15:29.950 に答える
2

console.log の問題だと思います。console.log はデバッグ専用なので、node から http 経由でブラウザに出力するときに同じ問題がありますか?

于 2011-08-09T20:54:21.270 に答える