diff --git a/package.json b/package.json index 5f1cd3735..d50f77eb7 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,7 @@ "autoflow": "0.27.0", "autosave": "0.23.1", "background-tips": "0.26.0", - "bookmarks": "0.39.0", + "bookmarks": "0.41.0", "bracket-matcher": "0.82.0", "command-palette": "0.38.0", "deprecation-cop": "0.54.1", diff --git a/spec/atom-environment-spec.coffee b/spec/atom-environment-spec.coffee index 846083b0e..39c22a33d 100644 --- a/spec/atom-environment-spec.coffee +++ b/spec/atom-environment-spec.coffee @@ -208,12 +208,15 @@ describe "AtomEnvironment", -> waitsForPromise -> atom.loadState().then (state) -> expect(state).toEqual(serializedState) - it "saves state on keydown, mousedown, and when the editor window unloads", -> + it "saves state when the CPU is idle after a keydown or mousedown event", -> spyOn(atom, 'saveState') + idleCallbacks = [] + spyOn(window, 'requestIdleCallback').andCallFake (callback) -> idleCallbacks.push(callback) keydown = new KeyboardEvent('keydown') atom.document.dispatchEvent(keydown) advanceClock atom.saveStateDebounceInterval + idleCallbacks.shift()() expect(atom.saveState).toHaveBeenCalledWith({isUnloading: false}) expect(atom.saveState).not.toHaveBeenCalledWith({isUnloading: true}) @@ -221,17 +224,33 @@ describe "AtomEnvironment", -> mousedown = new MouseEvent('mousedown') atom.document.dispatchEvent(mousedown) advanceClock atom.saveStateDebounceInterval + idleCallbacks.shift()() expect(atom.saveState).toHaveBeenCalledWith({isUnloading: false}) expect(atom.saveState).not.toHaveBeenCalledWith({isUnloading: true}) - atom.saveState.reset() + it "saves state immediately when unloading the editor window, ignoring pending and successive mousedown/keydown events", -> + spyOn(atom, 'saveState') + idleCallbacks = [] + spyOn(window, 'requestIdleCallback').andCallFake (callback) -> idleCallbacks.push(callback) + + mousedown = new MouseEvent('mousedown') + atom.document.dispatchEvent(mousedown) atom.unloadEditorWindow() - mousedown = new MouseEvent('mousedown') - atom.document.dispatchEvent(mousedown) - advanceClock atom.saveStateDebounceInterval expect(atom.saveState).toHaveBeenCalledWith({isUnloading: true}) expect(atom.saveState).not.toHaveBeenCalledWith({isUnloading: false}) + atom.saveState.reset() + advanceClock atom.saveStateDebounceInterval + idleCallbacks.shift()() + expect(atom.saveState).not.toHaveBeenCalled() + + atom.saveState.reset() + mousedown = new MouseEvent('mousedown') + atom.document.dispatchEvent(mousedown) + advanceClock atom.saveStateDebounceInterval + idleCallbacks.shift()() + expect(atom.saveState).not.toHaveBeenCalled() + it "serializes the project state with all the options supplied in saveState", -> spyOn(atom.project, 'serialize').andReturn({foo: 42}) @@ -367,7 +386,7 @@ describe "AtomEnvironment", -> updateAvailableHandler = jasmine.createSpy("update-available-handler") subscription = atom.onUpdateAvailable updateAvailableHandler - autoUpdater = require('remote').require('auto-updater') + autoUpdater = require('electron').remote.require('auto-updater') autoUpdater.emit 'update-downloaded', null, "notes", "version" waitsFor -> diff --git a/spec/module-cache-spec.coffee b/spec/module-cache-spec.coffee index 3a995aec7..4c0a549aa 100644 --- a/spec/module-cache-spec.coffee +++ b/spec/module-cache-spec.coffee @@ -8,13 +8,13 @@ describe 'ModuleCache', -> beforeEach -> spyOn(Module, '_findPath').andCallThrough() - it 'resolves atom shell module paths without hitting the filesystem', -> + it 'resolves Electron module paths without hitting the filesystem', -> builtins = ModuleCache.cache.builtins expect(Object.keys(builtins).length).toBeGreaterThan 0 for builtinName, builtinPath of builtins expect(require.resolve(builtinName)).toBe builtinPath - expect(fs.isFileSync(require.resolve(builtinName))) + expect(fs.isFileSync(require.resolve(builtinName))).toBeTruthy() expect(Module._findPath.callCount).toBe 0 diff --git a/spec/window-event-handler-spec.coffee b/spec/window-event-handler-spec.coffee index bb7e1665b..22f43c90f 100644 --- a/spec/window-event-handler-spec.coffee +++ b/spec/window-event-handler-spec.coffee @@ -75,7 +75,7 @@ describe "WindowEventHandler", -> describe "when a link is clicked", -> it "opens the http/https links in an external application", -> - shell = require 'shell' + {shell} = require 'electron' spyOn(shell, 'openExternal') link = document.createElement('a') diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index f50ae9d5b..da3e989f2 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -234,13 +234,14 @@ class AtomEnvironment extends Model checkPortableHomeWritable() attachSaveStateListeners: -> - saveState = => @saveState({isUnloading: false}) unless @unloaded - debouncedSaveState = _.debounce(saveState, @saveStateDebounceInterval) - @document.addEventListener('mousedown', debouncedSaveState, true) - @document.addEventListener('keydown', debouncedSaveState, true) + saveState = _.debounce((=> + window.requestIdleCallback => @saveState({isUnloading: false}) unless @unloaded + ), @saveStateDebounceInterval) + @document.addEventListener('mousedown', saveState, true) + @document.addEventListener('keydown', saveState, true) @disposables.add new Disposable => - @document.removeEventListener('mousedown', debouncedSaveState, true) - @document.removeEventListener('keydown', debouncedSaveState, true) + @document.removeEventListener('mousedown', saveState, true) + @document.removeEventListener('keydown', saveState, true) setConfigSchema: -> @config.setSchema null, {type: 'object', properties: _.clone(require('./config-schema'))} @@ -655,6 +656,7 @@ class AtomEnvironment extends Model # Call this method when establishing a real application window. startEditorWindow: -> + @unloaded = false @loadState().then (state) => @windowDimensions = state?.windowDimensions @displayWindow().then => @@ -842,16 +844,15 @@ class AtomEnvironment extends Model return Promise.resolve() unless @enablePersistence new Promise (resolve, reject) => - window.requestIdleCallback => - return if not @project + return if not @project - state = @serialize(options) - savePromise = - if storageKey = @getStateKey(@project?.getPaths()) - @stateStore.save(storageKey, state) - else - @applicationDelegate.setTemporaryWindowState(state) - savePromise.catch(reject).then(resolve) + state = @serialize(options) + savePromise = + if storageKey = @getStateKey(@project?.getPaths()) + @stateStore.save(storageKey, state) + else + @applicationDelegate.setTemporaryWindowState(state) + savePromise.catch(reject).then(resolve) loadState: -> if @enablePersistence diff --git a/src/module-cache.coffee b/src/module-cache.coffee index a2840a864..9a2961bf6 100644 --- a/src/module-cache.coffee +++ b/src/module-cache.coffee @@ -202,13 +202,13 @@ registerBuiltins = (devMode) -> atomShellRoot = path.join(process.resourcesPath, 'atom.asar') - commonRoot = path.join(atomShellRoot, 'common', 'api', 'lib') - commonBuiltins = ['callbacks-registry', 'clipboard', 'crash-reporter', 'screen', 'shell'] + commonRoot = path.join(atomShellRoot, 'common', 'api') + commonBuiltins = ['callbacks-registry', 'clipboard', 'crash-reporter', 'shell'] for builtin in commonBuiltins cache.builtins[builtin] = path.join(commonRoot, "#{builtin}.js") - rendererRoot = path.join(atomShellRoot, 'renderer', 'api', 'lib') - rendererBuiltins = ['ipc-renderer', 'remote'] + rendererRoot = path.join(atomShellRoot, 'renderer', 'api') + rendererBuiltins = ['ipc-renderer', 'remote', 'screen'] for builtin in rendererBuiltins cache.builtins[builtin] = path.join(rendererRoot, "#{builtin}.js")