Support String.prototype.at on strings held in untyped values (#1948)

This commit is contained in:
Chris Tate
2026-10-23 01:03:32 -05:00
committed by GitHub
4 changed files with 30 additions and 1 deletions
@@ -0,0 +1,6 @@
{
"order": [
"<repo>/tests/corpus/7403-dyn-string-at.mjs"
],
"diags": []
}
+14 -1
View File
@@ -996,7 +996,20 @@ static ScrDyn *scr_dyn_invoke_impl(
scr_str_release(piece);
return r;
}
if ((mid == DYN_M_at) || (mid == DYN_M_concat) ||
if (mid == DYN_M_at) {
/* String.prototype.at: one UTF-16 code unit, counted from the end
* for a negative index; undefined outside the string. */
double index = dyn_index_arg(args, argc, 0, 0, what);
if (scr_exc_pending()) return NULL;
double len = (double)scr_str_utf16_len(s);
double k = index < 0 ? len + index : index;
if (k < 0 || k >= len) return scr_dyn_retain(scr_dyn_undefined());
ScrStr *unit = scr_str_slice(s, k, k + 1);
ScrDyn *r = scr_dyn_new_str(unit); /* retains */
scr_str_release(unit);
return r;
}
if ((mid == DYN_M_concat) ||
(mid == DYN_M_indexOf) || (mid == DYN_M_lastIndexOf) ||
(mid == DYN_M_includes)) {
if (((mid == DYN_M_indexOf) || (mid == DYN_M_lastIndexOf) ||
+9
View File
@@ -0,0 +1,9 @@
// String.prototype.at on strings held in untyped (checked-dynamic) values,
// as Hono's mergePath reads `base?.at(-1)`.
const mergePath = (base, sub, ...rest) => {
if (rest.length) sub = mergePath(sub, ...rest);
return `${base?.[0] === "/" ? "" : "/"}${base}${sub === "/" ? "" : `${base?.at(-1) === "/" ? "" : "/"}${sub?.[0] === "/" ? sub.slice(1) : sub}`}`;
};
console.log(mergePath("/api", "/users"), mergePath("api/", "/"), mergePath("/a", "b", "/c"));
const values = JSON.parse(`["hello", "", "a\\ud83d\\ude00b"]`);
for (const v of values) console.log(JSON.stringify([v.at(0), v.at(-1), v.at(1), v.at(99), v.at(-99), v.at(1.7), v.at()]));
@@ -0,0 +1 @@
{ "plain": 2600, "san": 15000 }