Ensure there is clean serialization of RootView state

Everything from RootView to Pane needs to return a serialized clone of
its state, so we don't accidentally further mutate the serialized state
in tests.
This commit is contained in:
Nathan Sobo
2013-07-20 22:40:40 -06:00
parent 5246d4cd72
commit 383985d331
7 changed files with 57 additions and 41 deletions

View File

@@ -15,7 +15,7 @@ class PaneAxis extends View
@state = args[0]
@state.get('children').each (child, index) => @addChild(deserialize(child), index, updateState: false)
else
@state = telepath.Document.create(deserializer: @className(), children: [])
@state = telepath.create(deserializer: @className(), children: [])
@addChild(child) for child in args
@state.get('children').on 'changed', ({index, inserted, removed, site}) =>
@@ -27,7 +27,7 @@ class PaneAxis extends View
addChild: (child, index=@children().length, options={}) ->
@insertAt(index, child)
@state.get('children').insert(index, child.serialize()) if options.updateState ? true
@state.get('children').insert(index, child.getState()) if options.updateState ? true
@getContainer()?.adjustPaneDimensions()
removeChild: (child, options={}) ->
@@ -83,8 +83,9 @@ class PaneAxis extends View
children.insert(childIndex + 1, newChild.getState())
serialize: ->
child.serialize() for child in @children().views()
@state
state = @state.clone()
state.set('children', child.serialize() for child in @children().views())
state
getState: -> @state

View File

@@ -18,22 +18,24 @@ class PaneContainer extends View
@content: ->
@div id: 'panes'
initialize: (@state) ->
if @state?
@setRoot(deserialize(@state.get('root')), updateState: false)
initialize: (state) ->
if state instanceof telepath.Document
@state = state
@setRoot(deserialize(@state.get('root')))
else
@state = telepath.Document.create(deserializer: 'PaneContainer')
@state = telepath.create(deserializer: 'PaneContainer')
@state.on 'changed', ({key, newValue, site}) =>
return if site is @state.site.id
if key is 'root'
@setRoot(deserialize(newValue), updateState: false)
@setRoot(deserialize(newValue))
@destroyedItemStates = []
serialize: ->
@getRoot()?.serialize()
@state
state = @state.clone()
state.set('root', @getRoot()?.serialize())
state
getState: -> @state
@@ -92,7 +94,7 @@ class PaneContainer extends View
setRoot: (root, options={}) ->
@empty()
@append(root) if root?
@state.set(root: root?.getState()) if options.updateState ? true
@state.set(root: root?.getState())
removeChild: (child) ->
throw new Error("Removing non-existant child") unless @getRoot() is child

View File

@@ -33,7 +33,7 @@ class Pane extends View
@items = args
@state = telepath.Document.create
deserializer: 'Pane'
items: @items.map (item) -> item.getState?() ? item.serialize()
items: @items.map (item) -> item.getState()
@state.get('items').on 'changed', ({index, removed, inserted, site}) =>
return if site is @state.site.id
@@ -315,9 +315,10 @@ class Pane extends View
@viewForItem(@activeItem)
serialize: ->
@state.get('items').set(index, item.serialize()) for item, index in @items
@state.set focused: @is(':has(:focus)')
@state
state = @state.clone()
state.set('items', item.serialize() for item, index in @items)
state.set('focused', @is(':has(:focus)'))
state
getState: -> @state
@@ -374,7 +375,7 @@ class Pane extends View
@closest('#panes').view()
copyActiveItem: ->
deserialize(@activeItem.serialize())
@activeItem.copy?() ? deserialize(@activeItem.serialize())
remove: (selector, keepData) ->
return super if keepData

View File

@@ -71,7 +71,11 @@ class Project
for insertedBuffer, i in inserted
@addBufferAtIndex(deserialize(insertedBuffer), index + i, updateState: false)
serialize: -> @state.clone()
serialize: ->
state = @state.clone()
state.set('buffers', buffer.serialize() for buffer in @getBuffers())
state
getState: -> @state
# Retrieves the project path.

View File

@@ -32,7 +32,7 @@ class RootView extends View
@div id: 'root-view', =>
@div id: 'horizontal', outlet: 'horizontal', =>
@div id: 'vertical', outlet: 'vertical', =>
@subview 'panes', deserialize(state?.get?('panes')) ? new PaneContainer
@div outlet: 'panes'
@deserialize: (state) ->
new RootView(state)
@@ -40,8 +40,16 @@ class RootView extends View
initialize: (state={}) ->
if state instanceof telepath.Document
@state = state
panes = deserialize(state.get('panes'))
else
@state = telepath.Document.create(_.extend({version: RootView.version, deserializer: 'RootView', panes: @panes.serialize()}, state))
panes = new PaneContainer
@state = telepath.create
deserializer: @constructor.name
version: @constructor.version
panes: panes.getState()
@panes.replaceWith(panes)
@panes = panes
@on 'focus', (e) => @handleFocus(e)
@subscribe $(window), 'focus', (e) =>
@@ -83,9 +91,12 @@ class RootView extends View
_.nextTick => atom.setFullScreen(@state.get('fullScreen'))
serialize: ->
@panes.serialize()
@state.set('fullScreen', atom.isFullScreen())
@state
state = @state.clone()
state.set('panes', @panes.serialize())
state.set('fullScreen', atom.isFullScreen())
state
getState: -> @state
handleFocus: (e) ->
if @getActivePane()

View File

@@ -90,9 +90,7 @@ class TextBuffer
this
serialize: ->
state = @state.clone()
state.remove('text') unless @isModified()
state
@state.clone()
getState: -> @state