-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Open
Labels
Description
Node.js version
20.19.1
jsdom version
27.1.0
Minimal reproduction case
// package.json
{
"name": "jsdom-regression-repro",
"version": "1.0.0",
"type": "module",
"scripts": {
"start": "node compare.js"
},
"dependencies": {
"jsdom-26": "npm:jsdom@26.0.0",
"jsdom-27": "npm:jsdom@27.1.0"
}
}<!-- jsdom-regression-repro.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>jsdom Performance Regression Test</title>
</head>
<body>
<div></div>
<div>
<div class="MuiDateRangeCalendar-root">
<div class="MuiDateRangeCalendar-monthContainer">
<div class="MuiPickersArrowSwitcher-root">
<button
class="MuiButtonBase-root MuiIconButton-root"
tabindex="0"
type="button"
title="Previous month"
aria-label="Previous month"
>
<svg
class="MuiSvgIcon-root"
focusable="false"
aria-hidden="true"
viewBox="0 0 24 24"
data-testid="ArrowLeftIcon"
>
<path
d="M15.41 16.59L10.83 12l4.58-4.59L14 6l-6 6 6 6 1.41-1.41z"
></path>
</svg>
</button>
<span class="MuiTypography-root" id="_r_0_-grid-0-label"
>January 2019</span
>
<button
class="MuiButtonBase-root MuiIconButton-root"
tabindex="0"
type="button"
title="Next month"
aria-label="Next month"
>
<svg
class="MuiSvgIcon-root"
focusable="false"
aria-hidden="true"
viewBox="0 0 24 24"
data-testid="ArrowRightIcon"
>
<path
d="M8.59 16.59L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.41z"
></path>
</svg>
</button>
</div>
<div
role="grid"
aria-labelledby="_r_0_-grid-0-label"
class="MuiDayCalendar-root"
>
<div role="row" class="MuiDayCalendar-header">
<span
class="MuiTypography-root"
role="columnheader"
aria-label="Sunday"
>S</span
>
<span
class="MuiTypography-root"
role="columnheader"
aria-label="Monday"
>M</span
>
<span
class="MuiTypography-root"
role="columnheader"
aria-label="Tuesday"
>T</span
>
<span
class="MuiTypography-root"
role="columnheader"
aria-label="Wednesday"
>W</span
>
<span
class="MuiTypography-root"
role="columnheader"
aria-label="Thursday"
>T</span
>
<span
class="MuiTypography-root"
role="columnheader"
aria-label="Friday"
>F</span
>
<span
class="MuiTypography-root"
role="columnheader"
aria-label="Saturday"
>S</span
>
</div>
<div class="MuiPickersSlideTransition-root" role="presentation">
<div
data-testid="pickers-calendar"
role="rowgroup"
class="MuiDayCalendar-monthContainer"
>
<div
role="row"
class="MuiDayCalendar-weekContainer"
aria-rowindex="1"
>
<div
class="MuiDateRangePickerDay-root MuiDateRangePickerDay-outsideCurrentMonth MuiDateRangePickerDay-hiddenDayFiller"
>
<div class="MuiDateRangePickerDay-rangeIntervalPreview">
<div
class="MuiPickersDay-root MuiPickersDay-hiddenDaySpacingFiller"
role="gridcell"
></div>
</div>
</div>
<div
class="MuiDateRangePickerDay-root MuiDateRangePickerDay-outsideCurrentMonth MuiDateRangePickerDay-endOfMonth MuiDateRangePickerDay-hiddenDayFiller"
>
<div
class="MuiDateRangePickerDay-rangeIntervalPreview MuiDateRangePickerDay-rangeIntervalDayPreviewEnd"
>
<div
class="MuiPickersDay-root MuiPickersDay-hiddenDaySpacingFiller"
role="gridcell"
></div>
</div>
</div>
<div
class="MuiDateRangePickerDay-root MuiDateRangePickerDay-startOfMonth MuiDateRangePickerDay-firstVisibleCell"
>
<div
class="MuiDateRangePickerDay-rangeIntervalPreview MuiDateRangePickerDay-rangeIntervalDayPreviewStart"
>
<button
class="MuiButtonBase-root MuiPickersDay-root MuiDateRangePickerDay-day"
tabindex="0"
type="button"
data-testid="DateRangePickerDay"
role="gridcell"
data-timestamp="1546300800000"
aria-colindex="3"
aria-selected="false"
>
1
</button>
</div>
</div>
<div class="MuiDateRangePickerDay-root">
<div class="MuiDateRangePickerDay-rangeIntervalPreview">
<button
class="MuiButtonBase-root MuiPickersDay-root MuiDateRangePickerDay-day"
tabindex="-1"
type="button"
data-testid="DateRangePickerDay"
role="gridcell"
data-timestamp="1546387200000"
aria-colindex="4"
aria-selected="false"
>
2
</button>
</div>
</div>
<div class="MuiDateRangePickerDay-root">
<div class="MuiDateRangePickerDay-rangeIntervalPreview">
<button
class="MuiButtonBase-root MuiPickersDay-root MuiDateRangePickerDay-day"
tabindex="-1"
type="button"
data-testid="DateRangePickerDay"
role="gridcell"
data-timestamp="1546473600000"
aria-colindex="5"
aria-selected="false"
>
3
</button>
</div>
</div>
<div class="MuiDateRangePickerDay-root">
<div class="MuiDateRangePickerDay-rangeIntervalPreview">
<button
class="MuiButtonBase-root MuiPickersDay-root MuiDateRangePickerDay-day"
tabindex="-1"
type="button"
data-testid="DateRangePickerDay"
role="gridcell"
data-timestamp="1546560000000"
aria-colindex="6"
aria-selected="false"
>
4
</button>
</div>
</div>
<div class="MuiDateRangePickerDay-root">
<div class="MuiDateRangePickerDay-rangeIntervalPreview">
<button
class="MuiButtonBase-root MuiPickersDay-root MuiDateRangePickerDay-day"
tabindex="-1"
type="button"
data-testid="DateRangePickerDay"
role="gridcell"
data-timestamp="1546646400000"
aria-colindex="7"
aria-selected="false"
>
5
</button>
</div>
</div>
</div>
<div
role="row"
class="MuiDayCalendar-weekContainer"
aria-rowindex="2"
>
<div class="MuiDateRangePickerDay-root">
<div class="MuiDateRangePickerDay-rangeIntervalPreview">
<button
class="MuiButtonBase-root MuiPickersDay-root MuiDateRangePickerDay-day"
tabindex="-1"
type="button"
data-testid="DateRangePickerDay"
role="gridcell"
data-timestamp="1546732800000"
aria-colindex="1"
aria-selected="false"
>
6
</button>
</div>
</div>
<div class="MuiDateRangePickerDay-root">
<div class="MuiDateRangePickerDay-rangeIntervalPreview">
<button
class="MuiButtonBase-root MuiPickersDay-root MuiDateRangePickerDay-day"
tabindex="-1"
type="button"
data-testid="DateRangePickerDay"
role="gridcell"
data-timestamp="1546819200000"
aria-colindex="2"
aria-selected="false"
>
7
</button>
</div>
</div>
<div class="MuiDateRangePickerDay-root">
<div class="MuiDateRangePickerDay-rangeIntervalPreview">
<button
class="MuiButtonBase-root MuiPickersDay-root MuiDateRangePickerDay-day"
tabindex="-1"
type="button"
data-testid="DateRangePickerDay"
role="gridcell"
data-timestamp="1546905600000"
aria-colindex="3"
aria-selected="false"
>
8
</button>
</div>
</div>
<div class="MuiDateRangePickerDay-root">
<div class="MuiDateRangePickerDay-rangeIntervalPreview">
<button
class="MuiButtonBase-root MuiPickersDay-root MuiDateRangePickerDay-day"
tabindex="-1"
type="button"
data-testid="DateRangePickerDay"
role="gridcell"
data-timestamp="1546992000000"
aria-colindex="4"
aria-selected="false"
>
9
</button>
</div>
</div>
<div class="MuiDateRangePickerDay-root">
<div class="MuiDateRangePickerDay-rangeIntervalPreview">
<button
class="MuiButtonBase-root MuiPickersDay-root MuiDateRangePickerDay-day"
tabindex="-1"
type="button"
data-testid="DateRangePickerDay"
role="gridcell"
data-timestamp="1547078400000"
aria-colindex="5"
aria-selected="false"
>
10
</button>
</div>
</div>
<div class="MuiDateRangePickerDay-root">
<div class="MuiDateRangePickerDay-rangeIntervalPreview">
<button
class="MuiButtonBase-root MuiPickersDay-root MuiDateRangePickerDay-day"
tabindex="-1"
type="button"
data-testid="DateRangePickerDay"
role="gridcell"
data-timestamp="1547164800000"
aria-colindex="6"
aria-selected="false"
>
11
</button>
</div>
</div>
<div class="MuiDateRangePickerDay-root">
<div class="MuiDateRangePickerDay-rangeIntervalPreview">
<button
class="MuiButtonBase-root MuiPickersDay-root MuiDateRangePickerDay-day"
tabindex="-1"
type="button"
data-testid="DateRangePickerDay"
role="gridcell"
data-timestamp="1547251200000"
aria-colindex="7"
aria-selected="false"
>
12
</button>
</div>
</div>
</div>
<div
role="row"
class="MuiDayCalendar-weekContainer"
aria-rowindex="3"
>
<div class="MuiDateRangePickerDay-root">
<div class="MuiDateRangePickerDay-rangeIntervalPreview">
<button
class="MuiButtonBase-root MuiPickersDay-root MuiDateRangePickerDay-day"
tabindex="-1"
type="button"
data-testid="DateRangePickerDay"
role="gridcell"
data-timestamp="1547337600000"
aria-colindex="1"
aria-selected="false"
>
13
</button>
</div>
</div>
<div class="MuiDateRangePickerDay-root">
<div class="MuiDateRangePickerDay-rangeIntervalPreview">
<button
class="MuiButtonBase-root MuiPickersDay-root MuiDateRangePickerDay-day"
tabindex="-1"
type="button"
data-testid="DateRangePickerDay"
role="gridcell"
data-timestamp="1547424000000"
aria-colindex="2"
aria-selected="false"
>
14
</button>
</div>
</div>
<div class="MuiDateRangePickerDay-root">
<div class="MuiDateRangePickerDay-rangeIntervalPreview">
<button
class="MuiButtonBase-root MuiPickersDay-root MuiDateRangePickerDay-day"
tabindex="-1"
type="button"
data-testid="DateRangePickerDay"
role="gridcell"
data-timestamp="1547510400000"
aria-colindex="3"
aria-selected="false"
>
15
</button>
</div>
</div>
<div class="MuiDateRangePickerDay-root">
<div class="MuiDateRangePickerDay-rangeIntervalPreview">
<button
class="MuiButtonBase-root MuiPickersDay-root MuiDateRangePickerDay-day"
tabindex="-1"
type="button"
data-testid="DateRangePickerDay"
role="gridcell"
data-timestamp="1547596800000"
aria-colindex="4"
aria-selected="false"
>
16
</button>
</div>
</div>
<div class="MuiDateRangePickerDay-root">
<div class="MuiDateRangePickerDay-rangeIntervalPreview">
<button
class="MuiButtonBase-root MuiPickersDay-root MuiDateRangePickerDay-day"
tabindex="-1"
type="button"
data-testid="DateRangePickerDay"
role="gridcell"
data-timestamp="1547683200000"
aria-colindex="5"
aria-selected="false"
>
17
</button>
</div>
</div>
<div class="MuiDateRangePickerDay-root">
<div class="MuiDateRangePickerDay-rangeIntervalPreview">
<button
class="MuiButtonBase-root MuiPickersDay-root MuiDateRangePickerDay-day"
tabindex="-1"
type="button"
data-testid="DateRangePickerDay"
role="gridcell"
data-timestamp="1547769600000"
aria-colindex="6"
aria-selected="false"
>
18
</button>
</div>
</div>
<div class="MuiDateRangePickerDay-root">
<div class="MuiDateRangePickerDay-rangeIntervalPreview">
<button
class="MuiButtonBase-root MuiPickersDay-root MuiDateRangePickerDay-day"
tabindex="-1"
type="button"
data-testid="DateRangePickerDay"
role="gridcell"
data-timestamp="1547856000000"
aria-colindex="7"
aria-selected="false"
>
19
</button>
</div>
</div>
</div>
<div
role="row"
class="MuiDayCalendar-weekContainer"
aria-rowindex="4"
>
<div class="MuiDateRangePickerDay-root">
<div class="MuiDateRangePickerDay-rangeIntervalPreview">
<button
class="MuiButtonBase-root MuiPickersDay-root MuiDateRangePickerDay-day"
tabindex="-1"
type="button"
data-testid="DateRangePickerDay"
role="gridcell"
data-timestamp="1547942400000"
aria-colindex="1"
aria-selected="false"
>
20
</button>
</div>
</div>
<div class="MuiDateRangePickerDay-root">
<div class="MuiDateRangePickerDay-rangeIntervalPreview">
<button
class="MuiButtonBase-root MuiPickersDay-root MuiDateRangePickerDay-day"
tabindex="-1"
type="button"
data-testid="DateRangePickerDay"
role="gridcell"
data-timestamp="1548028800000"
aria-colindex="2"
aria-selected="false"
>
21
</button>
</div>
</div>
<div class="MuiDateRangePickerDay-root">
<div class="MuiDateRangePickerDay-rangeIntervalPreview">
<button
class="MuiButtonBase-root MuiPickersDay-root MuiDateRangePickerDay-day"
tabindex="-1"
type="button"
data-testid="DateRangePickerDay"
role="gridcell"
data-timestamp="1548115200000"
aria-colindex="3"
aria-selected="false"
>
22
</button>
</div>
</div>
<div class="MuiDateRangePickerDay-root">
<div class="MuiDateRangePickerDay-rangeIntervalPreview">
<button
class="MuiButtonBase-root MuiPickersDay-root MuiDateRangePickerDay-day"
tabindex="-1"
type="button"
data-testid="DateRangePickerDay"
role="gridcell"
data-timestamp="1548201600000"
aria-colindex="4"
aria-selected="false"
>
23
</button>
</div>
</div>
<div class="MuiDateRangePickerDay-root">
<div class="MuiDateRangePickerDay-rangeIntervalPreview">
<button
class="MuiButtonBase-root MuiPickersDay-root MuiDateRangePickerDay-day"
tabindex="-1"
type="button"
data-testid="DateRangePickerDay"
role="gridcell"
data-timestamp="1548288000000"
aria-colindex="5"
aria-selected="false"
>
24
</button>
</div>
</div>
<div class="MuiDateRangePickerDay-root">
<div class="MuiDateRangePickerDay-rangeIntervalPreview">
<button
class="MuiButtonBase-root MuiPickersDay-root MuiDateRangePickerDay-day"
tabindex="-1"
type="button"
data-testid="DateRangePickerDay"
role="gridcell"
data-timestamp="1548374400000"
aria-colindex="6"
aria-selected="false"
>
25
</button>
</div>
</div>
<div class="MuiDateRangePickerDay-root">
<div class="MuiDateRangePickerDay-rangeIntervalPreview">
<button
class="MuiButtonBase-root MuiPickersDay-root MuiDateRangePickerDay-day"
tabindex="-1"
type="button"
data-testid="DateRangePickerDay"
role="gridcell"
data-timestamp="1548460800000"
aria-colindex="7"
aria-selected="false"
>
26
</button>
</div>
</div>
</div>
<div
role="row"
class="MuiDayCalendar-weekContainer"
aria-rowindex="5"
>
<div class="MuiDateRangePickerDay-root">
<div class="MuiDateRangePickerDay-rangeIntervalPreview">
<button
class="MuiButtonBase-root MuiPickersDay-root MuiDateRangePickerDay-day"
tabindex="-1"
type="button"
data-testid="DateRangePickerDay"
role="gridcell"
data-timestamp="1548547200000"
aria-colindex="1"
aria-selected="false"
>
27
</button>
</div>
</div>
<div class="MuiDateRangePickerDay-root">
<div class="MuiDateRangePickerDay-rangeIntervalPreview">
<button
class="MuiButtonBase-root MuiPickersDay-root MuiDateRangePickerDay-day"
tabindex="-1"
type="button"
data-testid="DateRangePickerDay"
role="gridcell"
data-timestamp="1548633600000"
aria-colindex="2"
aria-selected="false"
>
28
</button>
</div>
</div>
<div class="MuiDateRangePickerDay-root">
<div class="MuiDateRangePickerDay-rangeIntervalPreview">
<button
class="MuiButtonBase-root MuiPickersDay-root MuiDateRangePickerDay-day"
tabindex="-1"
type="button"
data-testid="DateRangePickerDay"
role="gridcell"
data-timestamp="1548720000000"
aria-colindex="3"
aria-selected="false"
>
29
</button>
</div>
</div>
<div class="MuiDateRangePickerDay-root">
<div class="MuiDateRangePickerDay-rangeIntervalPreview">
<button
class="MuiButtonBase-root MuiPickersDay-root MuiDateRangePickerDay-day"
tabindex="-1"
type="button"
data-testid="DateRangePickerDay"
role="gridcell"
data-timestamp="1548806400000"
aria-colindex="4"
aria-selected="false"
>
30
</button>
</div>
</div>
<div
class="MuiDateRangePickerDay-root MuiDateRangePickerDay-endOfMonth MuiDateRangePickerDay-lastVisibleCell"
>
<div
class="MuiDateRangePickerDay-rangeIntervalPreview MuiDateRangePickerDay-rangeIntervalDayPreviewEnd"
>
<button
class="MuiButtonBase-root MuiPickersDay-root MuiDateRangePickerDay-day"
tabindex="-1"
type="button"
data-testid="DateRangePickerDay"
role="gridcell"
data-timestamp="1548892800000"
aria-colindex="5"
aria-selected="false"
>
31
</button>
</div>
</div>
<div
class="MuiDateRangePickerDay-root MuiDateRangePickerDay-outsideCurrentMonth MuiDateRangePickerDay-startOfMonth MuiDateRangePickerDay-hiddenDayFiller"
>
<div
class="MuiDateRangePickerDay-rangeIntervalPreview MuiDateRangePickerDay-rangeIntervalDayPreviewStart"
>
<div
class="MuiPickersDay-root MuiPickersDay-hiddenDaySpacingFiller"
role="gridcell"
></div>
</div>
</div>
<div
class="MuiDateRangePickerDay-root MuiDateRangePickerDay-outsideCurrentMonth MuiDateRangePickerDay-hiddenDayFiller"
>
<div class="MuiDateRangePickerDay-rangeIntervalPreview">
<div
class="MuiPickersDay-root MuiPickersDay-hiddenDaySpacingFiller"
role="gridcell"
></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="MuiDateRangeCalendar-monthContainer">
<div class="MuiPickersArrowSwitcher-root">
<button
class="MuiButtonBase-root MuiIconButton-root"
tabindex="0"
type="button"
title="Previous month"
aria-label="Previous month"
>
<svg
class="MuiSvgIcon-root"
focusable="false"
aria-hidden="true"
viewBox="0 0 24 24"
data-testid="ArrowLeftIcon"
>
<path
d="M15.41 16.59L10.83 12l4.58-4.59L14 6l-6 6 6 6 1.41-1.41z"
></path>
</svg>
</button>
<span class="MuiTypography-root" id="_r_0_-grid-1-label"
>February 2019</span
>
<button
class="MuiButtonBase-root MuiIconButton-root"
tabindex="0"
type="button"
title="Next month"
aria-label="Next month"
>
<svg
class="MuiSvgIcon-root"
focusable="false"
aria-hidden="true"
viewBox="0 0 24 24"
data-testid="ArrowRightIcon"
>
<path
d="M8.59 16.59L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.41z"
></path>
</svg>
</button>
</div>
<div
role="grid"
aria-labelledby="_r_0_-grid-1-label"
class="MuiDayCalendar-root"
>
<div role="row" class="MuiDayCalendar-header">
<span
class="MuiTypography-root"
role="columnheader"
aria-label="Sunday"
>S</span
>
<span
class="MuiTypography-root"
role="columnheader"
aria-label="Monday"
>M</span
>
<span
class="MuiTypography-root"
role="columnheader"
aria-label="Tuesday"
>T</span
>
<span
class="MuiTypography-root"
role="columnheader"
aria-label="Wednesday"
>W</span
>
<span
class="MuiTypography-root"
role="columnheader"
aria-label="Thursday"
>T</span
>
<span
class="MuiTypography-root"
role="columnheader"
aria-label="Friday"
>F</span
>
<span
class="MuiTypography-root"
role="columnheader"
aria-label="Saturday"
>S</span
>
</div>
<div class="MuiPickersSlideTransition-root" role="presentation">
<div
data-testid="pickers-calendar"
role="rowgroup"
class="MuiDayCalendar-monthContainer"
>
<!-- February 2019 days abbreviated for brevity - same structure as January -->
<div
role="row"
class="MuiDayCalendar-weekContainer"
aria-rowindex="1"
>
<div
class="MuiDateRangePickerDay-root MuiDateRangePickerDay-outsideCurrentMonth MuiDateRangePickerDay-hiddenDayFiller"
>
<div class="MuiDateRangePickerDay-rangeIntervalPreview">
<div
class="MuiPickersDay-root MuiPickersDay-hiddenDaySpacingFiller"
role="gridcell"
></div>
</div>
</div>
<div
class="MuiDateRangePickerDay-root MuiDateRangePickerDay-startOfMonth MuiDateRangePickerDay-firstVisibleCell"
>
<div
class="MuiDateRangePickerDay-rangeIntervalPreview MuiDateRangePickerDay-rangeIntervalDayPreviewStart"
>
<button
class="MuiButtonBase-root MuiPickersDay-root MuiDateRangePickerDay-day"
tabindex="-1"
type="button"
data-testid="DateRangePickerDay"
role="gridcell"
data-timestamp="1548979200000"
aria-colindex="6"
aria-selected="false"
>
1
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>// compare.js
/**
* jsdom Performance Regression - getComputedStyle Isolation
* This test isolates the performance regression to window.getComputedStyle().
*/
import { readFile } from 'fs/promises';
async function testJsdomVersion(jsdomPackage, versionLabel) {
const html = await readFile('./jsdom-regression-repro.html', 'utf-8');
// Dynamically import the jsdom version
const { JSDOM } = await import(jsdomPackage);
// Initialize jsdom for testing
const dom = new JSDOM(html);
const document = dom.window.document;
const window = dom.window;
// Get all elements with roles for testing
const allRoleElements = document.querySelectorAll('[role]');
console.log(
` Found ${allRoleElements.length} elements with role attributes`
);
// Test: getComputedStyle performance
function testGetComputedStyle() {
const start = performance.now();
for (let i = 0; i < 100; i++) {
for (const element of allRoleElements) {
window.getComputedStyle(element);
}
}
return performance.now() - start;
}
// Warmup test runs
testGetComputedStyle();
testGetComputedStyle();
// Run test multiple times
const iterations = 10;
const timings = [];
for (let i = 0; i < iterations; i++) {
timings.push(testGetComputedStyle());
}
// Calculate average
const avgTime = timings.reduce((a, b) => a + b, 0) / iterations;
return {
versionLabel,
elementCount: allRoleElements.length,
avgTime,
timings,
};
}
// Run tests for both versions
console.log('jsdom Performance Regression - getComputedStyle');
console.log('='.repeat(80));
console.log(
'Test: Call window.getComputedStyle() on 65 elements, 100 times (6,500 calls)'
);
console.log('='.repeat(80));
console.log('');
console.log('Testing jsdom 26.0.0...');
const results26 = await testJsdomVersion('jsdom-26', 'jsdom 26.0.0');
console.log('Testing jsdom 27.1.0...');
const results27 = await testJsdomVersion('jsdom-27', 'jsdom 27.1.0');
console.log('');
console.log('='.repeat(80));
console.log('RESULTS');
console.log('='.repeat(80));
console.log('');
console.log(`${results26.versionLabel}:`);
console.log(` Average time: ${results26.avgTime.toFixed(3)}ms`);
console.log('');
console.log(`${results27.versionLabel}:`);
console.log(` Average time: ${results27.avgTime.toFixed(3)}ms`);
console.log('');
// Calculate regression
const regression =
((results27.avgTime - results26.avgTime) / results26.avgTime) * 100;
const multiplier = results27.avgTime / results26.avgTime;
console.log('='.repeat(80));
console.log('REGRESSION ANALYSIS');
console.log('='.repeat(80));
console.log('');
console.log(
` Difference: +${(results27.avgTime - results26.avgTime).toFixed(3)}ms`
);
console.log(` Regression: +${regression.toFixed(1)}%`);
console.log(` Multiplier: ${multiplier.toFixed(2)}x slower`);See the following StackBlitz
How does similar code behave in browsers?
Didn't notice any performance regressions in browsers recently
What is the problem?
At MUI we recently upgraded JSDOM from 26 to 27 and noticed the runtime of our tests doubled. The main culprit I could find was @testing-library/dom getByRole which got a 4x slowdown. I traced it down to dom-accessibility-api computeAccessibleName which further lead me to getComputedStyle in jsdom.
Output of the script on my local machine
jsdom Performance Regression - getComputedStyle
================================================================================
Test: Call window.getComputedStyle() on 65 elements, 100 times (6,500 calls)
================================================================================
Testing jsdom 26.0.0...
Found 65 elements with role attributes
Testing jsdom 27.1.0...
Found 65 elements with role attributes
================================================================================
RESULTS
================================================================================
jsdom 26.0.0:
Average time: 259.998ms
jsdom 27.1.0:
Average time: 1410.337ms
================================================================================
REGRESSION ANALYSIS
================================================================================
Difference: +1150.339ms
Regression: +442.4%
Multiplier: 5.42x slower
I think there will be more perf regressions, but this one so far seems to be the biggest one.
Potentially the same root cause as #3967