Files
scriptc/tests/corpus/5553-string-append-char-code.ts
T
Chris Tate 416311f2c5 Append to strings in place for fields, concat chains and character codes
The runtime appends to a string in place when the left operand is
uniquely owned, but three common forms never got there:

- `obj.field += s` on a plain class or record field kept a second
  reference to the old value, so every append copied the whole string.
  The compound assignment now reads a stored string field into a mutable
  local, stores "" into the field (no code runs in between: both operands
  are already strings), runs the self-append `old = old + rhs` and stores
  the result.
- `s = s + a + b` copied per append: the self-append recognized only
  `s = s + x`. A concat chain whose leftmost operand is the target now
  takes the remaining operands as the suffix, in the same order.
- `s += String.fromCharCode(c)` built a one-character string first.
  scr_str_concat_move_char_code appends the character, in place for ASCII.

Self-appends also borrow the suffix instead of retaining it, and a
discarded compound assignment no longer retains and releases its result.
2026-10-15 06:17:38 -05:00

38 lines
1.5 KiB
TypeScript

// `s += String.fromCharCode(c)` appends one character: ASCII, two- and
// three-byte characters, surrogate halves that join into one character,
// codes that wrap modulo 2^16, aliases of the old string (which must not
// change), and growth from an empty string, against Node.
let s = "";
const seen: string[] = [];
for (let i = 0; i < 1000; i++) {
s += String.fromCharCode(32 + (i % 95));
if (i % 250 === 0) seen.push(s);
}
console.log(s.length, s.slice(0, 10), s.slice(-10), seen.map((x) => x.length).join(","));
let t = "abc";
const alias = t;
t += String.fromCharCode(100);
t += String.fromCharCode(0xe9);
t += String.fromCharCode(0x65e5);
t += String.fromCharCode(0x10041);
t += String.fromCharCode(-1);
console.log(t, t.length, alias, alias.length);
let pair = "x";
pair += String.fromCharCode(0xd83d);
const half = pair;
pair += String.fromCharCode(0xde00);
console.log(pair, pair.length, half.length, half.charCodeAt(1).toString(16));
let lone = "";
lone += String.fromCharCode(0xde00);
lone += String.fromCharCode(0xd83d);
console.log(lone.length, lone.charCodeAt(0).toString(16), lone.charCodeAt(1).toString(16));
let codes = "";
for (const c of [72, 101, 108, 108, 111, 1.9, 65.5, 0x7f, 0x80]) codes += String.fromCharCode(c);
console.log(JSON.stringify(codes), codes.length);
function build(n: number): string {
let out = "";
for (let i = 0; i < n; i++) out += String.fromCharCode(97 + (i % 26));
return out;
}
console.log(build(0), build(1), build(27), build(5000).length);