如何在google v8(和nodejs)中呈现32位unicode字符

有没有人有一个想法,如何在谷歌V8,同时驱动谷歌浏览器和nodejs的JavaScript虚拟机,呈现unicode“星平面”字符(其CID超出0xffff)?

有趣的是,当我给谷歌浏览器(它标识为11.0.696.71,在Ubuntu 10.4上运行)这样的HTML页面:

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

它将正确地呈现“宽”字符𡥂与“窄”字符一起,但是当我在nodejs(使用console.log() )中尝试相当于我得到一个单一的 (0xfffd,replace字符)字符代替。

我也被告知,无论不可理解的原因,谷歌已决定使用16位宽的数据types来实现字符。 虽然我觉得这很愚蠢,但代理码点的devise恰恰是为了使'星际码点'通过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规范的braindead部分似乎要求? /不彻底禁止? /允许? 使用代理对,那么也许我的源文件编码(utf-8)可能是问题的一部分。 毕竟,在utf-8中有两种编码32位编码点的方法:一种是写出第一个替代品需要的utf-8字节,然后是第二个替代品所需的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> 

这似乎表明parsingutf-8与超出0xffff CID并输出这些字符到控制台是打破。 python3.1,顺便说一句,将字符视为代理对,并可以将字符打印到控制台。

注意我已经把这个问题交给了v8用户邮件列表 。

这个最近的报告涵盖了stream行语言中Unicode的各种问题,而且对Javascript不友好: 好,坏,(大部分)丑陋

他用Javascript的双字节表示法来解决这个问题:

UTF-16néeUCS-2诅咒

像其他几种语言一样,Javascript遭受UTF-16诅咒。 除了Javascript有一个更糟糕的forms,UCS-2诅咒。 像charCodeAt和fromCharCode这样的东西只能处理16位数量,而不能处理真正的21位Unicode代码点。 因此,如果你想打印出一些像𝒜,U + 1D49C,MATHEMATICAL SCRIPT CAPITAL A这样的东西,你必须指定不是一个字符,而是两个“字符单位”:“\ uD835 \ uDC9C”。 😱

 // ERROR!! document.write(String.fromCharCode(0x1D49C)); // needed bogosity document.write(String.fromCharCode(0xD835,0xDC9C)); 

我认为这是一个console.log问题。 由于console.log仅用于debugging,当你通过http输出节点到浏览器时,你是否也遇到同样的问题?

Interesting Posts