mirror of
https://github.com/atom/atom.git
synced 2026-04-06 03:02:13 -04:00
Fix race condition between opening new files and restoring window state
This commit fixes a race condition in the `attemptRestoreProjectStateForPaths` function that could cause a file to be opened more than once within the same workspace pane. In particular, when opening some file into an empty window, Atom tries to recover the state for the project containing the file (if there is one). However, we were previously not waiting until the `AtomEnvironment`'s state had been fully deserialized before trying to load the requested file into the workspace. If the same file also existed in the serialized representation of the workspace, it could end up being opened twice. With this commit we will now wait until the environment has been fully deserialized before honoring the user's request of loading new files into an empty window. Also, tests have been restructured to test more thoroughly this interaction.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
const {it, fit, ffit, beforeEach, afterEach, conditionPromise} = require('./async-spec-helpers')
|
||||
const _ = require('underscore-plus')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const temp = require('temp').track()
|
||||
const AtomEnvironment = require('../src/atom-environment')
|
||||
@@ -471,15 +472,28 @@ describe('AtomEnvironment', () => {
|
||||
await atom.workspace.open()
|
||||
})
|
||||
|
||||
it('automatically restores the saved state into the current environment', () => {
|
||||
const state = {}
|
||||
spyOn(atom.workspace, 'open')
|
||||
spyOn(atom, 'restoreStateIntoThisEnvironment')
|
||||
it('automatically restores the saved state into the current environment', async () => {
|
||||
const projectPath = temp.mkdirSync()
|
||||
const filePath1 = path.join(projectPath, 'file-1')
|
||||
const filePath2 = path.join(projectPath, 'file-2')
|
||||
const filePath3 = path.join(projectPath, 'file-3')
|
||||
fs.writeFileSync(filePath1, 'abc')
|
||||
fs.writeFileSync(filePath2, 'def')
|
||||
fs.writeFileSync(filePath3, 'ghi')
|
||||
|
||||
atom.attemptRestoreProjectStateForPaths(state, [__dirname], [__filename])
|
||||
expect(atom.restoreStateIntoThisEnvironment).toHaveBeenCalledWith(state)
|
||||
expect(atom.workspace.open.callCount).toBe(1)
|
||||
expect(atom.workspace.open).toHaveBeenCalledWith(__filename)
|
||||
const env1 = new AtomEnvironment({applicationDelegate: atom.applicationDelegate})
|
||||
env1.project.setPaths([projectPath])
|
||||
await env1.workspace.open(filePath1)
|
||||
await env1.workspace.open(filePath2)
|
||||
await env1.workspace.open(filePath3)
|
||||
const env1State = env1.serialize()
|
||||
env1.destroy()
|
||||
|
||||
const env2 = new AtomEnvironment({applicationDelegate: atom.applicationDelegate})
|
||||
await env2.attemptRestoreProjectStateForPaths(env1State, [projectPath], [filePath2])
|
||||
const restoredURIs = env2.workspace.getPaneItems().map(p => p.getURI())
|
||||
expect(restoredURIs).toEqual([filePath1, filePath2, filePath3])
|
||||
env2.destroy()
|
||||
})
|
||||
|
||||
describe('when a dock has a non-text editor', () => {
|
||||
|
||||
@@ -1121,7 +1121,7 @@ class AtomEnvironment {
|
||||
}
|
||||
|
||||
if (windowIsUnused()) {
|
||||
this.restoreStateIntoThisEnvironment(state)
|
||||
await this.restoreStateIntoThisEnvironment(state)
|
||||
return Promise.all(filesToOpen.map(file => this.workspace.open(file)))
|
||||
} else {
|
||||
let resolveDiscardStatePromise = null
|
||||
|
||||
Reference in New Issue
Block a user