fix(ui): preserve upstream behavior after performance rebase
This commit is contained in:
@@ -284,7 +284,7 @@ const initializePerformanceDom = async (): Promise<void> => {
|
||||
mock.module('@/hooks/useEffectiveDirectory', () => ({ useEffectiveDirectory: () => null }));
|
||||
mock.module('@/hooks/useRuntimeAPIs', () => ({ useRuntimeAPIs: () => ({ editor: undefined, runtime: { isVSCode: false } }) }));
|
||||
mock.module('@/lib/runtime-fetch', () => ({ runtimeFetch: async () => ({ ok: false }) }));
|
||||
mock.module('@/lib/url', () => ({ isExternalHttpUrl: () => false, openExternalUrl: async () => undefined, getExternalFaviconUrl: () => null, isLoopbackHttpUrl: () => false }));
|
||||
mock.module('@/lib/url', () => ({ getUrlScheme: () => null, isAppLinkUrl: () => false, isExternalHttpUrl: () => false, openConfirmedAppLinkUrl: async () => false, openExternalUrl: async () => undefined, getExternalFaviconUrl: () => null, isLoopbackHttpUrl: () => false }));
|
||||
mock.module('@/lib/desktop', () => ({ isDesktopLocalOriginActive: () => false, isDesktopShell: () => false, isVSCodeRuntime: () => false }));
|
||||
mock.module('@/lib/runtimeSurface', () => ({ isMobileSurfaceRuntime: () => false }));
|
||||
mock.module('@/lib/outsideFileGrants', () => ({ ensureOutsideFileGrantForDesktop: async () => undefined }));
|
||||
|
||||
@@ -48,6 +48,7 @@ let hookStates: Array<{ current: null } | undefined> = [];
|
||||
let activeFakeDocument: FakeDocument | null = null;
|
||||
|
||||
const makeFakeElement = (ownerDocument: { createElement: () => FakeElement }): FakeElement => {
|
||||
void ownerDocument;
|
||||
let html = '';
|
||||
const element: FakeElement = {
|
||||
childNodes: [],
|
||||
@@ -184,6 +185,7 @@ const fakeReact = {
|
||||
return factory();
|
||||
},
|
||||
useRef: <T>(current: T) => {
|
||||
void current;
|
||||
const index = hookCursor;
|
||||
hookCursor += 1;
|
||||
if (!hookStates[index]) hookStates[index] = { current: null };
|
||||
|
||||
@@ -1080,8 +1080,9 @@ const MarkdownRendererImpl: React.FC<MarkdownRendererProps> = ({
|
||||
scope: `${runtimeKey}\0${settledPart.sessionID}`,
|
||||
id: `${settledPart.messageID}\0${settledPart.id}\0${imageMode}`,
|
||||
locale,
|
||||
directory: effectiveDirectory,
|
||||
};
|
||||
}, [content.length, imageMode, isStreaming, locale, runtimeKey, settledPart]);
|
||||
}, [content.length, effectiveDirectory, imageMode, isStreaming, locale, runtimeKey, settledPart]);
|
||||
// Identity for the fade-in wrapper: a new part/message restarts the animation.
|
||||
const fadeKey = `markdown-${part?.id ? `part-${part.id}` : `message-${messageId}`}`;
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import { DetachedMarkdownDomCache, type DetachedMarkdownDom } from './detachedMa
|
||||
|
||||
Object.assign(globalThis, { document: new Window().document });
|
||||
|
||||
const keyFor = ({ scope, id, locale }: DetachedMarkdownDom) => ({ scope, id, locale });
|
||||
const keyFor = ({ scope, id, locale, directory }: DetachedMarkdownDom) => ({ scope, id, locale, directory });
|
||||
|
||||
const createEntry = (
|
||||
document: Document,
|
||||
@@ -21,6 +21,7 @@ const createEntry = (
|
||||
scope: `runtime:${sessionId}`,
|
||||
id: `${messageId}:${partId}`,
|
||||
locale: 'en',
|
||||
directory: '/repo-a',
|
||||
fragment,
|
||||
};
|
||||
};
|
||||
@@ -51,11 +52,13 @@ describe('DetachedMarkdownDomCache', () => {
|
||||
scope: 'runtime:session-a',
|
||||
id: 'message-2:part',
|
||||
locale: 'en',
|
||||
directory: '/repo-a',
|
||||
})).toBeNull();
|
||||
expect(cache.take({
|
||||
scope: 'runtime:session-c',
|
||||
id: 'message-5:part',
|
||||
locale: 'en',
|
||||
directory: '/repo-a',
|
||||
})).not.toBeNull();
|
||||
});
|
||||
|
||||
@@ -75,6 +78,15 @@ describe('DetachedMarkdownDomCache', () => {
|
||||
expect(cache.take(keyFor(replacement))?.firstChild).toBe(replacementNode);
|
||||
});
|
||||
|
||||
test('does not restore file-link DOM under another directory', () => {
|
||||
const cache = new DetachedMarkdownDomCache({ maxSessions: 2, maxEntriesPerSession: 2 });
|
||||
const entry = createEntry(document, 'session', 'message', 'part');
|
||||
|
||||
cache.store(entry);
|
||||
|
||||
expect(cache.take({ ...keyFor(entry), directory: '/repo-b' })).toBeNull();
|
||||
});
|
||||
|
||||
test('refreshes session LRU and clears all entries', () => {
|
||||
const cache = new DetachedMarkdownDomCache({ maxSessions: 2, maxEntriesPerSession: 2 });
|
||||
const sessionA = createEntry(document, 'session-a', 'message-a', 'part');
|
||||
|
||||
@@ -2,6 +2,7 @@ export type DetachedMarkdownDomKey = {
|
||||
scope: string;
|
||||
id: string;
|
||||
locale: string;
|
||||
directory: string;
|
||||
};
|
||||
|
||||
export type DetachedMarkdownDom = DetachedMarkdownDomKey & {
|
||||
@@ -79,7 +80,7 @@ export class DetachedMarkdownDomCache {
|
||||
// A fragment is a move-only resource; taking it removes cache ownership.
|
||||
session.delete(entryKey);
|
||||
if (session.size === 0) this.sessions.delete(sessionKey);
|
||||
if (entry.locale !== key.locale) return null;
|
||||
if (entry.locale !== key.locale || entry.directory !== key.directory) return null;
|
||||
return entry.fragment;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user