Merge pull request #6449 from atom/ns-update-again-in-frame

Perform DOM updates requested from DOM reads in the same frame, after we finish reading
This commit is contained in:
Nathan Sobo 2015-04-21 08:20:14 -06:00
commit e9e0857a5e
3 changed files with 40 additions and 3 deletions

View File

@ -2624,7 +2624,7 @@ describe "TextEditorComponent", ->
expect(componentNode.querySelector('.placeholder-text')).toBeNull()
describe "legacy editor compatibility", ->
it "triggers the screen-lines-changed event before the editor:display-update event", ->
it "triggers the screen-lines-changed event before the editor:display-updated event", ->
editor.setSoftWrapped(true)
callingOrder = []
@ -2633,7 +2633,7 @@ describe "TextEditorComponent", ->
editor.insertText("HELLO! HELLO!\n HELLO! HELLO! HELLO! HELLO! HELLO! HELLO! HELLO! HELLO! HELLO! HELLO! HELLO! HELLO! HELLO! HELLO! HELLO! HELLO! HELLO! HELLO! ")
nextAnimationFrame()
expect(callingOrder).toEqual ['screen-lines-changed', 'editor:display-updated']
expect(callingOrder).toEqual ['screen-lines-changed', 'editor:display-updated', 'editor:display-updated']
it "works with the ::setEditorHeightInLines and ::setEditorWidthInChars helpers", ->
setEditorHeightInLines(wrapperView, 7)

View File

@ -119,6 +119,36 @@ describe "ViewRegistry", ->
frameRequests[0]()
expect(events).toEqual ['write 4', 'read 3']
it "performs writes requested from read callbacks in the same animation frame", ->
spyOn(window, 'setInterval').andCallFake(fakeSetInterval)
spyOn(window, 'clearInterval').andCallFake(fakeClearInterval)
events = []
registry.pollDocument -> events.push('poll')
registry.pollAfterNextUpdate()
registry.updateDocument -> events.push('write 1')
registry.readDocument ->
registry.updateDocument -> events.push('write from read 1')
events.push('read 1')
registry.readDocument ->
registry.updateDocument -> events.push('write from read 2')
events.push('read 2')
registry.updateDocument -> events.push('write 2')
expect(frameRequests.length).toBe 1
frameRequests[0]()
expect(frameRequests.length).toBe 1
expect(events).toEqual [
'write 1'
'write 2'
'read 1'
'read 2'
'poll'
'write from read 1'
'write from read 2'
]
it "pauses DOM polling when reads or writes are pending", ->
spyOn(window, 'setInterval').andCallFake(fakeSetInterval)
spyOn(window, 'clearInterval').andCallFake(fakeClearInterval)

View File

@ -44,6 +44,7 @@ module.exports =
class ViewRegistry
documentPollingInterval: 200
documentUpdateRequested: false
documentReadInProgress: false
performDocumentPollAfterUpdate: false
pollIntervalHandle: null
@ -161,7 +162,7 @@ class ViewRegistry
updateDocument: (fn) ->
@documentWriters.push(fn)
@requestDocumentUpdate()
@requestDocumentUpdate() unless @documentReadInProgress
new Disposable =>
@documentWriters = @documentWriters.filter (writer) -> writer isnt fn
@ -196,9 +197,15 @@ class ViewRegistry
performDocumentUpdate: =>
@documentUpdateRequested = false
writer() while writer = @documentWriters.shift()
@documentReadInProgress = true
reader() while reader = @documentReaders.shift()
@performDocumentPoll() if @performDocumentPollAfterUpdate
@performDocumentPollAfterUpdate = false
@documentReadInProgress = false
# process updates requested as a result of reads
writer() while writer = @documentWriters.shift()
startPollingDocument: ->
@pollIntervalHandle = window.setInterval(@performDocumentPoll, @documentPollingInterval)