mirror of
https://github.com/atom/atom.git
synced 2026-01-25 06:48:28 -05:00
Don't render block decorations located outside the visible range
Previously, when trying to use block decorations on non-empty markers, Atom could sometimes throw an error if such markers ended or started at a position that was not currently rendered. In fact, even if we already restricted the decoration query to markers that intersected the visible row range, markers that were only partially visible would still be considered for rendering. If, depending on the `reversed` property, we decided to render the tail or head of the marker in question and this was outside the viewport, Atom would throw the aforementioned exception. This commit addresses the above issue by explicitly ignoring block decorations that are located on rows that are not yet rendered.
This commit is contained in:
@@ -2388,6 +2388,31 @@ describe('TextEditorComponent', () => {
|
||||
])
|
||||
})
|
||||
|
||||
it('does not attempt to render block decorations located outside the visible range', async () => {
|
||||
const {editor, component} = buildComponent({autoHeight: false, rowsPerTile: 2})
|
||||
await setEditorHeightInLines(component, 2)
|
||||
expect(component.getRenderedStartRow()).toBe(0)
|
||||
expect(component.getRenderedEndRow()).toBe(4)
|
||||
|
||||
const marker1 = editor.markScreenRange([[3, 0], [5, 0]], {reversed: false})
|
||||
const item1 = document.createElement('div')
|
||||
editor.decorateMarker(marker1, {type: 'block', item: item1})
|
||||
|
||||
const marker2 = editor.markScreenRange([[3, 0], [5, 0]], {reversed: true})
|
||||
const item2 = document.createElement('div')
|
||||
editor.decorateMarker(marker2, {type: 'block', item: item2})
|
||||
|
||||
await component.getNextUpdatePromise()
|
||||
expect(item1.parentElement).toBeNull()
|
||||
expect(item2.nextSibling).toBe(lineNodeForScreenRow(component, 3))
|
||||
|
||||
await setScrollTop(component, 4 * component.getLineHeight())
|
||||
expect(component.getRenderedStartRow()).toBe(4)
|
||||
expect(component.getRenderedEndRow()).toBe(8)
|
||||
expect(item1.nextSibling).toBe(lineNodeForScreenRow(component, 5))
|
||||
expect(item2.parentElement).toBeNull()
|
||||
})
|
||||
|
||||
it('measures block decorations correctly when they are added before the component width has been updated', async () => {
|
||||
{
|
||||
const {editor, component, element} = buildComponent({autoHeight: false, width: 500, attach: false})
|
||||
|
||||
@@ -1153,9 +1153,11 @@ class TextEditorComponent {
|
||||
}
|
||||
|
||||
addBlockDecorationToRender (decoration, screenRange, reversed) {
|
||||
const screenPosition = reversed ? screenRange.start : screenRange.end
|
||||
const tileStartRow = this.tileStartRowForRow(screenPosition.row)
|
||||
const screenLine = this.renderedScreenLines[screenPosition.row - this.getRenderedStartRow()]
|
||||
const {row} = reversed ? screenRange.start : screenRange.end
|
||||
if (row < this.getRenderedStartRow() || row >= this.getRenderedEndRow()) return
|
||||
|
||||
const tileStartRow = this.tileStartRowForRow(row)
|
||||
const screenLine = this.renderedScreenLines[row - this.getRenderedStartRow()]
|
||||
|
||||
let decorationsByScreenLine = this.decorationsToRender.blocks.get(tileStartRow)
|
||||
if (!decorationsByScreenLine) {
|
||||
|
||||
Reference in New Issue
Block a user