Skip to content

Commit 20ea98a

Browse files
author
Antonio Scandurra
committed
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.
1 parent 0d9dc47 commit 20ea98a

File tree

2 files changed

+30
-3
lines changed

2 files changed

+30
-3
lines changed

spec/text-editor-component-spec.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2388,6 +2388,31 @@ describe('TextEditorComponent', () => {
23882388
])
23892389
})
23902390

2391+
it('does not attempt to render block decorations located outside the visible range', async () => {
2392+
const {editor, component} = buildComponent({autoHeight: false, rowsPerTile: 2})
2393+
await setEditorHeightInLines(component, 2)
2394+
expect(component.getRenderedStartRow()).toBe(0)
2395+
expect(component.getRenderedEndRow()).toBe(4)
2396+
2397+
const marker1 = editor.markScreenRange([[3, 0], [5, 0]], {reversed: false})
2398+
const item1 = document.createElement('div')
2399+
editor.decorateMarker(marker1, {type: 'block', item: item1})
2400+
2401+
const marker2 = editor.markScreenRange([[3, 0], [5, 0]], {reversed: true})
2402+
const item2 = document.createElement('div')
2403+
editor.decorateMarker(marker2, {type: 'block', item: item2})
2404+
2405+
await component.getNextUpdatePromise()
2406+
expect(item1.parentElement).toBeNull()
2407+
expect(item2.nextSibling).toBe(lineNodeForScreenRow(component, 3))
2408+
2409+
await setScrollTop(component, 4 * component.getLineHeight())
2410+
expect(component.getRenderedStartRow()).toBe(4)
2411+
expect(component.getRenderedEndRow()).toBe(8)
2412+
expect(item1.nextSibling).toBe(lineNodeForScreenRow(component, 5))
2413+
expect(item2.parentElement).toBeNull()
2414+
})
2415+
23912416
it('measures block decorations correctly when they are added before the component width has been updated', async () => {
23922417
{
23932418
const {editor, component, element} = buildComponent({autoHeight: false, width: 500, attach: false})

src/text-editor-component.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1153,9 +1153,11 @@ class TextEditorComponent {
11531153
}
11541154

11551155
addBlockDecorationToRender (decoration, screenRange, reversed) {
1156-
const screenPosition = reversed ? screenRange.start : screenRange.end
1157-
const tileStartRow = this.tileStartRowForRow(screenPosition.row)
1158-
const screenLine = this.renderedScreenLines[screenPosition.row - this.getRenderedStartRow()]
1156+
const {row} = reversed ? screenRange.start : screenRange.end
1157+
if (row < this.getRenderedStartRow() || row >= this.getRenderedEndRow()) return
1158+
1159+
const tileStartRow = this.tileStartRowForRow(row)
1160+
const screenLine = this.renderedScreenLines[row - this.getRenderedStartRow()]
11591161

11601162
let decorationsByScreenLine = this.decorationsToRender.blocks.get(tileStartRow)
11611163
if (!decorationsByScreenLine) {

0 commit comments

Comments
 (0)