有谁知道如何在 google v8(驱动 google chrome 和 nodejs 的 javascript vm)中呈现 unicode 'astral plane' 字符(其 CID 超过 0xffff)?
有趣的是,当我给谷歌浏览器(它标识为 11.0.696.71,在 ubuntu 10.4 上运行)一个这样的 html 页面时:
<script>document.write( "helo" )
document.write( " ⿸子" );
</script>
它会正确地渲染“宽”字符和“窄”字符,但是当我在 nodejs 中尝试等效(使用console.log()
)时,我得到一个“宽”字符的 �(0xfffd,REPLACEMENT CHARACTER)。
我还被告知,出于任何不可理解的原因,谷歌决定使用 16 位宽的数据类型来实现字符。虽然我觉得这很愚蠢,但代理代码点的设计正是为了通过 16 位挑战路径实现“星体代码点”的“通道”。并且不知何故,在 chrome 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 位代码点有两种方法:一种是写出第一个代理所需的 utf-8 八位字节,然后是第二个代理所需的 utf-8 八位字节;另一种方式(这是首选方式,根据 utf-8 规范)是计算结果代码点并写出该代码点所需的八位字节。所以在这里我完全排除了源文件编码的问题,只处理数字。上面的代码确实可以document.write()
在 chrome 中使用,所以我知道我的数字是正确的。
叹。
编辑我做了一些实验,发现当我做的时候
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 ) );
我确实在谷歌浏览器中得到了正确的结果---在浏览器窗口和控制台上:
2
0xd864
0xdd0e
2
0xd864
0xdd0e
但是,这是我在使用 nodejs 时得到的console.log
:
<h1> � </h1>
<div> 1 </div>
<div>0x fffd </div>
<div>0x NaN </div>
<h1> �����</h1>
<div> 2 </div>
<div>0x d864 </div>
<div>0x dd0e </div>
这似乎表明解析带有 CID 的 utf-80xffff
并将这些字符输出到控制台都被破坏了。顺便说一句,python 3.1 确实将字符视为代理对,并且可以将字符打印到控制台。
注意我已将此问题交叉发布到v8-users 邮件列表。