MIRROR: javascript for ๐Ÿœ's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

add codePointAt and improve charAt/charCodeAt handling

+62 -8
+11
examples/spec/strings.js
··· 52 52 test('repeat', 'ab'.repeat(3), 'ababab'); 53 53 54 54 test('charAt', 'hello'.charAt(1), 'e'); 55 + test('charAt default index', 'hello'.charAt(), 'h'); 56 + test('charAt coercion', 'hello'.charAt('1'), 'e'); 55 57 test('charCodeAt', 'ABC'.charCodeAt(0), 65); 58 + test('charCodeAt default index', 'ABC'.charCodeAt(), 65); 59 + test('charCodeAt coercion', 'ABC'.charCodeAt('1'), 66); 60 + test('codePointAt ascii', 'ABC'.codePointAt(0), 65); 61 + test('codePointAt default index', 'ABC'.codePointAt(), 65); 62 + test('codePointAt coercion', 'ABC'.codePointAt('1'), 66); 63 + test('codePointAt out of bounds', 'ABC'.codePointAt(10), undefined); 64 + test('codePointAt utf8 2-byte', 'รฉ'.codePointAt(0), 233); 65 + test('codePointAt utf8 3-byte', 'ไธญ'.codePointAt(0), 20013); 66 + test('codePointAt utf8 4-byte', '๐Ÿ˜€'.codePointAt(0), 128512); 56 67 57 68 test('replace', 'hello world'.replace('world', 'there'), 'hello there'); 58 69 test('replaceAll', 'a-b-c'.replaceAll('-', '_'), 'a_b_c');
+51 -8
src/ant.c
··· 18279 18279 static jsval_t builtin_string_charCodeAt(struct js *js, jsval_t *args, int nargs) { 18280 18280 jsval_t str = to_string_val(js, js->this_val); 18281 18281 if (vtype(str) != T_STR) return js_mkerr(js, "charCodeAt called on non-string"); 18282 - if (nargs < 1 || vtype(args[0]) != T_NUM) return tov(JS_NAN); 18282 + 18283 + double idx_d = nargs < 1 ? 0.0 : js_to_number(js, args[0]); 18284 + if (isnan(idx_d) || isinf(idx_d)) return tov(JS_NAN); 18283 18285 18284 - double idx_d = tod(args[0]); 18285 - if (idx_d < 0 || idx_d != (double)(long)idx_d) return tov(JS_NAN); 18286 + long idx_l = (long) idx_d; 18287 + if (idx_l < 0) return tov(JS_NAN); 18286 18288 18287 - jsoff_t idx = (jsoff_t) idx_d; 18289 + jsoff_t idx = (jsoff_t) idx_l; 18288 18290 jsoff_t str_len = offtolen(loadoff(js, (jsoff_t) vdata(str))); 18289 18291 18290 18292 if (idx >= str_len) return tov(JS_NAN); ··· 18293 18295 unsigned char ch = (unsigned char) js->mem[str_off + idx]; 18294 18296 18295 18297 return tov((double) ch); 18298 + } 18299 + 18300 + static jsval_t builtin_string_codePointAt(struct js *js, jsval_t *args, int nargs) { 18301 + jsval_t str = to_string_val(js, js->this_val); 18302 + if (vtype(str) != T_STR) return js_mkerr(js, "codePointAt called on non-string"); 18303 + 18304 + double idx_d = nargs < 1 ? 0.0 : js_to_number(js, args[0]); 18305 + if (isnan(idx_d) || isinf(idx_d)) return js_mkundef(); 18306 + 18307 + long idx_l = (long) idx_d; 18308 + if (idx_l < 0) return js_mkundef(); 18309 + 18310 + jsoff_t idx = (jsoff_t) idx_l; 18311 + jsoff_t str_len = offtolen(loadoff(js, (jsoff_t) vdata(str))); 18312 + 18313 + if (idx >= str_len) return js_mkundef(); 18314 + 18315 + jsoff_t str_off = (jsoff_t) vdata(str) + sizeof(jsoff_t); 18316 + const unsigned char *s = &js->mem[str_off + idx]; 18317 + jsoff_t remaining = str_len - idx; 18318 + 18319 + unsigned char c0 = s[0]; 18320 + if (c0 < 0x80) return tov((double) c0); 18321 + 18322 + if ((c0 & 0xE0) == 0xC0 && remaining >= 2 && (s[1] & 0xC0) == 0x80) { 18323 + uint32_t cp = ((c0 & 0x1F) << 6) | (s[1] & 0x3F); 18324 + return tov((double) cp); 18325 + } 18326 + 18327 + if ((c0 & 0xF0) == 0xE0 && remaining >= 3 && (s[1] & 0xC0) == 0x80 && (s[2] & 0xC0) == 0x80) { 18328 + uint32_t cp = ((c0 & 0x0F) << 12) | ((s[1] & 0x3F) << 6) | (s[2] & 0x3F); 18329 + return tov((double) cp); 18330 + } 18331 + 18332 + if ((c0 & 0xF8) == 0xF0 && remaining >= 4 && (s[1] & 0xC0) == 0x80 && (s[2] & 0xC0) == 0x80 && (s[3] & 0xC0) == 0x80) { 18333 + uint32_t cp = ((c0 & 0x07) << 18) | ((s[1] & 0x3F) << 12) | ((s[2] & 0x3F) << 6) | (s[3] & 0x3F); 18334 + return tov((double) cp); 18335 + } 18336 + 18337 + return tov((double) c0); 18296 18338 } 18297 18339 18298 18340 static jsval_t builtin_string_toLowerCase(struct js *js, jsval_t *args, int nargs) { ··· 18487 18529 static jsval_t builtin_string_charAt(struct js *js, jsval_t *args, int nargs) { 18488 18530 jsval_t str = to_string_val(js, js->this_val); 18489 18531 if (vtype(str) != T_STR) return js_mkerr(js, "charAt called on non-string"); 18490 - if (nargs < 1 || vtype(args[0]) != T_NUM) return js_mkstr(js, "", 0); 18491 18532 18492 - double idx_d = tod(args[0]); 18533 + double idx_d = nargs < 1 ? 0.0 : js_to_number(js, args[0]); 18493 18534 if (isnan(idx_d)) idx_d = 0; 18494 18535 else if (idx_d < 0) idx_d = -floor(-idx_d); 18495 18536 else idx_d = floor(idx_d); ··· 18509 18550 static jsval_t builtin_string_at(struct js *js, jsval_t *args, int nargs) { 18510 18551 jsval_t str = to_string_val(js, js->this_val); 18511 18552 if (vtype(str) != T_STR) return js_mkerr(js, "at called on non-string"); 18512 - if (nargs < 1 || vtype(args[0]) != T_NUM) return js_mkundef(); 18553 + 18554 + double idx_d = nargs < 1 ? 0.0 : js_to_number(js, args[0]); 18555 + if (isnan(idx_d) || isinf(idx_d)) return js_mkundef(); 18513 18556 18514 18557 jsoff_t str_len = offtolen(loadoff(js, (jsoff_t) vdata(str))); 18515 - double idx_d = tod(args[0]); 18516 18558 long idx = (long) idx_d; 18517 18559 18518 18560 if (idx < 0) idx += (long) str_len; ··· 22041 22083 setprop(js, string_proto, js_mkstr(js, "match", 5), js_mkfun(builtin_string_match)); 22042 22084 setprop(js, string_proto, js_mkstr(js, "template", 8), js_mkfun(builtin_string_template)); 22043 22085 setprop(js, string_proto, js_mkstr(js, "charCodeAt", 10), js_mkfun(builtin_string_charCodeAt)); 22086 + setprop(js, string_proto, js_mkstr(js, "codePointAt", 11), js_mkfun(builtin_string_codePointAt)); 22044 22087 setprop(js, string_proto, js_mkstr(js, "toLowerCase", 11), js_mkfun(builtin_string_toLowerCase)); 22045 22088 setprop(js, string_proto, js_mkstr(js, "toUpperCase", 11), js_mkfun(builtin_string_toUpperCase)); 22046 22089 setprop(js, string_proto, js_mkstr(js, "toLocaleLowerCase", 17), js_mkfun(builtin_string_toLowerCase));