Skip to content

Commit

Permalink
fix(commons/dom/createGrid): only add the visible, non-overflow areas…
Browse files Browse the repository at this point in the history
… of an element to the grid (#4101)

* fix(commons/dom/createGrid): only add the visible, non-overflow areas of an element to the grid

* integration test

* Update test/integration/full/contrast/memory.html

Co-authored-by: Wilco Fiers <WilcoFiers@users.noreply.github.com>

---------

Co-authored-by: Wilco Fiers <WilcoFiers@users.noreply.github.com>
  • Loading branch information
straker and WilcoFiers committed Jul 28, 2023
1 parent 9634282 commit d77f47b
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 2 deletions.
17 changes: 15 additions & 2 deletions lib/commons/dom/create-grid.js
Expand Up @@ -6,6 +6,8 @@ import { getNodeFromTree, getScroll, isShadowRoot } from '../../core/utils';
import constants from '../../core/constants';
import cache from '../../core/base/cache';
import assert from '../../core/utils/assert';
import getOverflowHiddenAncestors from './get-overflow-hidden-ancestors';
import { getIntersectionRect } from '../math';

const ROOT_LEVEL = 0;
const DEFAULT_LEVEL = 0.1;
Expand Down Expand Up @@ -392,11 +394,22 @@ function findScrollRegionParent(vNode, parentVNode) {
* @param {VirtualNode}
*/
function addNodeToGrid(grid, vNode) {
vNode.clientRects.forEach(rect => {
const overflowHiddenNodes = getOverflowHiddenAncestors(vNode);

vNode.clientRects.forEach(clientRect => {
// ignore any rects that are outside the bounds of overflow hidden ancestors
const visibleRect = overflowHiddenNodes.reduce((rect, overflowNode) => {
return rect && getIntersectionRect(rect, overflowNode.boundingClientRect);
}, clientRect);

if (!visibleRect) {
return;
}

// save a reference to where this element is in the grid so we
// can find it even if it's in a subgrid
vNode._grid ??= grid;
const gridRect = grid.getGridPositionOfRect(rect);
const gridRect = grid.getGridPositionOfRect(visibleRect);
grid.loopGridPosition(gridRect, gridCell => {
if (!gridCell.includes(vNode)) {
gridCell.push(vNode);
Expand Down
18 changes: 18 additions & 0 deletions test/commons/dom/create-grid.js
Expand Up @@ -55,6 +55,24 @@ describe('create-grid', () => {
]);
});

it('only adds the visible non-overflow area of large elements', () => {
const vNode = queryFixture(`
<div style="overflow: hidden; width: 300px; height: 300px;">
<span id="target" style="display: inline-block; width: 1000px; height: 1000px;">' +
'Hello world</span>
</div>
`);
createGrid();

const positions = findPositions(vNode._grid, vNode);
assert.deepEqual(positions, [
{ col: 0, row: 0 },
{ col: 1, row: 0 },
{ col: 0, row: 1 },
{ col: 1, row: 1 }
]);
});

describe('stackingOrder', () => {
it('adds stacking context information', () => {
fixture = fixtureSetup('<span>Hello world</span>');
Expand Down
45 changes: 45 additions & 0 deletions test/integration/full/contrast/memory.html
@@ -0,0 +1,45 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Test Page</title>
<link
rel="stylesheet"
type="text/css"
href="/node_modules/mocha/mocha.css"
/>
<script src="/node_modules/mocha/mocha.js"></script>
<script src="/node_modules/chai/chai.js"></script>
<script src="/axe.js"></script>
<script>
mocha.setup({
timeout: 2000,
ui: 'bdd'
});
var assert = chai.assert;
</script>
<script src="/test/integration/no-ui-reporter.js"></script>
<style>
* {
box-sizing: border-box;
}
html,
body {
padding: 0;
margin: 0;
height: 100%;
background: #fff;
color: #000;
}
</style>
</head>
<body>
<div id="fixture">
<div style="overflow: hidden; width: 200px; height: 200px">
<!-- browsers each have their own CSS size limit so this number (which should be greater than the limit) will be capped to that -->
<div style="width: 1e9px; height: 1e9px">Hello World</div>
</div>
</div>
<script src="memory.js"></script>
<script src="/test/integration/adapter.js"></script>
</body>
</html>
18 changes: 18 additions & 0 deletions test/integration/full/contrast/memory.js
@@ -0,0 +1,18 @@
/*
Since we can't easily test for memory issue we'll assume that if this test doesn't time out then the memory issue isn't a problem
*/
describe('color-contrast memory test', () => {
describe('violations', () => {
it('should find none', done => {
axe.run(
'#fixture',
{ runOnly: { type: 'rule', values: ['color-contrast'] } },
(err, results) => {
assert.isNull(err);
assert.lengthOf(results.violations, 0);
done();
}
);
});
});
});

0 comments on commit d77f47b

Please sign in to comment.