mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-11-07 08:33:50 +08:00
Keep a live Pick or Omit class view's identity when it flows into another structural type
A Pick or Omit view of a program class that holds the instance (its view exposes a method) now carries the class's identity in the flow analysis, and its values count as instances of that class. Assigning such a view to another structural type keeps the instance, so reads through the second type see the instance's later writes instead of a copy's.
This commit is contained in:
@@ -414,6 +414,11 @@ export class ClassProtocols {
|
||||
for (const part of ts.constituentTypes(type)) add(part);
|
||||
return;
|
||||
}
|
||||
// A Pick or Omit view's values are instances of the class it views.
|
||||
if (this.pickOfProgramClass(type)) {
|
||||
add(type.getAliasTypeArguments()[0]!);
|
||||
return;
|
||||
}
|
||||
const symbol = type.getSymbol();
|
||||
if (symbol === undefined) return;
|
||||
if (this.isProgramClassInstance(type)) {
|
||||
@@ -603,6 +608,8 @@ export class ClassProtocols {
|
||||
return element !== undefined && this.carriesIdentity(element, marked);
|
||||
}
|
||||
if (this.isProgramClassInstance(type)) return true;
|
||||
// A live Pick or Omit view of a program class holds the instance itself.
|
||||
if (this.pickOfProgramClass(type) && this.usesCheckedIdentity(type)) return true;
|
||||
const symbol = type.getSymbol();
|
||||
if (symbol === undefined) return false;
|
||||
if (marked.has(symbol)) return true;
|
||||
|
||||
@@ -37,3 +37,19 @@ void run({ client, name: "ctx" }).then(() => {
|
||||
finish(client);
|
||||
console.log(count(client), client.calls);
|
||||
});
|
||||
|
||||
// A live view that flows into another structural type keeps the instance:
|
||||
// reads through the second view see the instance's later writes.
|
||||
interface Counter {
|
||||
calls: number;
|
||||
}
|
||||
function counted(view: Pick<ApiClient, "request" | "calls">): Counter {
|
||||
void view.request("/z");
|
||||
return view;
|
||||
}
|
||||
const second = new ApiClient("https://k");
|
||||
const counter = counted(second);
|
||||
second.calls += 10;
|
||||
const holder: { counter: Counter } = { counter: counted(second) };
|
||||
second.calls = 100;
|
||||
console.log("counter", counter.calls, holder.counter.calls, second.calls);
|
||||
|
||||
Reference in New Issue
Block a user