mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-11-02 07:43:42 +08:00
`s.charAt(i) === "c"`, and `s[i] === "c"` where the index is proven in bounds, built a one-character string to compare with the literal. When the literal is one UTF-16 code unit, the comparison now reads `s.charCodeAt(i)` and compares the number. charCodeAt converts the index the same way charAt does, and an index out of range answers NaN, which equals no unit, as "" equals no one-unit literal. A switch on `s.charAt(i)` whose case tests are all one-unit literals switches on the code unit the same way. A switch on a `string | undefined` value with string literal cases, such as an array element or an optional field, lowered to a chain of union equalities. It now tests for undefined, which matches no case, and dispatches the string through the string switch: by byte length, then by the literal's leading bytes. `String.fromCharCode(a, b, ...)` with up to sixteen arguments passes the codes to the runtime in a stack array instead of a heap f64[], and up to 64 code units encode into a stack buffer instead of a heap scratch block. `.length` of a string that is not ASCII counts its UTF-16 units. The string index keeps four entries, so a program that read the lengths of more long texts than that in turn (the text of every source file) walked each whole string on every read. Lengths of non-ASCII strings longer than 64 bytes now go into a 1024-slot table keyed by address, allocated by the first length it records. A slot is dropped when the string is freed or reallocated and when an append changes it in place, which is where the index drops its facts.
37 lines
1.4 KiB
TypeScript
37 lines
1.4 KiB
TypeScript
// .length of long non-ASCII strings: many texts read in turn, appends in
|
|
// place (including a lone high surrogate completed by a low one), strings
|
|
// freed and rebuilt at reused addresses, split pieces, and slices and
|
|
// searches on texts whose lengths were read before.
|
|
let unit = "";
|
|
while (unit.length < 300) unit += "naïve 日本語 ";
|
|
const texts: string[] = [];
|
|
for (let i = 0; i < 40; i++) texts.push(unit.repeat(1 + (i % 7)) + "é".repeat(i));
|
|
let sum = 0;
|
|
for (let r = 0; r < 3; r++) for (const t of texts) sum += t.length;
|
|
console.log(sum, texts[39].length, texts[0].length);
|
|
|
|
let grow = unit;
|
|
const lengths: number[] = [];
|
|
for (let i = 0; i < 20; i++) {
|
|
grow += i % 2 ? "ü" : "x";
|
|
lengths.push(grow.length);
|
|
}
|
|
console.log(lengths.join(","));
|
|
let pair = unit + "\uD83D";
|
|
const before = pair.length;
|
|
pair += "\uDE00";
|
|
console.log(before, pair.length, pair.codePointAt(pair.length - 2)!.toString(16));
|
|
|
|
const seen: number[] = [];
|
|
for (let i = 0; i < 50; i++) {
|
|
const temp = unit + "ß".repeat(i % 5) + i;
|
|
seen.push(temp.length);
|
|
}
|
|
console.log(seen.slice(0, 10).join(","), seen.reduce((a, b) => a + b, 0));
|
|
|
|
const parts = (unit + "|").repeat(30).split("|");
|
|
console.log(parts.length, parts[0].length, parts.map((p) => p.length).reduce((a, b) => a + b, 0));
|
|
|
|
const big = texts[39];
|
|
console.log(big.slice(big.length - 5), big.substring(10, 20).length, big.indexOf("日本"), big.lastIndexOf("é"), big.length);
|