એક વિડ્થ ચેક (Width Check) એ કહ્યું કે સ્ટ્રિંગ કાપવા માટે સુરક્ષિત છે, પરંતુ તેણે એક કાંજી (Kanji) ને અડધી કરી નાખી.
એક નામ ટર્મિનલ ટેબલમાં દાખલ કરવામાં આવ્યું અને તે તૂટેલું બહાર આવ્યું. અટક 𠮷田 હતી.
પ્રથમ અક્ષર સામાન્ય 吉 નથી. તે 𠮷 (U+20BB7) છે. આ જાપાનીઝ કુટુંબના નામોમાં વપરાતું એક દુર્લભ સ્વરૂપ છે. ટેબલે કોલમમાં સમાવવા માટે સેલને ટ્રંકેટ (truncate) કરી દીધો. તેના કારણે એક તૂટેલો અક્ષર રહી ગયો.
આ બગ (bug) કોડની માત્ર એક જ લાઇન માં હતો. તે એક ઓપ્ટિમાઇઝેશન હતું જેણે નક્કી કર્યું કે સ્ટ્રિંગને ઇન્ડેક્સ (index) દ્વારા કાપવી સુરક્ષિત છે.
JavaScript સ્ટ્રિંગની ત્રણ અલગ-અલગ લંબાઈ હોય છે: • કોડ યુનિટ્સ (Code units) (.length): "𠮷".length એ 2 છે. • કોડ પોઈન્ટ્સ (Code points): [..."𠮷"].length એ 1 છે. • ડિસ્પ્લે વિડ્થ (Display width): 𠮷 એ 2 કોલમ રોકે છે.
પ્રમાણભૂત અંગ્રેજી લખાણ માટે, આ બધી સંખ્યાઓ સમાન હોય છે. આ સંયોગને કારણે કોડ સુરક્ષિત લાગે છે.
𠮷 અક્ષર આ નિયમ તોડે છે. તેમાં 2 કોડ યુનિટ્સ છે કારણ કે તે એક સરોગેટ પેર (surrogate pair) છે. તેમાં 2 કોલમ છે કારણ કે તે એક વાઈડ (wide) અક્ષર છે. આ સંખ્યાઓ મેચ થાય છે (2 = 2), પરંતુ અલગ કારણોસર.
cli-table3 લાઇબ્રેરીએ ફાસ્ટ પાથ (fast path) નો ઉપયોગ કર્યો:
જો કોડ યુનિટની લંબાઈ ડિસ્પ્લે વિડ્થ જેટલી હોય, તો સ્ટ્રિંગને ઇન્ડેક્સ દ્વારા કાપો.
આ વર્ષો સુધી કામ કરી ગયું કારણ કે 漢 જેવા સામાન્ય જાપાનીઝ અક્ષરોની લંબાઈ 1 અને વિડ્થ 2 હોય છે. તેઓ ક્યારેય ફાસ્ટ પાથ સુધી પહોંચતા નથી.
ફાસ્ટ પાથ માત્ર 𠮷 અથવા ઇમોજી જેવા દુર્લભ અક્ષરો માટે જ ટ્રિગર થાય છે. આ અક્ષરોની લંબાઈ 2 અને વિડ્થ 2 હોય છે. કોડને લાગે છે કે તેઓ સાદા એક-યુનિટવાળા અક્ષરો છે. તે તેમને ઇન્ડેક્સ દ્વારા અડધા કરી નાખે છે. આનાથી એક એકલો સરોગેટ (surrogate) રહી જાય છે. આથી જ ટર્મિનલમાં તૂટેલો બોક્સ દેખાય છે.
આને સુધારવા માટે, તમારે:
- સરોગેટ પેરને બાકાત રાખવા માટે ફાસ્ટ પાથને ગાર્ડ (guard) કરવો જોઈએ.
- કોડ યુનિટ્સને બદલે કોડ પોઈન્ટ્સ દ્વારા ટ્રિમ (trim) કરવું જોઈએ.
Array.from(str) નો ઉપયોગ કરવાથી મદદ મળે છે કારણ કે તે કોડ પોઈન્ટ દ્વારા ઇટરેટ (iterate) કરે છે. આ સુનિશ્ચિત કરે છે કે તમે ક્યારેય અક્ષરને અડધો ન કરો.
પાઠ સરળ છે: ક્યારેય એક યુનિટથી માપો નહીં અને બીજા યુનિટથી કાપો નહીં. જો તમે ડિસ્પ્લે વિડ્થ અથવા કોડ પોઈન્ટ્સ માપો છો, તો તમારે તે જ યુનિટ્સનો ઉપયોગ કરીને કાપવું જોઈએ.
તમારા કોડને CJK Extension B અક્ષર અથવા ઇમોજી સાથે ટેસ્ટ કરો. ASCII ક્યારેય આ બગને બહાર લાવશે નહીં.
Optional learning community: https://greymoth-jp.github.io/cjk-failure-corpus/
