mirror of
https://github.com/microsoft/vscode.git
synced 2026-08-16 11:17:35 +01:00
* telemetry: report ResizeObserver delivery context The browser's ResizeObserver loop ErrorEvent contains only a generic message; it does not expose the skipped target or causative callback. Prefixing that warning with the most recently invoked DisposableResizeObserver therefore turned callback order into false causal attribution. Record the wrapped observers that ran in the current rendering frame instead. Context is scoped per window, deduplicated, sorted for stable bucketing, and bounded to the canonical smallest eight names plus an overflow marker. The telemetry prefix explicitly calls these recent wrapped observers rather than an offending consumer. Clear context at the next animation frame, after Blink dispatches any loop warning from the current rendering update. Unit coverage locks deduplication, canonical overflow, window isolation, and frame cleanup; a real Chromium component fixture deliberately triggers a self-resize loop and verifies context survives until the native warning. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: aacd276e-cf84-48bd-a2ab-6f6a4d4c3431 * telemetry: shorten ResizeObserver context prefix ResizeObserverLoopContext already identifies the observer names as non-causal context, so remove the redundant ecentWrappedObservers= label from the emitted error string. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: aacd276e-cf84-48bd-a2ab-6f6a4d4c3431 --------- Copilot-Session: aacd276e-cf84-48bd-a2ab-6f6a4d4c3431
52 lines
2.6 KiB
TypeScript
52 lines
2.6 KiB
TypeScript
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
|
|
import { expect, test } from '@playwright/test';
|
|
import { openFixture } from './utils.js';
|
|
|
|
const scenarios = [
|
|
{ name: 'no host layout', fixture: 'ResizeObserverLoopNoHostLayout', expectedWarnings: 0 },
|
|
{ name: 'list-only layout', fixture: 'ResizeObserverLoopListOnly', expectedWarnings: 0 },
|
|
{ name: 'stacked full layout', fixture: 'ResizeObserverLoopHarness', expectedWarnings: 0 },
|
|
{ name: 'stacked targeted layout', fixture: 'ResizeObserverLoopStackedTargeted', expectedWarnings: 0 },
|
|
] as const;
|
|
|
|
for (const scenario of scenarios) {
|
|
test(`runs the mocked chat resize-observer burst harness with ${scenario.name}`, async ({ page }) => {
|
|
const resizeObserverErrors: string[] = [];
|
|
page.on('pageerror', error => {
|
|
if (error.message.includes('ResizeObserver loop')) {
|
|
resizeObserverErrors.push(error.message);
|
|
}
|
|
});
|
|
|
|
await openFixture(page, `chat/widget/chatWidget/${scenario.fixture}/Dark`, '.resize-observer-loop-harness');
|
|
await page.getByRole('button', { name: 'Run 20-turn burst' }).click();
|
|
await expect(page.getByRole('status')).toContainText(/Completed/, { timeout: 30_000 });
|
|
const warningText = await page.locator('.resize-observer-loop-warnings').textContent();
|
|
const observerContext = await page.locator('.resize-observer-loop-warnings').getAttribute('data-observer-context');
|
|
console.log(`[chat-resize-harness:${scenario.name}] ${warningText}; page errors: ${resizeObserverErrors.length}; observer context: ${observerContext}`);
|
|
const warningCount = Number(warningText?.replace('Warnings: ', ''));
|
|
expect(warningCount).toBe(scenario.expectedWarnings);
|
|
if (scenario.name === 'stacked targeted layout') {
|
|
const geometry = await page.locator('.interactive-list').evaluate(element => {
|
|
const list = element.querySelector<HTMLElement>('.monaco-list');
|
|
return {
|
|
expectedHeight: Number((element as HTMLElement).dataset['expectedHeight']),
|
|
containerHeight: element.getBoundingClientRect().height,
|
|
listHeight: list?.getBoundingClientRect().height,
|
|
};
|
|
});
|
|
expect(geometry.containerHeight).toBeCloseTo(geometry.expectedHeight);
|
|
expect(geometry.listHeight).toBeCloseTo(geometry.expectedHeight);
|
|
}
|
|
|
|
await test.info().attach('resize-observer-errors.json', {
|
|
body: Buffer.from(JSON.stringify(resizeObserverErrors, null, 2)),
|
|
contentType: 'application/json',
|
|
});
|
|
});
|
|
}
|