// `recv.f += suffix` and `recv.f = recv.f + suffix` on string fields of // class instances and object literals, and `a[i] += suffix` on string // arrays, append in place when nothing else holds the string. Aliases must keep their value, interned literals are // never mutated, a throwing suffix leaves the field unchanged, suffixes that // read or write the field see JavaScript's values, a rebound receiver keeps // the original target, and accessors and expression-position updates keep // their semantics. Output must match Node. class Writer { buf = ""; count = 0; write(s: string): void { this.buf += s; this.count++; } writeNumber(n: number): void { this.buf += n; } writeParts(a: string, n: number): void { this.buf += "[" + a + ":" + n + "]"; } } function writerLoop(): string { const w = new Writer(); for (let i = 0; i < 2000; i++) w.write("" + i + ""); w.writeNumber(-0); w.writeNumber(1e21); w.writeNumber(0.1 + 0.2); w.writeParts("p", 7); return `${w.count} ${w.buf.length} ${w.buf.slice(0, 24)} ${w.buf.slice(-40)}`; } function aliases(): string { const o = { text: "start" }; const seen: string[] = []; for (let i = 0; i < 5; i++) { const before = o.text; // shares the string: the append must copy o.text += `-${i}`; seen.push(before); } const other = { text: o.text }; o.text = o.text + "!"; seen.push(other.text, o.text); return seen.join(" "); } class Pair { a = "lit"; b = "lit"; } function literals(): string { const p = new Pair(); p.a += "eral"; const q = new Pair(); return `${p.a} ${p.b} ${q.a} ${"lit"}`; } function failing(n: number): string { if (n > 2) throw new Error(`too big: ${n}`); return `<${n}>`; } function guarded(): string { const w = new Writer(); for (let i = 0; i < 5; i++) { try { w.buf += failing(i); } catch (e) { w.buf = w.buf + `!${(e as Error).message.length}`; } } return w.buf; } function suffixWritesField(): string { const w = new Writer(); w.buf = "old"; w.buf += ((w.buf = "replaced"), "+tail"); const o = { text: "x" }; o.text = o.text + ((o.text = "y"), "z"); return `${w.buf} ${o.text}`; } function suffixReadsField(): string { const w = new Writer(); w.buf = "ab"; w.buf += w.buf; w.buf += w.buf.length; w.buf = w.buf + "|" + w.buf; return w.buf; } function reboundReceiver(): string { const first = new Writer(); const second = new Writer(); first.buf = "first"; second.buf = "second"; let target = first; target.buf += ((target = second), "-appended"); let rec = { text: "one" }; const original = rec; rec.text = rec.text + ((rec = { text: "two" }), "-x"); return `${first.buf} ${second.buf} ${target.buf} ${original.text} ${rec.text}`; } class Shout { private inner = ""; get value(): string { return this.inner; } set value(v: string) { this.inner = v.toUpperCase(); } } function accessor(): string { const s = new Shout(); s.value += "ab"; s.value += "cd"; return s.value; } function expressionPosition(): string { const w = new Writer(); const r1 = (w.buf += "x"); const r2 = (w.buf += "y"); return `${r1} ${r2} ${w.buf}`; } function surrogates(): string { const o = { text: "a\uD83D" }; o.text += "\uDE00b"; const w = new Writer(); w.buf = "\uD83D"; w.write("\uDE00"); return `${o.text.length} ${o.text.codePointAt(1)} ${w.buf.length} ${w.buf.codePointAt(0)}`; } function shared(): string { const base = "shared"; const a = { text: base }; const b = { text: base }; for (let i = 0; i < 3; i++) a.text += i; return `${a.text} ${b.text} ${base}`; } function arraySlots(): string { const slots: string[] = ["", "", "", ""]; for (let i = 0; i < 4000; i++) slots[i % 4] += "v" + (i % 10); const direct: string[] = ["a", "b"]; for (let i = 0; i < 3; i++) direct[1] = direct[1] + i; return `${slots[0].length} ${slots[3].slice(-6)} ${direct.join(",")}`; } function arrayEdges(): string { const holes: string[] = []; holes[2] += "x"; // a hole reads as undefined holes[2] += "y"; holes[5] += "tail"; const keep: string[] = ["base"]; const before = keep[0]; keep[0] += "+1"; const writes: string[] = ["old"]; writes[0] += ((writes[0] = "new"), "!"); const grows: string[] = ["g"]; for (let i = 0; i < 40; i++) grows[0] += ((grows[grows.length] = `${i}`), "."); const idx: string[] = ["i0", "i1", "i2"]; let k = 0; idx[k] += ((k = 2), "-k"); const shared: string[] = ["s"]; const other = shared; shared[0] += "1"; other[0] += "2"; return [ holes.length, String(holes[2]), String(holes[5]), before, keep[0], writes[0], grows[0].length, grows.length, idx.join(","), shared[0], ].join(" "); } console.log(writerLoop()); console.log(aliases()); console.log(literals()); console.log(guarded()); console.log(suffixWritesField()); console.log(suffixReadsField()); console.log(reboundReceiver()); console.log(accessor()); console.log(expressionPosition()); console.log(surrogates()); console.log(shared()); console.log(arraySlots()); console.log(arrayEdges());