有没有人知道如何在google v8中渲染unicode'星界'字符(其CID超出0xffff),javascript vm同时驱动google chrome和nodejs?
有趣的是,当我给谷歌chrome(它标识为11.0.696.71,在ubuntu 10.4上运行)这样的html页面时:<script>document.write( "helo" )
document.write( " ⿸子" );
</script>
它将正确地呈现'宽'字符和'窄'字符,但是当我在nodejs中尝试等效时(使用console.log()
)我得到一个 (0xfffd,REPLACEMENT CHARACTER)'相反,广泛的性格。
我也被告知,出于任何不可理解的原因,谷歌决定使用16位宽的数据类型来实现字符。虽然我觉得愚蠢,但surrogate codepoints的设计恰恰是为了通过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规范,这是首选方式)是计算得到的代码点并写出该代码点所需的八位字节。所以在这里我完全排除源文件编码的问题,只处理数字。上面的代码与Chrome中的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 ) );
我确实在谷歌浏览器窗口和控制台上获得了正确的结果:
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>
这似乎表明,使用超出0xffff
的CID解析utf-8并将这些字符输出到控制台都会被破坏。顺便说一句,python 3.1将字符视为代理对,并可以将字符打印到控制台。
注意我已将此问题交叉发布到v8-users mailing list。
答案 0 :(得分:10)
最近的演示文稿涵盖了流行语言中Unicode的各种问题,并且不适合Javascript:The Good, the Bad, & the (mostly) Ugly
他用Javascript中的Unicode双字节表示来解决这个问题:
UTF-16néeUCS-2诅咒
像其他几种语言一样,Javascript 患有UTF-16诅咒。除了Javascript有一个偶数 更糟糕的形式,UCS-2诅咒。像charCodeAt和 fromCharCode只处理16位数量,而不是真实的, 21位Unicode代码点。因此,如果要打印出来 比如,U + 1D49C,MATHEMATICAL SCRIPT CAPITAL A,你必须这样做 指定不是一个字符而是两个“char单元”:“\ uD835 \ uDC9C”。
// ERROR!!
document.write(String.fromCharCode(0x1D49C));
// needed bogosity
document.write(String.fromCharCode(0xD835,0xDC9C));
答案 1 :(得分:2)
我认为这是一个console.log问题。由于console.log仅用于调试,因此从节点通过http输出到浏览器时会出现同样的问题吗?