- From: Kang-Hao (Kenny) Lu <kennyluck@w3.org>
- Date: Tue, 20 Sep 2011 17:40:07 +0800
- To: 中文HTML5同樂會ML <public-html-ig-zh@w3.org>
(11/06/17 16:18), Kang-Hao (Kenny) Lu wrote: > 花了不少時間多做了一點研究,分成兩篇,這篇講現象與實作。 > > 我也要對以下這個表達震驚: > > HTML5 規範裡表單的 maxlength 屬性有考慮到這個東西(請參考代碼點長 > 度(code-point length)的定義),而且 webkit 也實作出來了。 > 之前討論這個[1]問題講的時候著重在實作的部份,其實規範上有一點含糊的地 方,我也有回報這個部份[2],因此來跟各位交流一下(順便炫耀一下 目前 HTML5 規範的翻譯進度 xd)。 [1] http://lists.w3.org/Archives/Public/public-html-ig-zh/2011Jun/0050 [2] http://www.w3.org/Bugs/Public/show_bug.cgi?id=13676 首先 maxlength 屬性的定義[3]那邊有提到「元素取值的代碼點(code point)長 度大於元素的最大容許取值長度」是它不過驗證的條件,而代碼點長度的定義[4] 是「字串有的 Unicode 代碼點的個數」,但是一個字串的代碼點長度其實在某些 情形下定義是很模糊的。 [3] http://www.w3.org/html/ig/zh/wiki/HTML5#attr-fe-maxlength [4] http://www.w3.org/html/ig/zh/wiki/HTML5#code-point-length 用幾個例子來討論: 1. <input maxlength="2" value="林𠂇" />(假人名) HTML5 用粗體(<dfn>)定義了很多內部使用的變數,很多地方沒有講這些變數是 32 位元還是 16 位元,不過在描述解析的部份似乎都假設各個字串變數是 32 位 元字串。所以上述的 HTML 不管原來的編碼是什麼,input 的「取值」[5]都是 32 位元的兩個字符/Unicode 代碼點,所以上述片段根據規範敘述應該符合驗證條件。 [5] http://www.w3.org/html/ig/zh/wiki/HTML5#concept-fe-value 2. input.maxLength = 2 的時候又有 input.value = "林𠂇" 這時候就麻煩了,因為基本上 ECMAScript 裡面的描述很少用到代碼點來定義行 為,而直接用 16 位元代碼單元(code unit)來定義 String.prototype.length 什麼的,事實各個 JS API(那些 IDL 定義框)裡面用的 DOMString 在 WebIDL(描述 DOM API 的語言,待翻 xd)下的定義[6]就是 16 位元的字串。所 以對於 .value 這個 IDL 屬性在設置[7]的時候,從 DOMString 到 input 元素的 「取值」其實有一個 16 位元字串到 32 位元字串的隱藏轉換(理論上的,因為事 實上實作全是用 16 位元),而這個隱藏轉換應該明確寫在規範裡。 [6] http://dev.w3.org/2006/webapi/WebIDL/#idl-DOMString [7] http://www.whatwg.org/specs/web-apps/current-work/multipage/common-input-element-attributes.html#dom-input-value-value (到這邊就沒翻譯了 T__T) 另一種方法是定義元素的「取值」為 16 位元字串,這雖然在應付 1. 不是很難 (解析串流的 32 位元字串要轉 16 位元字串就比較明顯是用 UTF-16),但是要 定義一個 16 位元字串的 Unicode 代碼點長度,就要確保以下這種畸形情形也有 明確定義: 3. input.maxLength = 2 的時候 input.value = "\ud840𠂇"(\ud840 是一個代 理代碼點(surrogate code point)) 而目前的規範沒有很明白的說「\ud840」究竟是算 1 個還是 0 個,其實我覺得連 「𠂇」都不能確定他的代碼點長度是算 1 而不是 2,畢竟代碼點是一個抽象概 念,不像代碼單位那麼具體。 所以我在[2]裡面提到了兩個規範的修正方法: 修正方法一:定義代碼點長度的句子「字串有的 Unicode 代碼點的個數」,應該 像 Java 的 String.codePointCount 的定義[8]一樣加上「1 個未配對的代理點算 1 個 Unicode 代碼點」(unpaired surrogates count as one Unicde code point each) [8] (似乎須翻牆)http://download.oracle.com/javase/1,5.0/docs/api/java /lang /String.html#codePointCount%28int,%20int%29 修正方法二:不要管「代碼點長度」是不是「代碼點」的「長度」,總之定義「代 碼點長度」為先透過[9]的演算法轉成不含代理點的 Unicode 字符串列,再計算它 的長度,這基本上也是把前述的「16 位元字串到 32 位元字串的隱藏轉換」寫下來。 [9] http://dev.w3.org/2006/webapi/WebIDL/#dfn-obtain-unicode 總得來說,我覺得規範最好把每個內用變數是 32 位元還是 16 位元講清楚比較 好...... 此致 呂 康豪(Kenny), 中文興趣小組W3C連絡人 Google+: https://plus.google.com/112088462407783855918/posts 新浪微博: http://t.sina.com.cn/1950042164
Received on Tuesday, 20 September 2011 09:40:50 UTC