विड्थ चेकने स्ट्रिंग कापण्यासाठी सुरक्षित असल्याचे सांगितले, पण त्याने एका कांजीचे दोन तुकडे केले.

एका टर्मिनल टेबलमध्ये एक नाव टाकले आणि ते तुटलेले बाहेर आले. आडनाव होते 𠮷田.

पहिले अक्षर सामान्य 吉 नाही. ते 𠮷 (U+20BB7) आहे. हे वास्तविक जपानी आडनावांमध्ये वापरले जाणारे एक दुर्मिळ रूप आहे. कॉलममध्ये बसवण्यासाठी टेबलने सेल ट्रंकेट (truncate) केला. यामुळे एक तुटलेले अक्षर मागे राहिले.

हा बग कोडच्या एकाच ओळीत होता. ते एक ऑप्टिमायझेशन (optimization) होते ज्याने ठरवले की स्ट्रिंग इंडेक्सनुसार (index) कापण्यासाठी सुरक्षित आहे.

JavaScript स्ट्रिंगची तीन वेगवेगळी लांबी असते: • कोड युनिट्स (Code units) (.length): "𠮷".length हे 2 आहे. • कोड पॉइंट्स (Code points): [..."𠮷"].length हे 1 आहे. • डिस्प्ले विड्थ (Display width): 𠮷 साठी 2 कॉलम्स लागतात.

प्रमाणित इंग्रजी मजकुरासाठी, हे सर्व अंक सारखेच असतात. या योगायोगामुळे कोड सुरक्षित वाटतो.

𠮷 हे अक्षर हा नियम मोडते. ते 'सरोगेट पेअर' (surrogate pair) असल्यामुळे त्याचे 2 कोड युनिट्स आहेत. ते 'वाईड कॅरेक्टर' (wide character) असल्यामुळे त्याचे 2 कॉलम्स आहेत. अंक जुळतात (2 = 2), पण वेगवेगळ्या कारणांमुळे.

cli-table3 लायब्ररीने 'फास्ट पाथ' (fast path) वापरला: जर कोड युनिटची लांबी डिस्प्ले विड्थच्या समान असेल, तर स्ट्रिंग इंडेक्सनुसार कापा.

हे अनेक वर्षे व्यवस्थित चालले कारण 漢 सारखी सामान्य जपानी अक्षरे यांची लांबी 1 आणि विड्थ 2 असते. ती कधीही 'फास्ट पाथ'ला स्पर्श करत नाहीत.

फास्ट पाथ फक्त 𠮷 किंवा इमोजींसारख्या दुर्मिळ अक्षरांसाठी सक्रिय होतो. या अक्षरांची लांबी 2 आणि विड्थ 2 असते. कोडला वाटते की ती साधी एक-युनिट अक्षरे आहेत. त्यामुळे तो इंडेक्सनुसार त्यांना मधून कापतो. यामुळे एक एकटा 'सरोगेट' मागे राहतो. म्हणूनच टर्मिनलमध्ये तुटलेला बॉक्स दिसतो.

हे सुधारण्यासाठी, तुम्हाला:

  • सरोगेट पेअर्स वगळण्यासाठी फास्ट पाथ सुरक्षित (guard) करावा लागेल.
  • कोड युनिट्सऐवजी कोड पॉइंट्सद्वारे ट्रिम (trim) करावे लागेल.

Array.from(str) वापरल्याने मदत होते कारण ते कोड पॉइंटनुसार इटरेशन (iterate) करते. यामुळे तुम्ही अक्षर कधीही मधून कापणार नाही याची खात्री मिळते.

धडा साधा आहे: कधीही एका युनिटने मोजू नका आणि दुसऱ्या युनिटने कापून टाकू नका. जर तुम्ही डिस्प्ले विड्थ किंवा कोड पॉइंट्स मोजत असाल, तर तुम्हाला त्याच युनिट्सचा वापर करून कापावे लागेल.

तुमचा कोड CJK Extension B अक्षर किंवा इमोजीसह तपासा. ASCII मुळे हा बग कधीही समोर येणार नाही.

Source: https://dev.to/greymothjp/a-width-check-said-the-string-was-safe-to-cut-it-split-a-kanji-in-half-4hjk

Optional learning community: https://greymoth-jp.github.io/cjk-failure-corpus/