mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-21 05:50:55 +08:00
- Preserve snapshots, bindings, and cleanup during eligible traversal. - Reuse unescaped piece storage and batch materialized results. - Cover limits, Unicode, debugging, and native/WASI behavior.
132 lines
4.4 KiB
TypeScript
132 lines
4.4 KiB
TypeScript
function collect(input: string, separator: string, limit: number): string {
|
|
let result = "";
|
|
for (const piece of input.split(separator, limit)) result += "[" + piece + "]";
|
|
return result;
|
|
}
|
|
|
|
for (const limit of [0, 1, 2, 7, -1, 1.9, NaN, Infinity, 4294967296, 4294967297]) {
|
|
console.log("limit", limit, collect(",a,,b,", ",", limit));
|
|
}
|
|
console.log("empty", collect("", "", 9), collect("", ",", 9));
|
|
console.log("overlap", collect("ababa", "aba", 9));
|
|
console.log("unicode", collect("é世界é中é", "é", 9), collect("世界", "", 9));
|
|
console.log("zero", collect("a\0b\0", "\0", 9));
|
|
|
|
function snapshot(): string {
|
|
let input = "left,right";
|
|
let separator = ",";
|
|
let limit = 2;
|
|
const pieces = input.split(separator, limit);
|
|
input += ",changed";
|
|
separator += "changed";
|
|
limit = 0;
|
|
let result = "";
|
|
for (let pass = 0; pass < 3; pass++) {
|
|
for (const piece of pieces) result += "[" + piece + "]";
|
|
}
|
|
return result + ":" + input + ":" + separator + ":" + limit;
|
|
}
|
|
console.log("snapshot", snapshot());
|
|
|
|
let receiver = "first,second";
|
|
let effects = "";
|
|
function source(): string { effects += "s"; return receiver; }
|
|
function separator(): string { effects += "p"; receiver += ",late"; return ","; }
|
|
function limit(): number { effects += "l"; return 2; }
|
|
let evaluated = "";
|
|
for (const piece of source().split(separator(), limit())) {
|
|
receiver += ",body";
|
|
evaluated += "[" + piece + "]";
|
|
}
|
|
console.log("order", effects, evaluated, receiver);
|
|
|
|
function failingSeparator(): string { throw new Error("separator"); }
|
|
function failingLimit(): number { throw new Error("limit"); }
|
|
try {
|
|
for (const piece of (receiver + ",temporary").split(failingSeparator())) console.log(piece);
|
|
} catch (error) { console.log("argument", (error as Error).message); }
|
|
try {
|
|
for (const piece of (receiver + ",temporary").split(receiver + ",separator", failingLimit())) console.log(piece);
|
|
} catch (error) { console.log("argument", (error as Error).message); }
|
|
|
|
function bindings(): string {
|
|
const readers: (() => string)[] = [];
|
|
for (let piece of "first-word,second-word,third-word".split(",")) {
|
|
piece += "!";
|
|
readers.push(() => piece);
|
|
}
|
|
let result = "";
|
|
for (const read of readers) result += read();
|
|
const shared: (() => string)[] = [];
|
|
for (var piece of "four,five".split(",")) shared.push(() => piece);
|
|
for (const read of shared) result += read();
|
|
let existing = "unchanged";
|
|
for (existing of "six,seven".split(",")) result += existing;
|
|
result += existing;
|
|
for (const [first, second = "_"] of "ab,c".split(",")) result += first + second;
|
|
return result;
|
|
}
|
|
console.log("bindings", bindings());
|
|
|
|
function exits(input: string): string {
|
|
const pieces = input.split(",");
|
|
let result = "";
|
|
outer: for (const piece of pieces) {
|
|
try {
|
|
for (const inner of "a,b,c".split(",")) {
|
|
if (inner === "a") continue;
|
|
if (piece === "break") break outer;
|
|
if (piece === "return") return result;
|
|
if (piece === "throw") throw new Error("stop");
|
|
result += piece + inner;
|
|
break;
|
|
}
|
|
} finally { result += "!"; }
|
|
}
|
|
return result;
|
|
}
|
|
console.log("break", exits("one,break,three"));
|
|
console.log("return", exits("one,return,three"));
|
|
try { console.log(exits("one,throw,three")); } catch (error) { console.log("throw", (error as Error).message); }
|
|
|
|
function observable(): string {
|
|
const pieces = "one,two".split(",");
|
|
const alias = pieces;
|
|
alias.push("three");
|
|
let result = "";
|
|
for (const piece of pieces) {
|
|
result += piece;
|
|
if (piece === "one") pieces.push("four");
|
|
}
|
|
return result + ":" + pieces.length;
|
|
}
|
|
console.log("observable", observable());
|
|
|
|
function escapes(): string {
|
|
const pieces = "one,two".split(",");
|
|
const read = (): string => pieces.join("/");
|
|
let result = "";
|
|
for (const piece of pieces) result += piece;
|
|
return result + ":" + read();
|
|
}
|
|
console.log("escapes", escapes());
|
|
|
|
async function suspended(): Promise<string> {
|
|
let input = "one,two";
|
|
const pieces = input.split(",");
|
|
input += ",late";
|
|
let result = "";
|
|
for (const piece of pieces) {
|
|
await Promise.resolve();
|
|
result += piece;
|
|
}
|
|
for await (const piece of "three,four".split(",")) result += piece;
|
|
return result;
|
|
}
|
|
suspended().then((value) => console.log("async", value));
|
|
|
|
function* generator(): Generator<string> {
|
|
for (const piece of "one,two".split(",")) yield piece;
|
|
}
|
|
for (const piece of generator()) console.log("generator", piece);
|