mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-23 06:10:02 +08:00
52 lines
1.4 KiB
TypeScript
52 lines
1.4 KiB
TypeScript
// A reference cycle THROUGH a base-typed field: the owner stores its pet
|
|
// in a Pet-typed slot that actually holds a Dog pointing back at the
|
|
// owner. The collector's trace must follow the base-typed edge into the
|
|
// DERIVED object's trace (stamped at allocation), and teardown through the
|
|
// vtable must release the derived fields — the sanitized lane asserts
|
|
// every dropped pair is collected.
|
|
class Pet {
|
|
tag: string;
|
|
constructor(tag: string) {
|
|
this.tag = tag;
|
|
}
|
|
describe(): string {
|
|
return this.tag;
|
|
}
|
|
}
|
|
class Dog extends Pet {
|
|
owner: Owner;
|
|
constructor(tag: string, owner: Owner) {
|
|
super(tag);
|
|
this.owner = owner;
|
|
}
|
|
describe(): string {
|
|
return `${this.tag} of ${this.owner.label}`;
|
|
}
|
|
}
|
|
class Owner {
|
|
label: string;
|
|
pet: Pet;
|
|
constructor(label: string) {
|
|
this.label = label;
|
|
this.pet = new Pet("none");
|
|
}
|
|
}
|
|
|
|
function spin(label: string): string {
|
|
const o = new Owner(label);
|
|
o.pet = new Dog(`${label}-dog`, o); // Owner -> (Pet-typed) Dog -> Owner
|
|
return o.pet.describe(); // virtual through the base-typed field
|
|
}
|
|
console.log(spin("one"));
|
|
for (let i = 0; i < 400; i++) {
|
|
spin(`x${i}`);
|
|
}
|
|
console.log(spin("two"));
|
|
|
|
// The same shape via instanceof narrowing: reach back around the cycle.
|
|
const home = new Owner("home");
|
|
home.pet = new Dog("buddy", home);
|
|
if (home.pet instanceof Dog) {
|
|
console.log(home.pet.owner === home, home.pet.owner.pet.describe());
|
|
}
|