Files
codegraph/__tests__/fixtures/kernel-parity/torture.tsx
T
cece0720e3 fix(resolution): resolve this.<field>.<method>() on the fields declared type (#1496) (#1792)
Land the six-file fix from upstream PR #1691 by danusha2345
(pr-1691 at 6d0e80d52ae953b22d615bd20c4a4c7758814e60), preserving
wasm/native extraction parity and exclusive field-type resolution.

Preserve coexistence with the #1566 Map/collection fix merged in #1790,
including nested holder.values.get coverage and the unchanged #1566
Unreleased changelog bullet. EXTRACTION_VERSION remains unchanged.

Align the existing chained-receiver regression with the fix: a declared
service field calls its method, while an anonymous field type does not
bind to unrelated same-named project functions.

Verified on Linux with Node 22.19.0:
- Rebuilt the native kernel and TypeScript/browser distribution.
- Both backends change Outbox::send -> Outbox::send into
  Outbox::send -> Mailer::send, keep Relay::forward -> Mailer::send,
  and store no self-edges in the issue repro.
- Wasm: 224 tests passed; native kernel: 255 tests passed, no skips.
- All 10 #1566 resolution cases pass on each backend, plus all four
  nested-receiver extraction parity cases.

Co-authored-by: Colby McHenry <colbymchenry@users.noreply.github.com>
2026-09-08 14:24:04 -05:00

233 lines
5.9 KiB
TypeScript

/**
* Torture fixture — exercises every TS/TSX extraction path the kernel ports.
*/
import React, { forwardRef, memo, useState as useStateAlias } from 'react';
import * as NS from './namespace-module';
import DefaultThing from './default-module';
import './side-effect';
import { helperFn, CONFIG_TABLE } from './helpers';
export { reExported, orig as aliased } from './barrel-source';
export * from './star-source';
// A documented constant table (value-ref target).
const RETRY_LIMITS = { a: 1, b: 2 };
export const API_BASE = 'https://example.test';
let plainLet = 42;
var oldVar = 'x';
/** Class docs.
* Multi-line.
*/
@Injectable()
@scoped.Registry<Config>('name')
export abstract class BaseService extends EventTarget implements Disposable, Serializable {
static instances = 0;
private readonly cache: Map<string, Config> = new Map();
public fonts: FontConfig;
count = 0;
onScroll = throttle((e: Event) => {
this.handleScroll(e);
}, 100);
handleClick = (ev: MouseEvent): void => {
emitTelemetry(ev);
new AbortController();
};
@Get('/list')
async list(query: QueryOpts): Promise<Result<Item>> {
const local: ItemMapper = makeMapper();
const limit = RETRY_LIMITS;
return this.cache.get(query.key) ?? helperFn(query);
}
private static compute(n: number): number {
return n * RETRY_LIMITS.a;
}
get size(): number {
return this.count;
}
protected dispose(): void {
listeners.forEach((l) => unregister(l));
}
}
class Plain {
constructor(private svc: BaseService) {
register(this.onEvent);
btn.on('click', this.handleClick);
}
onEvent() {}
handleClick() {}
}
export interface Shape extends Named, Sized {
area: number;
resize(f: number): Shape;
onchange: (s: Shape) => void;
}
export enum Direction {
Up,
Down = 2,
Left,
}
export type Handle = {
stop: () => void;
id: string;
refresh(force: boolean): Promise<void>;
};
export type ServiceList = [
Service<'query_apply_record', Req, Resp>,
Service<'apply_confirm', Req, Resp>,
];
export type MaybeShape = Shape | null;
export function topLevel(a: ShapeConfig): Shape {
const inner = () => reallyDeep();
function namedInner(): void {
chained(a).value;
}
namedInner();
return makeShape(a);
}
async function* generatorFn(items: Item[]) {
yield* items.map((i) => transform(i));
}
export const arrowConst = async (x: number) => {
return x + plainLet;
};
const AnonClassHolder = class {
method() {}
};
// React components (#841).
export const Button = forwardRef((props: ButtonProps, ref) => {
const [state, setState] = useStateAlias(0);
useEffect(() => {
trackRender();
});
return <BaseButton ref={ref} onClick={() => setState(state + 1)} {...props} />;
});
export const MemoRow = memo(function Row(props: RowProps) {
return <tr className={props.cls}>{props.children}</tr>;
});
export const Wrapped = React.memo(ImportedComponent);
export const Styled = styled.button`
color: red;
`;
const memoCache = memo(computeThing); // lowercase — stays a constant
export function App() {
const nodes: GraphNode[] = [];
return (
<div>
<Button label={CONFIG_TABLE.label} />
<NS.Panel />
{nodes.map((n) => (
<MemoRow key={n.id} cls={n.cls} />
))}
</div>
);
}
// Object-of-functions (SvelteKit-style actions map).
export const actionsMap = {
create: async (input: CreateInput) => {
return persistNew(input);
},
update(input: UpdateInput) {
return persistExisting(input);
},
};
// Zustand-style store through middleware wrappers.
export const useStore = create(
persist(
(set, get) => ({
fetchUser: async (id: string) => {
const user = await api.load(id);
set({ user });
},
reset: () => set({ user: null }),
}),
{ name: 'store' }
)
);
// RTK Query.
export const widgetApi = createApi({
reducerPath: 'widgets',
endpoints: (build) => ({
getWidget: build.query({
query: (id: string) => fetchWidget(id),
}),
updateWidget: build.mutation({
queryFn: async (patch) => {
return applyPatch(patch);
},
}),
prebuilt: build.query(makeEndpointConfig()),
}),
});
export const { useGetWidgetQuery, useUpdateWidgetMutation } = widgetApi;
const { notAHook } = widgetApi;
// Value-ref shadowing: SHADOWED_LIMIT re-bound locally must be pruned.
const SHADOWED_LIMIT = 10;
export function readsShadowed() {
const SHADOWED_LIMIT = 20;
return SHADOWED_LIMIT;
}
export function readsTable() {
return RETRY_LIMITS.b + API_BASE.length;
}
// Fn-ref registrations.
registerHandler(helperFn);
queueMicrotask(topLevel);
const routeTable = { home: topLevel, missing: notDefinedAnywhere };
const handlerList = [helperFn, DefaultThing];
target.cb = topLevel;
const aliasFn = topLevel;
// Calls with interesting callees.
;(topLevel)(cfg);
NS.helper.deep(1);
"literal".includes('x');
[1, 2].map(String);
obj?.optMethod?.(3);
import('./dynamic-module');
new NS.Widget(makeArg());
new Map<string, number>();
super_weird?.();
// --- call through a field of the enclosing class (#1496) ---------------------
export class FieldDelegator {
constructor(private readonly mailer: { send(m: string): string }, private items: string[]) {}
send(msg: string): string { return this.mailer.send(msg); }
push(msg: string): void { this.items.push(msg); this.mailer.send(msg).trim(); }
direct(): void { this.send('x'); super.toString(); }
}
// --- const-bound functions inside a body (#1669) -----------------------------
export function NestedHandlers({ items, onPick }: { items: string[]; onPick: (a: unknown, b: unknown) => void }) {
const handleClear = () => { onPick(null, null); };
const describe = function (item: string) { return formatLabel(item); };
let later = (x: string) => parseLabel(x);
const count = items.length;
const [a, b] = [() => 1, () => 2];
return items.map((i) => <button onClick={handleClear} onDoubleClick={() => describe(i)}>{later(i)}{count}{a()}{b()}</button>);
}