mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-24 06:14:01 +08:00
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.
38 lines
1.5 KiB
TypeScript
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);
|