chore(lint): apply eslint auto-fixes across the .tsx backlog

Mechanical --fix output over the newly linted .tsx files (indent,
arrow-parens, comma-dangle, member-delimiter-style, unnecessary type
assertions), plus the three generic-arrow test hooks converted to
function declarations up front: the comma-dangle fixer strips the
<T,> disambiguation comma and turns them into parse errors otherwise.
This commit is contained in:
imccyu
2026-07-27 21:49:40 +08:00
parent 36e8141145
commit 49c2e85ac7
58 changed files with 479 additions and 475 deletions

View File

@@ -8,7 +8,7 @@ import type { HostObservable as ObservableSnapshot, SnapshotSelectorHook } from
// Keep equality local: this suite asserts the eq parameter contract without
// adding a reverse dependency from web-react to runtime.
const shallowEqual = (a: Record<string, unknown>, b: Record<string, unknown>): boolean =>
Object.keys(a).length === Object.keys(b).length && Object.keys(a).every((k) => Object.is(a[k], b[k]))
Object.keys(a).length === Object.keys(b).length && Object.keys(a).every(k => Object.is(a[k], b[k]))
interface Snap { a: number; b: number }
@@ -51,7 +51,7 @@ describe('bindSnapshotSelector', () => {
const { source, set } = makeSource({ a: 1, b: 10 })
const useSelector = bindSnapshotSelector(source)
const probe = { renders: 0, value: undefined as number | undefined }
render(<Harness useSelector={useSelector} sel={(s) => s.a} probe={probe} />)
render(<Harness useSelector={useSelector} sel={s => s.a} probe={probe} />)
expect(probe.value).toBe(1)
const before = probe.renders
act(() => { set({ a: 1, b: 11 }) }) // unrelated field: Object.is bail
@@ -65,7 +65,7 @@ describe('bindSnapshotSelector', () => {
const { source, set } = makeSource({ a: 1, b: 10 })
const useSelector = bindSnapshotSelector(source)
const probe = { renders: 0, value: undefined as { a: number } | undefined }
render(<Harness useSelector={useSelector} sel={(s) => ({ a: s.a })} eq={shallowEqual} probe={probe} />)
render(<Harness useSelector={useSelector} sel={s => ({ a: s.a })} eq={shallowEqual} probe={probe} />)
const before = probe.renders
act(() => { set({ a: 1, b: 99 }) }) // fresh object, shallow-equal slice
expect(probe.renders).toBe(before)
@@ -78,11 +78,11 @@ describe('bindSnapshotSelector', () => {
const { source, set, stats } = makeSource({ a: 1, b: 10 })
const useSelector = bindSnapshotSelector(source)
const probe = { renders: 0, value: undefined as number | undefined }
const { rerender } = render(<Harness useSelector={useSelector} sel={(s) => s.a} probe={probe} />)
const { rerender } = render(<Harness useSelector={useSelector} sel={s => s.a} probe={probe} />)
const after = stats.subscribeCalls
rerender(<Harness useSelector={useSelector} sel={(s) => s.a} probe={probe} />)
rerender(<Harness useSelector={useSelector} sel={s => s.a} probe={probe} />)
act(() => { set({ a: 2, b: 10 }) })
rerender(<Harness useSelector={useSelector} sel={(s) => s.a} probe={probe} />)
rerender(<Harness useSelector={useSelector} sel={s => s.a} probe={probe} />)
expect(stats.subscribeCalls).toBe(after)
})
@@ -92,7 +92,7 @@ describe('bindSnapshotSelector', () => {
const probe = { renders: 0, value: undefined as number | undefined }
const view = render(
<StrictMode>
<Harness useSelector={useSelector} sel={(s) => s.a} probe={probe} />
<Harness useSelector={useSelector} sel={s => s.a} probe={probe} />
</StrictMode>,
)
expect(probe.value).toBe(1)
@@ -112,7 +112,7 @@ describe('bindSnapshotSelector', () => {
}
const useSelector = bindSnapshotSelector(new MethodSource())
const probe = { renders: 0, value: undefined as number | undefined }
render(<Harness useSelector={useSelector} sel={(s) => s.a} probe={probe} />)
render(<Harness useSelector={useSelector} sel={s => s.a} probe={probe} />)
expect(probe.value).toBe(7)
})

View File

@@ -28,10 +28,10 @@ type FrameSlots = PropsRenderSlots<'spec.single' | 'spec.list'>
function hostOver(core: SlotCore): SlotRendererHost {
return {
subscribe: (key, fn) => core.subscribe(key, fn),
getVersion: (key) => core.getVersion(key),
entriesOf: (key) => core.entries(key),
specOf: (key) => core.specDynamic(key),
isLive: (entry) => core.isLive(entry),
getVersion: key => core.getVersion(key),
entriesOf: key => core.entries(key),
specOf: key => core.specDynamic(key),
isLive: entry => core.isLive(entry),
storeOf: () => undefined,
sessions: {
list: { getSnapshot: () => ({}), subscribe: () => () => {} },
@@ -61,7 +61,7 @@ function mountFrame(core: SlotCore, body: (renderSlot: FrameSlots['renderSlot'])
describe('createSlotRenderer over the real SlotCore', () => {
it('renders registrations live through real microtask batching: register, dispose back to fallback', async () => {
const core = new SlotCore()
const { view } = mountFrame(core, (renderSlot) =>
const { view } = mountFrame(core, renderSlot =>
renderSlot('spec.single', {}, { fallback: <i>none</i> }))
expect(view.container.textContent).toBe('none')
let dispose = () => {}
@@ -78,7 +78,7 @@ describe('createSlotRenderer over the real SlotCore', () => {
const core = new SlotCore()
const notified = vi.fn()
core.subscribe('spec.list', notified)
const { view } = mountFrame(core, (renderSlot) => renderSlot('spec.list', {}))
const { view } = mountFrame(core, renderSlot => renderSlot('spec.list', {}))
await act(async () => {
core.register({ name: 'spec.list', id: 'two', order: 2 }, () => <span>2</span>)
core.register({ name: 'spec.list', id: 'one', order: 1 }, () => <span>1</span>)

View File

@@ -96,10 +96,10 @@ function makeHost() {
subs.set(key, set)
return () => { set.delete(fn) }
},
getVersion: (key) => versions.get(key) ?? 0,
entriesOf: (key) => entries.get(key) ?? [],
specOf: (key) => specs.get(key),
isLive: (entry) => live.has(entry),
getVersion: key => versions.get(key) ?? 0,
entriesOf: key => entries.get(key) ?? [],
specOf: key => specs.get(key),
isLive: entry => live.has(entry),
storeOf: (entry, scopeKey) => {
if (entry.store === undefined) return undefined
let perScope = storeCache.get(entry)
@@ -121,8 +121,8 @@ function makeHost() {
sessions: {
list,
current,
provideInfo: (id) => infos.get(id),
maybeProvideInfo: (id) => (id === undefined ? undefined : infos.get(id))
provideInfo: id => infos.get(id),
maybeProvideInfo: id => (id === undefined ? undefined : infos.get(id))
?? { sessionId: undefined, hooks: {}, props: {} },
},
workspaces: { list: workspaces },
@@ -145,7 +145,7 @@ function makeHost() {
live.add(entry)
bump(key)
return () => {
entries.set(key, (entries.get(key) ?? []).filter((e) => e !== entry))
entries.set(key, (entries.get(key) ?? []).filter(e => e !== entry))
live.delete(entry)
bump(key)
}
@@ -187,7 +187,7 @@ const chainEntryOf = (partial: {
priority?: number
}): Omit<StoredEntry, 'options'> & { options?: StoredEntry['options'] } => ({
component: partial.component,
select: partial.select as StoredEntry['select'],
select: partial.select,
...(partial.priority !== undefined ? { options: { priority: partial.priority } } : {}),
})
@@ -230,7 +230,7 @@ describe('child outlets and the renderSlot binding', () => {
const h = makeHost()
h.declare('k.single', SINGLE_ROOT)
const { view } = mountRoot(h, { 'k.single': SINGLE_ROOT },
(renderSlot) => renderSlot('k.single', {}, { fallback: <i>none</i> }))
renderSlot => renderSlot('k.single', {}, { fallback: <i>none</i> }))
expect(view.container.textContent).toBe('none')
let dispose = () => {}
act(() => { dispose = h.add('k.single', { component: () => <b>SB</b> }) })
@@ -242,7 +242,7 @@ describe('child outlets and the renderSlot binding', () => {
it('renders an undeclared key as empty (declaring entry unloaded = natural blank, not a crash)', () => {
const h = makeHost()
const { view } = mountRoot(h, { 'k.single': SINGLE_ROOT },
(renderSlot) => <main>{renderSlot('k.single', {}, { fallback: <i>fb</i> })}</main>)
renderSlot => <main>{renderSlot('k.single', {}, { fallback: <i>fb</i> })}</main>)
// Declared by children (authorization) but absent from the ledger (specOf
// undefined): the outlet renders nothing, not even the fallback path's spec dispatch.
expect(view.container.querySelector('main')!.textContent).toBe('')
@@ -256,7 +256,7 @@ describe('child outlets and the renderSlot binding', () => {
h.add('k.list', { component: () => <span>a</span>, options: { id: 'a', order: 1 } })
h.add('k.keyed', { component: () => <span>goal</span>, options: { key: 'goal' } })
const children = { 'k.list': { kind: 'list', scope: 'root' } as DeclaredSpec, 'k.keyed': { kind: 'keyed', scope: 'root' } as DeclaredSpec }
const { view } = mountRoot(h, children, (renderSlot) => <>
const { view } = mountRoot(h, children, renderSlot => <>
<main>{renderSlot('k.list', {})}</main>
<aside>{renderSlot('k.list', {}, { only: 'b' })}</aside>
<nav>{renderSlot('k.keyed', {}, { entryKey: 'goal' })}</nav>
@@ -291,7 +291,7 @@ describe('child outlets and the renderSlot binding', () => {
h.add('k.list', { component: () => <span>alive</span>, options: { id: 'ok', order: 2 } })
const spy = vi.spyOn(console, 'error').mockImplementation(() => {})
const { view } = mountRoot(h, { 'k.list': { kind: 'list', scope: 'root' } },
(renderSlot) => renderSlot('k.list', {}))
renderSlot => renderSlot('k.list', {}))
spy.mockRestore()
expect(view.container.textContent).toBe('alive')
expect(view.container.querySelector('[data-slot-error]')).not.toBeNull()
@@ -309,10 +309,10 @@ describe('chain outlets and the renderSlotChain binding', () => {
}))
h.add('k.chain', chainEntryOf({
component: ({ matched }: { matched?: { label: string } }) => <b>{matched?.label}</b>,
select: (owner) => ({ label: `hit:${(owner as { tag: string }).tag}` }),
select: owner => ({ label: `hit:${(owner as { tag: string }).tag}` }),
}))
const { view } = mountChainRoot(h, { 'k.chain': CHAIN_ROOT },
(renderSlotChain) => renderSlotChain('k.chain', { tag: 'T' }))
renderSlotChain => renderSlotChain('k.chain', { tag: 'T' }))
// The declining entry never mounts: the routing decision is select-layer only.
expect(view.container.textContent).toBe('hit:T')
expect(declinerBody).not.toHaveBeenCalled()
@@ -327,10 +327,10 @@ describe('chain outlets and the renderSlotChain binding', () => {
}))
h.add('k.chain', chainEntryOf({
component: ({ matched }: { matched?: string }) => <b>{matched}</b>,
select: (owner) => (owner as { pick?: string }).pick ?? null,
select: owner => (owner as { pick?: string }).pick ?? null,
}))
const spy = vi.spyOn(console, 'error').mockImplementation(() => {})
const { view } = mountChainRoot(h, { 'k.chain': CHAIN_ROOT }, (renderSlotChain) => <>
const { view } = mountChainRoot(h, { 'k.chain': CHAIN_ROOT }, renderSlotChain => <>
<main>{renderSlotChain('k.chain', { pick: 'OK' })}</main>
<aside>{renderSlotChain('k.chain', {}, { fallback: <i>fb</i> })}</aside>
</>)
@@ -347,16 +347,16 @@ describe('chain outlets and the renderSlotChain binding', () => {
h.declare('k.chain', CHAIN_ROOT)
h.add('k.chain', chainEntryOf({
component: () => { throw new Error('entry A boom') },
select: (owner) => (owner as { pick?: string }).pick === 'A' ? {} : null,
select: owner => (owner as { pick?: string }).pick === 'A' ? {} : null,
}))
h.add('k.chain', chainEntryOf({
component: () => <b>B-ok</b>,
select: (owner) => (owner as { pick?: string }).pick === 'B' ? {} : null,
select: owner => (owner as { pick?: string }).pick === 'B' ? {} : null,
}))
let pick = 'A'
const spy = vi.spyOn(console, 'error').mockImplementation(() => {})
const { view } = mountChainRoot(h, { 'k.chain': CHAIN_ROOT },
(renderSlotChain) => renderSlotChain('k.chain', { pick }))
renderSlotChain => renderSlotChain('k.chain', { pick }))
spy.mockRestore()
expect(view.container.querySelector('[data-slot-error]')).not.toBeNull()
// Re-elect entry B: the entry-keyed boundary remounts fresh instead of
@@ -372,9 +372,9 @@ describe('chain outlets and the renderSlotChain binding', () => {
h.declare('k.chain', CHAIN_ROOT)
h.add('k.chain', chainEntryOf({
component: ({ matched }: { matched?: string }) => <b>{matched}</b>,
select: (owner) => (owner as { pick?: string }).pick ?? null,
select: owner => (owner as { pick?: string }).pick ?? null,
}))
const { view } = mountChainRoot(h, { 'k.chain': CHAIN_ROOT }, (renderSlotChain) => <>
const { view } = mountChainRoot(h, { 'k.chain': CHAIN_ROOT }, renderSlotChain => <>
<main>{renderSlotChain('k.chain', {}, { fallback: <i>bar</i> })}</main>
<aside>{renderSlotChain('k.chain', { pick: 'P' }, { fallback: <i>bar</i> })}</aside>
</>)
@@ -387,7 +387,7 @@ describe('chain outlets and the renderSlotChain binding', () => {
const h = makeHost()
h.declare('k.chain', CHAIN_ROOT)
const { view } = mountChainRoot(h, { 'k.chain': CHAIN_ROOT },
(renderSlotChain) => renderSlotChain('k.chain', {}, { fallback: <i>none</i> }))
renderSlotChain => renderSlotChain('k.chain', {}, { fallback: <i>none</i> }))
expect(view.container.textContent).toBe('none')
let dispose = () => {}
act(() => {
@@ -422,7 +422,7 @@ describe('chain outlets and the renderSlotChain binding', () => {
priority: 1,
}))
const { view } = mountChainRoot(h, { 'k.chain': CHAIN_ROOT },
(renderSlotChain) => renderSlotChain('k.chain', {}))
renderSlotChain => renderSlotChain('k.chain', {}))
expect(view.container.textContent).toBe('early')
})
@@ -490,13 +490,13 @@ describe('overlay chains (ChainRenderOpts.overlay)', () => {
h.declare('k.chain', CHAIN_ROOT)
h.add('k.chain', chainEntryOf({
component: () => <b>TAKEOVER</b>,
select: (owner) => (owner as { take?: boolean }).take ? {} : null,
select: owner => (owner as { take?: boolean }).take ? {} : null,
}))
const mounted = vi.fn()
const Probe = fallbackProbe(mounted)
let take = false
const { view } = mountChainRoot(h, { 'k.chain': CHAIN_ROOT },
(renderSlotChain) => renderSlotChain('k.chain', { take }, { fallback: <Probe />, overlay: true }))
renderSlotChain => renderSlotChain('k.chain', { take }, { fallback: <Probe />, overlay: true }))
const wrapper = () => view.container.querySelector<HTMLElement>('[data-chain-overlay-fallback="k.chain"]')!
const input = () => view.container.querySelector<HTMLInputElement>('input[aria-label="probe"]')!
@@ -525,13 +525,13 @@ describe('overlay chains (ChainRenderOpts.overlay)', () => {
h.declare('k.chain', CHAIN_ROOT)
h.add('k.chain', chainEntryOf({
component: () => <b>TAKEOVER</b>,
select: (owner) => (owner as { take?: boolean }).take ? {} : null,
select: owner => (owner as { take?: boolean }).take ? {} : null,
}))
const mounted = vi.fn()
const Probe = fallbackProbe(mounted)
let take = false
const { view } = mountChainRoot(h, { 'k.chain': CHAIN_ROOT },
(renderSlotChain) => renderSlotChain('k.chain', { take }, { fallback: <Probe /> }))
renderSlotChain => renderSlotChain('k.chain', { take }, { fallback: <Probe /> }))
fireEvent.change(view.container.querySelector('input[aria-label="probe"]')!, { target: { value: 'gone' } })
expect(view.container.querySelector('[data-chain-overlay-fallback]')).toBeNull()
@@ -561,7 +561,7 @@ describe('overlay chains (ChainRenderOpts.overlay)', () => {
priority: 2,
}))
const { view } = mountChainRoot(h, { 'k.chain': CHAIN_ROOT },
(renderSlotChain) => renderSlotChain('k.chain', {}, { fallback: <i>resident</i>, overlay: true }))
renderSlotChain => renderSlotChain('k.chain', {}, { fallback: <i>resident</i>, overlay: true }))
expect(view.container.textContent).toContain('ELECTED')
expect(spy.mock.calls.some(([msg]) => String(msg).includes('chain selector crashed'))).toBe(true)
spy.mockRestore()
@@ -578,9 +578,9 @@ describe('standard-kit synthesis', () => {
h.declare('k.single', SINGLE_ROOT)
h.add('k.single', {
component: ({ useSessions }: { useSessions: <S>(sel: (s: { ids: string[] }) => S) => S }) =>
<b>{useSessions((s) => s.ids.length)}</b>,
<b>{useSessions(s => s.ids.length)}</b>,
})
const { view } = mountRoot(h, { 'k.single': SINGLE_ROOT }, (renderSlot) => renderSlot('k.single', {}))
const { view } = mountRoot(h, { 'k.single': SINGLE_ROOT }, renderSlot => renderSlot('k.single', {}))
expect(view.container.textContent).toBe('0')
act(() => { h.list.set({ ids: ['a', 'b'] }) })
expect(view.container.textContent).toBe('2')
@@ -591,9 +591,9 @@ describe('standard-kit synthesis', () => {
h.declare('k.single', SINGLE_ROOT)
h.add('k.single', {
component: ({ useWorkspaces }: { useWorkspaces: <S>(sel: (s: { ids: string[] }) => S) => S }) =>
<b>{useWorkspaces((s) => s.ids.length)}</b>,
<b>{useWorkspaces(s => s.ids.length)}</b>,
})
const { view } = mountRoot(h, { 'k.single': SINGLE_ROOT }, (renderSlot) => renderSlot('k.single', {}))
const { view } = mountRoot(h, { 'k.single': SINGLE_ROOT }, renderSlot => renderSlot('k.single', {}))
expect(view.container.textContent).toBe('0')
act(() => { h.workspaces.set({ ids: ['w1'] }) })
expect(view.container.textContent).toBe('1')
@@ -606,11 +606,11 @@ describe('standard-kit synthesis', () => {
const seen: AnyProps[] = []
h.add('k.session', {
component: (props: { useSession?: <S>(sel: (s: { sid: string }) => S) => S; sessionId?: string }) => {
seen.push({ ...props, read: props.useSession!((s) => s.sid) })
seen.push({ ...props, read: props.useSession!(s => s.sid) })
return null
},
})
mountRoot(h, { 'k.session': SINGLE_SESSION }, (renderSlot) => (
mountRoot(h, { 'k.session': SINGLE_SESSION }, renderSlot => (
<SessionProvider empty={() => <i>empty</i>}>
{() => renderSlot('k.session', {})}
</SessionProvider>
@@ -669,14 +669,14 @@ describe('standard-kit synthesis', () => {
h.declare('k.session', SINGLE_SESSION)
h.add('k.session', { component: () => <b>x</b> })
const { view } = mountRoot(h, { 'k.session': SINGLE_SESSION },
(renderSlot) => renderSlot('k.session', {}))
renderSlot => renderSlot('k.session', {}))
expect(view.container.querySelector('b')).toBeNull()
})
it('delivers the store pair for store-declaring entries and writes through baked actions', () => {
const h = makeHost()
h.declare('k.single', SINGLE_ROOT)
const handle = miniStore(() => ({ n: 0 }), { inc: (s) => ({ n: s.n + 1 }) })
const handle = miniStore(() => ({ n: 0 }), { inc: s => ({ n: s.n + 1 }) })
let bump = () => {}
h.add('k.single', {
component: ({ useStore, actions }: {
@@ -684,11 +684,11 @@ describe('standard-kit synthesis', () => {
actions: { inc: () => void }
}) => {
bump = actions.inc
return <b>{useStore((s) => s.n)}</b>
return <b>{useStore(s => s.n)}</b>
},
store: handle,
})
const { view } = mountRoot(h, { 'k.single': SINGLE_ROOT }, (renderSlot) => renderSlot('k.single', {}))
const { view } = mountRoot(h, { 'k.single': SINGLE_ROOT }, renderSlot => renderSlot('k.single', {}))
expect(view.container.textContent).toBe('0')
act(() => { bump() })
expect(view.container.textContent).toBe('1')
@@ -707,11 +707,11 @@ describe('standard-kit synthesis', () => {
actions: { setDraft: (text: string) => void }
}) => {
setDraft = actions.setDraft
return <b>{useStore((s) => s.draft) || '(blank)'}</b>
return <b>{useStore(s => s.draft) || '(blank)'}</b>
},
store: handle,
})
const { view } = mountRoot(h, { 'k.session': SINGLE_SESSION }, (renderSlot) => (
const { view } = mountRoot(h, { 'k.session': SINGLE_SESSION }, renderSlot => (
<SessionProvider>{() => renderSlot('k.session', {})}</SessionProvider>
))
act(() => { h.current.set('s1') })
@@ -730,7 +730,7 @@ describe('inject: execution point, parameter derivation, cache granularity', ()
h.declare('k.single', SINGLE_ROOT)
const inject = vi.fn(() => ({ tag: 'FROM-INJECT' }))
h.add('k.single', { component: ({ tag }: { tag?: string }) => <b>{tag}</b>, inject })
const { view } = mountRoot(h, { 'k.single': SINGLE_ROOT }, (renderSlot) => renderSlot('k.single', {}))
const { view } = mountRoot(h, { 'k.single': SINGLE_ROOT }, renderSlot => renderSlot('k.single', {}))
expect(view.container.textContent).toBe('FROM-INJECT')
act(() => { h.add('k.single', { component: () => null }) }) // sibling bump re-renders the outlet
expect(inject).toHaveBeenCalledTimes(1)
@@ -745,9 +745,9 @@ describe('inject: execution point, parameter derivation, cache granularity', ()
const inject = vi.fn((sessionId: string) => ({ sid: sessionId }))
h.add('k.session', {
component: ({ sid }: { sid?: string }) => <b>{sid}</b>,
inject: inject as unknown as StoredEntry['inject'],
inject: inject,
})
const { view } = mountRoot(h, { 'k.session': SINGLE_SESSION }, (renderSlot) => (
const { view } = mountRoot(h, { 'k.session': SINGLE_SESSION }, renderSlot => (
<SessionProvider>{() => renderSlot('k.session', {})}</SessionProvider>
))
act(() => { h.current.set('s1') })
@@ -767,22 +767,22 @@ describe('inject: execution point, parameter derivation, cache granularity', ()
h.declare('k.single', SINGLE_ROOT)
h.declare('k.session', SINGLE_SESSION)
h.addSession('s1')
const handle = miniStore(() => ({ n: 0 }), { inc: (s) => ({ n: s.n + 1 }) })
const handle = miniStore(() => ({ n: 0 }), { inc: s => ({ n: s.n + 1 }) })
const rootInject = vi.fn((actions: { inc: () => void }) => ({ viaRoot: actions }))
const sessionInject = vi.fn((sessionId: string, actions: { inc: () => void }) => ({ sid: sessionId, viaSession: actions }))
const seenRoot: AnyProps[] = []
const seenSession: AnyProps[] = []
h.add('k.single', {
component: (props: object) => { seenRoot.push(props as AnyProps); return null },
inject: rootInject as unknown as StoredEntry['inject'],
inject: rootInject,
store: handle,
})
h.add('k.session', {
component: (props: object) => { seenSession.push(props as AnyProps); return null },
inject: sessionInject as unknown as StoredEntry['inject'],
inject: sessionInject,
store: handle,
})
mountRoot(h, { 'k.single': SINGLE_ROOT, 'k.session': SINGLE_SESSION }, (renderSlot) => <>
mountRoot(h, { 'k.single': SINGLE_ROOT, 'k.session': SINGLE_SESSION }, renderSlot => <>
{renderSlot('k.single', {})}
<SessionProvider>{() => renderSlot('k.session', {})}</SessionProvider>
</>)
@@ -807,7 +807,7 @@ describe('inject: execution point, parameter derivation, cache granularity', ()
h.add('k.list', { component: () => <span>alive</span>, options: { id: 'ok', order: 2 } })
const spy = vi.spyOn(console, 'error').mockImplementation(() => {})
const { view } = mountRoot(h, { 'k.list': { kind: 'list', scope: 'root' } },
(renderSlot) => <main>{renderSlot('k.list', {})}</main>)
renderSlot => <main>{renderSlot('k.list', {})}</main>)
spy.mockRestore()
// The failing entry blacks out alone; the sibling and the tree above survive.
expect(view.container.querySelector('main')).not.toBeNull()
@@ -824,7 +824,7 @@ describe('inject: execution point, parameter derivation, cache granularity', ()
inject: () => ({ fromInject: 'inject', shared: 'inject' }),
})
mountRoot(h, { 'k.single': SINGLE_ROOT },
(renderSlot) => renderSlot('k.single', { owner: 'owner', shared: 'owner' }))
renderSlot => renderSlot('k.single', { owner: 'owner', shared: 'owner' }))
const props = seen.at(-1)!
expect(typeof props['useSessions']).toBe('function') // kit always present
expect(typeof props['useWorkspaces']).toBe('function')

View File

@@ -43,15 +43,15 @@ function makeHost(bodies: { root: (rp: (key: string, owner: object) => React.Rea
const host: SlotRendererHost = {
subscribe: () => () => {},
getVersion: () => 0,
entriesOf: (key) => key === 'root' ? [rootEntry] : sessionEntries,
specOf: (key) => key === 'k.session' ? { kind: 'single', scope: 'session' } : undefined,
entriesOf: key => key === 'root' ? [rootEntry] : sessionEntries,
specOf: key => key === 'k.session' ? { kind: 'single', scope: 'session' } : undefined,
isLive: () => true,
storeOf: () => undefined,
sessions: {
list: observable<unknown>({ ids: [] }),
current,
provideInfo: (id) => infos.get(id),
maybeProvideInfo: (id) => (id === undefined ? undefined : infos.get(id))
provideInfo: id => infos.get(id),
maybeProvideInfo: id => (id === undefined ? undefined : infos.get(id))
?? { sessionId: undefined, hooks: { session: undefined }, props: {} },
},
workspaces: { list: observable<unknown>({ items: [] }) },
@@ -78,7 +78,7 @@ describe('SessionProvider', () => {
const h = makeHost({
root: () => (
<SessionProvider empty={() => <span>empty</span>}>
{(id) => <div data-testid="body">{id}</div>}
{id => <div data-testid="body">{id}</div>}
</SessionProvider>
),
})
@@ -93,7 +93,7 @@ describe('SessionProvider', () => {
it('renders null empty state when the empty prop is omitted', () => {
const h = makeHost({
root: () => <SessionProvider>{(id) => <b>{id}</b>}</SessionProvider>,
root: () => <SessionProvider>{id => <b>{id}</b>}</SessionProvider>,
})
const view = render(<>{createSlotRenderer().renderRoot(h.host, {})}</>)
expect(view.container.textContent).toBe('')
@@ -110,7 +110,7 @@ describe('SessionProvider', () => {
return <div>{id}</div>
}
const h = makeHost({
root: () => <SessionProvider>{(id) => <Body id={id} />}</SessionProvider>,
root: () => <SessionProvider>{id => <Body id={id} />}</SessionProvider>,
})
h.addSession('s1')
h.addSession('s2')
@@ -127,7 +127,7 @@ describe('SessionProvider', () => {
it('delivers the resolved cell to session slots under it (observable behavior, not context internals)', () => {
const seen: Record<string, unknown>[] = []
const h = makeHost({
root: (renderSlot) => <SessionProvider>{() => renderSlot('k.session', {})}</SessionProvider>,
root: renderSlot => <SessionProvider>{() => renderSlot('k.session', {})}</SessionProvider>,
})
h.addSession('s1')
h.addSession('s2')
@@ -135,7 +135,7 @@ describe('SessionProvider', () => {
component: (props: { useSession?: <S>(sel: (s: { sid: string }) => S) => S; sessionId?: string }) => {
// The bound hook reads the cell's bare source — asserting through it
// proves the machinery wired THIS session's source, not another's.
seen.push({ sessionId: props.sessionId, read: props.useSession!((s) => s.sid) })
seen.push({ sessionId: props.sessionId, read: props.useSession!(s => s.sid) })
return null
},
options: {},
@@ -152,7 +152,7 @@ describe('SessionProvider', () => {
it('fails loud when mounted outside the renderer tree (no host channel)', () => {
const spy = vi.spyOn(console, 'error').mockImplementation(() => {})
expect(() => render(
<SessionProvider>{(id) => <b>{id}</b>}</SessionProvider>,
<SessionProvider>{id => <b>{id}</b>}</SessionProvider>,
)).toThrow(/outside the installed renderer tree/)
spy.mockRestore()
})

View File

@@ -32,10 +32,10 @@ function makeHost() {
subs.set(key, set)
return () => { set.delete(fn) }
},
getVersion: (key) => versions.get(key) ?? 0,
entriesOf: (key) => entries.get(key) ?? [],
getVersion: key => versions.get(key) ?? 0,
entriesOf: key => entries.get(key) ?? [],
specOf: () => ({ kind: 'single', scope: 'root' }),
isLive: (entry) => live.has(entry),
isLive: entry => live.has(entry),
storeOf: () => undefined,
sessions: {
list: { getSnapshot: () => ({}), subscribe: () => () => {} },
@@ -54,7 +54,7 @@ function makeHost() {
live.add(entry)
bump(key)
return () => {
entries.set(key, (entries.get(key) ?? []).filter((e) => e !== entry))
entries.set(key, (entries.get(key) ?? []).filter(e => e !== entry))
live.delete(entry)
bump(key)
}