Spread a string into its code points array (#2389)

This commit is contained in:
Chris Tate
2026-10-27 01:51:43 -05:00
committed by GitHub
4 changed files with 43 additions and 0 deletions
@@ -652,6 +652,17 @@ export function lowerArrayLiteral(
return lowered;
});
if (!needsStateBuild) {
// `[...text]`: the code points call already builds a fresh array of the
// literal's type, so it is the literal's value, as `Array.from(text)` is.
const only = elems[0];
if (
elems.length === 1 &&
spreads.length === 1 &&
only?.kind === "libCall" &&
only.fn === "str.codePoints" &&
typeEquals(only.type, type)
)
return { ...only, loc };
return { kind: "arrayLit", elems, ...(spreads.length > 0 ? { spreads } : {}), type, loc };
}
const out = lowerer.declareHiddenLocal("%arrayLit", type);
@@ -0,0 +1,6 @@
{
"order": [
"<repo>/tests/corpus/string-spread.ts"
],
"diags": []
}
+25
View File
@@ -0,0 +1,25 @@
// Spreading strings into arrays: code points of each UTF-8 length, astral
// pairs, lone surrogates, the empty string, and the fresh array each spread
// returns.
const samples = ["", "a", "abc", "é", "café", "日本語", "😀", "a😀b", "🚀🚀", "\ud800", "a\udc00b", "xé日😀"];
for (const s of samples) {
const chars = [...s];
console.log(JSON.stringify(s), chars.length, JSON.stringify(chars), chars.join("|"));
}
// Each spread is a new array: changing one leaves the others and the string.
const text = "héllo 😀";
const first = [...text];
const second = [...text];
first.reverse();
first.push("!");
console.log(first.join(""), second.join(""), first === second, text);
// The spread result is an ordinary array.
const letters = [..."naïve"];
letters.sort();
console.log(letters, letters.length, Array.isArray(letters));
console.log([..."abc"].map((c) => c.toUpperCase()).join(""));
console.log([..."日本"].concat([..."語"]).join("-"));
@@ -0,0 +1 @@
{ "plain": 4500, "san": 4300 }