Merge pull request #12394 from atom/ns-as-switch-offset-test-to-mocha

Replace ChromeDriver integration tests main process Mocha tests
This commit is contained in:
Nathan Sobo
2016-08-12 14:17:16 -06:00
committed by GitHub
17 changed files with 775 additions and 597 deletions

View File

@@ -1,6 +1,16 @@
var ipcRenderer = null
var ipcMain = null
var BrowserWindow = null
'use strict'
const Disposable = require('event-kit').Disposable
let ipcRenderer = null
let ipcMain = null
let BrowserWindow = null
exports.on = function (emitter, eventName, callback) {
emitter.on(eventName, callback)
return new Disposable(function () {
emitter.removeListener(eventName, callback)
})
}
exports.call = function (methodName, ...args) {
if (!ipcRenderer) {
@@ -28,7 +38,7 @@ exports.respondTo = function (methodName, callback) {
var responseChannel = getResponseChannel(methodName)
ipcMain.on(methodName, function (event, ...args) {
return exports.on(ipcMain, methodName, function (event, ...args) {
var browserWindow = BrowserWindow.fromWebContents(event.sender)
var result = callback(browserWindow, ...args)
event.sender.send(responseChannel, result)

View File

@@ -7,6 +7,7 @@ Config = require '../config'
FileRecoveryService = require './file-recovery-service'
ipcHelpers = require '../ipc-helpers'
{BrowserWindow, Menu, app, dialog, ipcMain, shell} = require 'electron'
{CompositeDisposable} = require 'event-kit'
fs = require 'fs-plus'
path = require 'path'
os = require 'os'
@@ -36,14 +37,12 @@ class AtomApplication
else
options.socketPath = path.join(os.tmpdir(), "atom-#{options.version}-#{process.env.USER}.sock")
createAtomApplication = -> new AtomApplication(options)
# FIXME: Sometimes when socketPath doesn't exist, net.connect would strangely
# take a few seconds to trigger 'error' event, it could be a bug of node
# or atom-shell, before it's fixed we check the existence of socketPath to
# speedup startup.
if (process.platform isnt 'win32' and not fs.existsSync options.socketPath) or options.test
createAtomApplication()
new AtomApplication(options).initialize(options)
return
client = net.connect {path: options.socketPath}, ->
@@ -51,7 +50,7 @@ class AtomApplication
client.end()
app.quit()
client.on 'error', createAtomApplication
client.on 'error', -> new AtomApplication(options).initialize(options)
windows: null
applicationMenu: null
@@ -64,32 +63,46 @@ class AtomApplication
constructor: (options) ->
{@resourcePath, @devResourcePath, @version, @devMode, @safeMode, @socketPath, timeout, clearWindowState} = options
@socketPath = null if options.test
global.atomApplication = this
@pidsToOpenWindows = {}
@windows = []
@config = new Config({configDirPath: process.env.ATOM_HOME, @resourcePath, enablePersistence: true})
@config.setSchema null, {type: 'object', properties: _.clone(require('../config-schema'))}
@config.load()
@fileRecoveryService = new FileRecoveryService(path.join(process.env.ATOM_HOME, "recovery"))
@storageFolder = new StorageFolder(process.env.ATOM_HOME)
@disposable = new CompositeDisposable
@handleEvents()
# This stuff was previously done in the constructor, but we want to be able to construct this object
# for testing purposes without booting up the world. As you add tests, feel free to move instantiation
# of these various sub-objects into the constructor, but you'll need to remove the side-effects they
# perform during their construction, adding an initialize method that you call here.
initialize: (options) ->
global.atomApplication = this
@config.onDidChange 'core.useCustomTitleBar', @promptForRelaunch
@autoUpdateManager = new AutoUpdateManager(@version, options.test, @resourcePath, @config)
@applicationMenu = new ApplicationMenu(@version, @autoUpdateManager)
@atomProtocolHandler = new AtomProtocolHandler(@resourcePath, @safeMode)
@fileRecoveryService = new FileRecoveryService(path.join(process.env.ATOM_HOME, "recovery"))
@listenForArgumentsFromNewProcess()
@setupJavaScriptArguments()
@handleEvents()
@setupDockMenu()
@storageFolder = new StorageFolder(process.env.ATOM_HOME)
@launch(options)
destroy: ->
@disposable.dispose()
windowsClosePromises = @windows.map (window) ->
window.close()
window.closedPromise
Promise.all(windowsClosePromises)
launch: (options) ->
if options.pathsToOpen?.length > 0 or options.urlsToOpen?.length > 0 or options.test
@openWithOptions(options)
else
@@ -121,7 +134,7 @@ class AtomApplication
@windows.push window
@applicationMenu?.addWindow(window.browserWindow)
window.once 'window:loaded', =>
@autoUpdateManager.emitUpdateAvailableEvent(window)
@autoUpdateManager?.emitUpdateAvailableEvent(window)
unless window.isSpec
focusHandler = => @lastFocusedWindow = window
@@ -218,27 +231,27 @@ class AtomApplication
@openPathOnEvent('application:open-your-stylesheet', 'atom://.atom/stylesheet')
@openPathOnEvent('application:open-license', path.join(process.resourcesPath, 'LICENSE.md'))
app.on 'before-quit', =>
@disposable.add ipcHelpers.on app, 'before-quit', =>
@quitting = true
app.on 'will-quit', =>
@disposable.add ipcHelpers.on app, 'will-quit', =>
@killAllProcesses()
@deleteSocketFile()
app.on 'open-file', (event, pathToOpen) =>
@disposable.add ipcHelpers.on app, 'open-file', (event, pathToOpen) =>
event.preventDefault()
@openPath({pathToOpen})
app.on 'open-url', (event, urlToOpen) =>
@disposable.add ipcHelpers.on app, 'open-url', (event, urlToOpen) =>
event.preventDefault()
@openUrl({urlToOpen, @devMode, @safeMode})
app.on 'activate-with-no-open-windows', (event) =>
@disposable.add ipcHelpers.on app, 'activate-with-no-open-windows', (event) =>
event?.preventDefault()
@emit('application:new-window')
# A request from the associated render process to open a new render process.
ipcMain.on 'open', (event, options) =>
@disposable.add ipcHelpers.on ipcMain, 'open', (event, options) =>
window = @windowForEvent(event)
if options?
if typeof options.pathsToOpen is 'string'
@@ -247,21 +260,21 @@ class AtomApplication
options.window = window
@openPaths(options)
else
new AtomWindow(@fileRecoveryService, options)
new AtomWindow(this, @fileRecoveryService, options)
else
@promptForPathToOpen('all', {window})
ipcMain.on 'update-application-menu', (event, template, keystrokesByCommand) =>
@disposable.add ipcHelpers.on ipcMain, 'update-application-menu', (event, template, keystrokesByCommand) =>
win = BrowserWindow.fromWebContents(event.sender)
@applicationMenu.update(win, template, keystrokesByCommand)
@applicationMenu?.update(win, template, keystrokesByCommand)
ipcMain.on 'run-package-specs', (event, packageSpecPath) =>
@disposable.add ipcHelpers.on ipcMain, 'run-package-specs', (event, packageSpecPath) =>
@runTests({resourcePath: @devResourcePath, pathsToOpen: [packageSpecPath], headless: false})
ipcMain.on 'command', (event, command) =>
@disposable.add ipcHelpers.on ipcMain, 'command', (event, command) =>
@emit(command)
ipcMain.on 'open-command', (event, command, args...) =>
@disposable.add ipcHelpers.on ipcMain, 'open-command', (event, command, args...) =>
defaultPath = args[0] if args.length > 0
switch command
when 'application:open' then @promptForPathToOpen('all', getLoadSettings(), defaultPath)
@@ -269,72 +282,72 @@ class AtomApplication
when 'application:open-folder' then @promptForPathToOpen('folder', getLoadSettings(), defaultPath)
else console.log "Invalid open-command received: " + command
ipcMain.on 'window-command', (event, command, args...) ->
@disposable.add ipcHelpers.on ipcMain, 'window-command', (event, command, args...) ->
win = BrowserWindow.fromWebContents(event.sender)
win.emit(command, args...)
ipcMain.on 'call-window-method', (event, method, args...) ->
@disposable.add ipcHelpers.on ipcMain, 'call-window-method', (event, method, args...) ->
win = BrowserWindow.fromWebContents(event.sender)
win[method](args...)
ipcMain.on 'pick-folder', (event, responseChannel) =>
@disposable.add ipcHelpers.on ipcMain, 'pick-folder', (event, responseChannel) =>
@promptForPath "folder", (selectedPaths) ->
event.sender.send(responseChannel, selectedPaths)
ipcHelpers.respondTo 'set-window-size', (win, width, height) ->
@disposable.add ipcHelpers.respondTo 'set-window-size', (win, width, height) ->
win.setSize(width, height)
ipcHelpers.respondTo 'set-window-position', (win, x, y) ->
@disposable.add ipcHelpers.respondTo 'set-window-position', (win, x, y) ->
win.setPosition(x, y)
ipcHelpers.respondTo 'center-window', (win) ->
@disposable.add ipcHelpers.respondTo 'center-window', (win) ->
win.center()
ipcHelpers.respondTo 'focus-window', (win) ->
@disposable.add ipcHelpers.respondTo 'focus-window', (win) ->
win.focus()
ipcHelpers.respondTo 'show-window', (win) ->
@disposable.add ipcHelpers.respondTo 'show-window', (win) ->
win.show()
ipcHelpers.respondTo 'hide-window', (win) ->
@disposable.add ipcHelpers.respondTo 'hide-window', (win) ->
win.hide()
ipcHelpers.respondTo 'get-temporary-window-state', (win) ->
@disposable.add ipcHelpers.respondTo 'get-temporary-window-state', (win) ->
win.temporaryState
ipcHelpers.respondTo 'set-temporary-window-state', (win, state) ->
@disposable.add ipcHelpers.respondTo 'set-temporary-window-state', (win, state) ->
win.temporaryState = state
ipcMain.on 'did-cancel-window-unload', =>
@disposable.add ipcHelpers.on ipcMain, 'did-cancel-window-unload', =>
@quitting = false
clipboard = require '../safe-clipboard'
ipcMain.on 'write-text-to-selection-clipboard', (event, selectedText) ->
@disposable.add ipcHelpers.on ipcMain, 'write-text-to-selection-clipboard', (event, selectedText) ->
clipboard.writeText(selectedText, 'selection')
ipcMain.on 'write-to-stdout', (event, output) ->
@disposable.add ipcHelpers.on ipcMain, 'write-to-stdout', (event, output) ->
process.stdout.write(output)
ipcMain.on 'write-to-stderr', (event, output) ->
@disposable.add ipcHelpers.on ipcMain, 'write-to-stderr', (event, output) ->
process.stderr.write(output)
ipcMain.on 'add-recent-document', (event, filename) ->
@disposable.add ipcHelpers.on ipcMain, 'add-recent-document', (event, filename) ->
app.addRecentDocument(filename)
ipcMain.on 'execute-javascript-in-dev-tools', (event, code) ->
@disposable.add ipcHelpers.on ipcMain, 'execute-javascript-in-dev-tools', (event, code) ->
event.sender.devToolsWebContents?.executeJavaScript(code)
ipcMain.on 'get-auto-update-manager-state', (event) =>
@disposable.add ipcHelpers.on ipcMain, 'get-auto-update-manager-state', (event) =>
event.returnValue = @autoUpdateManager.getState()
ipcMain.on 'get-auto-update-manager-error', (event) =>
@disposable.add ipcHelpers.on ipcMain, 'get-auto-update-manager-error', (event) =>
event.returnValue = @autoUpdateManager.getErrorMessage()
ipcMain.on 'will-save-path', (event, path) =>
@disposable.add ipcHelpers.on ipcMain, 'will-save-path', (event, path) =>
@fileRecoveryService.willSavePath(@windowForEvent(event), path)
event.returnValue = true
ipcMain.on 'did-save-path', (event, path) =>
@disposable.add ipcHelpers.on ipcMain, 'did-save-path', (event, path) =>
@fileRecoveryService.didSavePath(@windowForEvent(event), path)
event.returnValue = true
@@ -498,7 +511,7 @@ class AtomApplication
windowInitializationScript ?= require.resolve('../initialize-application-window')
resourcePath ?= @resourcePath
windowDimensions ?= @getDimensionsForNewWindow()
openedWindow = new AtomWindow(@fileRecoveryService, {initialPaths, locationsToOpen, windowInitializationScript, resourcePath, devMode, safeMode, windowDimensions, profileStartup, clearWindowState, env})
openedWindow = new AtomWindow(this, @fileRecoveryService, {initialPaths, locationsToOpen, windowInitializationScript, resourcePath, devMode, safeMode, windowDimensions, profileStartup, clearWindowState, env})
if pidToKillWhenClosed?
@pidsToOpenWindows[pidToKillWhenClosed] = openedWindow
@@ -506,6 +519,8 @@ class AtomApplication
openedWindow.browserWindow.once 'closed', =>
@killProcessForWindow(openedWindow)
openedWindow
# Kill all processes associated with opened windows.
killAllProcesses: ->
@killProcess(pid) for pid of @pidsToOpenWindows
@@ -548,9 +563,8 @@ class AtomApplication
devMode: @devMode
safeMode: @safeMode
}))
true
else
false
null
# Open an atom:// url.
#
@@ -577,7 +591,7 @@ class AtomApplication
packagePath = @packages.resolvePackagePath(packageName)
windowInitializationScript = path.resolve(packagePath, pack.urlMain)
windowDimensions = @getDimensionsForNewWindow()
new AtomWindow(@fileRecoveryService, {windowInitializationScript, @resourcePath, devMode, safeMode, urlToOpen, windowDimensions, env})
new AtomWindow(this, @fileRecoveryService, {windowInitializationScript, @resourcePath, devMode, safeMode, urlToOpen, windowDimensions, env})
else
console.log "Package '#{pack.name}' does not have a url main: #{urlToOpen}"
else
@@ -622,7 +636,7 @@ class AtomApplication
devMode = true
isSpec = true
safeMode ?= false
new AtomWindow(@fileRecoveryService, {windowInitializationScript, resourcePath, headless, isSpec, devMode, testRunnerPath, legacyTestRunnerPath, testPaths, logFile, safeMode, env})
new AtomWindow(this, @fileRecoveryService, {windowInitializationScript, resourcePath, headless, isSpec, devMode, testRunnerPath, legacyTestRunnerPath, testPaths, logFile, safeMode, env})
resolveTestRunnerPath: (testPath) ->
FindParentDir ?= require 'find-parent-dir'
@@ -720,4 +734,3 @@ class AtomApplication
# once we're using electron v.1.2.2
# app.relaunch()
app.quit()

View File

@@ -15,11 +15,14 @@ class AtomWindow
loaded: null
isSpec: null
constructor: (@fileRecoveryService, settings={}) ->
constructor: (@atomApplication, @fileRecoveryService, settings={}) ->
{@resourcePath, initialPaths, pathToOpen, locationsToOpen, @isSpec, @headless, @safeMode, @devMode} = settings
locationsToOpen ?= [{pathToOpen}] if pathToOpen
locationsToOpen ?= []
@loadedPromise = new Promise((@resolveLoadedPromise) =>)
@closedPromise = new Promise((@resolveClosedPromise) =>)
options =
show: false
title: 'Atom'
@@ -44,7 +47,7 @@ class AtomWindow
options.titleBarStyle = 'hidden'
@browserWindow = new BrowserWindow options
global.atomApplication.addWindow(this)
@atomApplication.addWindow(this)
@handleEvents()
@@ -72,8 +75,9 @@ class AtomWindow
@browserWindow.loadSettings = loadSettings
@browserWindow.once 'window:loaded', =>
@emit 'window:loaded'
@loaded = true
@emit 'window:loaded'
@resolveLoadedPromise()
@setLoadSettings(loadSettings)
@env = loadSettings.env if loadSettings.env?
@@ -124,12 +128,13 @@ class AtomWindow
false
handleEvents: ->
@browserWindow.on 'close', ->
global.atomApplication.saveState(false)
@browserWindow.on 'close', =>
@atomApplication.saveState(false)
@browserWindow.on 'closed', =>
@fileRecoveryService.didCloseWindow(this)
global.atomApplication.removeWindow(this)
@atomApplication.removeWindow(this)
@resolveClosedPromise()
@browserWindow.on 'unresponsive', =>
return if @isSpec
@@ -142,7 +147,7 @@ class AtomWindow
@browserWindow.destroy() if chosen is 0
@browserWindow.webContents.on 'crashed', =>
global.atomApplication.exit(100) if @headless
@atomApplication.exit(100) if @headless
@fileRecoveryService.didCrashWindow(this)
chosen = dialog.showMessageBox @browserWindow,
@@ -182,7 +187,7 @@ class AtomWindow
sendCommand: (command, args...) ->
if @isSpecWindow()
unless global.atomApplication.sendCommandToFirstResponder(command)
unless @atomApplication.sendCommandToFirstResponder(command)
switch command
when 'window:reload' then @reload()
when 'window:toggle-dev-tools' then @toggleDevTools()
@@ -190,7 +195,7 @@ class AtomWindow
else if @isWebViewFocused()
@sendCommandToBrowserWindow(command, args...)
else
unless global.atomApplication.sendCommandToFirstResponder(command)
unless @atomApplication.sendCommandToFirstResponder(command)
@sendCommandToBrowserWindow(command, args...)
sendCommandToBrowserWindow: (command, args...) ->
@@ -205,7 +210,7 @@ class AtomWindow
shouldHideTitleBar: ->
not @isSpec and
process.platform is 'darwin' and
global.atomApplication.config.get('core.useCustomTitleBar')
@atomApplication.config.get('core.useCustomTitleBar')
close: -> @browserWindow.close()

View File

@@ -14,21 +14,20 @@ const {app} = require('electron')
const fs = require('fs-plus')
const path = require('path')
const temp = require('temp')
const yargs = require('yargs')
const dedent = require('dedent')
const parseCommandLine = require('./parse-command-line')
const startCrashReporter = require('../crash-reporter-start')
const previousConsoleLog = console.log
console.log = require('nslog')
function start () {
const args = parseCommandLine()
args.env = process.env
const args = parseCommandLine(process.argv.slice(1))
setupAtomHome(args)
setupCompileCache()
if (handleStartupEventWithSquirrel()) {
return
} else if (args.test && args.mainProcess) {
app.setPath('userData', temp.mkdirSync('atom-user-data-dir-for-main-process-tests'))
console.log = previousConsoleLog
app.on('ready', function () {
const testRunner = require(path.join(args.resourcePath, 'spec/main-process/mocha-test-runner'))
@@ -72,14 +71,6 @@ function start () {
})
}
function normalizeDriveLetterName (filePath) {
if (process.platform === 'win32') {
return filePath.replace(/^([a-z]):/, ([driveLetter]) => driveLetter.toUpperCase() + ':')
} else {
return filePath
}
}
function handleStartupEventWithSquirrel () {
if (process.platform !== 'win32') {
return false
@@ -125,141 +116,4 @@ function setupCompileCache () {
CompileCache.setAtomHomeDirectory(process.env.ATOM_HOME)
}
function writeFullVersion () {
process.stdout.write(
`Atom : ${app.getVersion()}\n` +
`Electron: ${process.versions.electron}\n` +
`Chrome : ${process.versions.chrome}\n` +
`Node : ${process.versions.node}\n`
)
}
function parseCommandLine () {
const options = yargs(process.argv.slice(1)).wrap(100)
const version = app.getVersion()
options.usage(
dedent`Atom Editor v${version}
Usage: atom [options] [path ...]
One or more paths to files or folders may be specified. If there is an
existing Atom window that contains all of the given folders, the paths
will be opened in that window. Otherwise, they will be opened in a new
window.
Environment Variables:
ATOM_DEV_RESOURCE_PATH The path from which Atom loads source code in dev mode.
Defaults to \`~/github/atom\`.
ATOM_HOME The root path for all configuration files and folders.
Defaults to \`~/.atom\`.`
)
// Deprecated 1.0 API preview flag
options.alias('1', 'one').boolean('1').describe('1', 'This option is no longer supported.')
options.boolean('include-deprecated-apis').describe('include-deprecated-apis', 'This option is not currently supported.')
options.alias('d', 'dev').boolean('d').describe('d', 'Run in development mode.')
options.alias('f', 'foreground').boolean('f').describe('f', 'Keep the main process in the foreground.')
options.alias('h', 'help').boolean('h').describe('h', 'Print this usage message.')
options.alias('l', 'log-file').string('l').describe('l', 'Log all output to file.')
options.alias('n', 'new-window').boolean('n').describe('n', 'Open a new window.')
options.boolean('profile-startup').describe('profile-startup', 'Create a profile of the startup execution time.')
options.alias('r', 'resource-path').string('r').describe('r', 'Set the path to the Atom source directory and enable dev-mode.')
options.boolean('safe').describe(
'safe',
'Do not load packages from ~/.atom/packages or ~/.atom/dev/packages.'
)
options.boolean('portable').describe(
'portable',
'Set portable mode. Copies the ~/.atom folder to be a sibling of the installed Atom location if a .atom folder is not already there.'
)
options.alias('t', 'test').boolean('t').describe('t', 'Run the specified specs and exit with error code on failures.')
options.alias('m', 'main-process').boolean('m').describe('m', 'Run the specified specs in the main process.')
options.string('timeout').describe(
'timeout',
'When in test mode, waits until the specified time (in minutes) and kills the process (exit code: 130).'
)
options.alias('v', 'version').boolean('v').describe('v', 'Print the version information.')
options.alias('w', 'wait').boolean('w').describe('w', 'Wait for window to be closed before returning.')
options.alias('a', 'add').boolean('a').describe('add', 'Open path as a new project in last used window.')
options.string('socket-path')
options.string('user-data-dir')
options.boolean('clear-window-state').describe('clear-window-state', 'Delete all Atom environment state.')
const args = options.argv
if (args.help) {
process.stdout.write(options.help())
process.exit(0)
}
if (args.version) {
writeFullVersion()
process.exit(0)
}
const addToLastWindow = args['add']
const safeMode = args['safe']
const pathsToOpen = args._
const test = args['test']
const mainProcess = args['main-process']
const timeout = args['timeout']
const newWindow = args['new-window']
let executedFrom = null
if (args['executed-from'] && args['executed-from'].toString()) {
executedFrom = args['executed-from'].toString()
} else {
executedFrom = process.cwd()
}
let pidToKillWhenClosed = null
if (args['wait']) {
pidToKillWhenClosed = args['pid']
}
const logFile = args['log-file']
const socketPath = args['socket-path']
const userDataDir = args['user-data-dir']
const profileStartup = args['profile-startup']
const clearWindowState = args['clear-window-state']
const urlsToOpen = []
const setPortable = args.portable
let devMode = args['dev']
let devResourcePath = process.env.ATOM_DEV_RESOURCE_PATH || path.join(app.getPath('home'), 'github', 'atom')
let resourcePath = null
if (args['resource-path']) {
devMode = true
resourcePath = args['resource-path']
}
if (test) {
devMode = true
}
if (devMode && !resourcePath) {
resourcePath = devResourcePath
}
if (!fs.statSyncNoException(resourcePath)) {
resourcePath = path.dirname(path.dirname(__dirname))
}
if (args['path-environment']) {
// On Yosemite the $PATH is not inherited by the "open" command, so we have to
// explicitly pass it by command line, see http://git.io/YC8_Ew.
process.env.PATH = args['path-environment']
}
resourcePath = normalizeDriveLetterName(resourcePath)
devResourcePath = normalizeDriveLetterName(devResourcePath)
return {
resourcePath, devResourcePath, pathsToOpen, urlsToOpen, executedFrom, test,
version, pidToKillWhenClosed, devMode, safeMode, newWindow, logFile, socketPath,
userDataDir, profileStartup, timeout, setPortable, clearWindowState,
addToLastWindow, mainProcess
}
}
start()

View File

@@ -0,0 +1,148 @@
'use strict'
const dedent = require('dedent')
const yargs = require('yargs')
const {app} = require('electron')
const path = require('path')
const fs = require('fs-plus')
module.exports = function parseCommandLine (processArgs) {
const options = yargs(processArgs).wrap(100)
const version = app.getVersion()
options.usage(
dedent`Atom Editor v${version}
Usage: atom [options] [path ...]
One or more paths to files or folders may be specified. If there is an
existing Atom window that contains all of the given folders, the paths
will be opened in that window. Otherwise, they will be opened in a new
window.
Environment Variables:
ATOM_DEV_RESOURCE_PATH The path from which Atom loads source code in dev mode.
Defaults to \`~/github/atom\`.
ATOM_HOME The root path for all configuration files and folders.
Defaults to \`~/.atom\`.`
)
// Deprecated 1.0 API preview flag
options.alias('1', 'one').boolean('1').describe('1', 'This option is no longer supported.')
options.boolean('include-deprecated-apis').describe('include-deprecated-apis', 'This option is not currently supported.')
options.alias('d', 'dev').boolean('d').describe('d', 'Run in development mode.')
options.alias('f', 'foreground').boolean('f').describe('f', 'Keep the main process in the foreground.')
options.alias('h', 'help').boolean('h').describe('h', 'Print this usage message.')
options.alias('l', 'log-file').string('l').describe('l', 'Log all output to file.')
options.alias('n', 'new-window').boolean('n').describe('n', 'Open a new window.')
options.boolean('profile-startup').describe('profile-startup', 'Create a profile of the startup execution time.')
options.alias('r', 'resource-path').string('r').describe('r', 'Set the path to the Atom source directory and enable dev-mode.')
options.boolean('safe').describe(
'safe',
'Do not load packages from ~/.atom/packages or ~/.atom/dev/packages.'
)
options.boolean('portable').describe(
'portable',
'Set portable mode. Copies the ~/.atom folder to be a sibling of the installed Atom location if a .atom folder is not already there.'
)
options.alias('t', 'test').boolean('t').describe('t', 'Run the specified specs and exit with error code on failures.')
options.alias('m', 'main-process').boolean('m').describe('m', 'Run the specified specs in the main process.')
options.string('timeout').describe(
'timeout',
'When in test mode, waits until the specified time (in minutes) and kills the process (exit code: 130).'
)
options.alias('v', 'version').boolean('v').describe('v', 'Print the version information.')
options.alias('w', 'wait').boolean('w').describe('w', 'Wait for window to be closed before returning.')
options.alias('a', 'add').boolean('a').describe('add', 'Open path as a new project in last used window.')
options.string('socket-path')
options.string('user-data-dir')
options.boolean('clear-window-state').describe('clear-window-state', 'Delete all Atom environment state.')
const args = options.argv
if (args.help) {
process.stdout.write(options.help())
process.exit(0)
}
if (args.version) {
process.stdout.write(
`Atom : ${app.getVersion()}\n` +
`Electron: ${process.versions.electron}\n` +
`Chrome : ${process.versions.chrome}\n` +
`Node : ${process.versions.node}\n`
)
process.exit(0)
}
const addToLastWindow = args['add']
const safeMode = args['safe']
const pathsToOpen = args._
const test = args['test']
const mainProcess = args['main-process']
const timeout = args['timeout']
const newWindow = args['new-window']
let executedFrom = null
if (args['executed-from'] && args['executed-from'].toString()) {
executedFrom = args['executed-from'].toString()
} else {
executedFrom = process.cwd()
}
let pidToKillWhenClosed = null
if (args['wait']) {
pidToKillWhenClosed = args['pid']
}
const logFile = args['log-file']
const socketPath = args['socket-path']
const userDataDir = args['user-data-dir']
const profileStartup = args['profile-startup']
const clearWindowState = args['clear-window-state']
const urlsToOpen = []
const setPortable = args.portable
let devMode = args['dev']
let devResourcePath = process.env.ATOM_DEV_RESOURCE_PATH || path.join(app.getPath('home'), 'github', 'atom')
let resourcePath = null
if (args['resource-path']) {
devMode = true
resourcePath = args['resource-path']
}
if (test) {
devMode = true
}
if (devMode && !resourcePath) {
resourcePath = devResourcePath
}
if (!fs.statSyncNoException(resourcePath)) {
resourcePath = path.dirname(path.dirname(__dirname))
}
if (args['path-environment']) {
// On Yosemite the $PATH is not inherited by the "open" command, so we have to
// explicitly pass it by command line, see http://git.io/YC8_Ew.
process.env.PATH = args['path-environment']
}
resourcePath = normalizeDriveLetterName(resourcePath)
devResourcePath = normalizeDriveLetterName(devResourcePath)
return {
resourcePath, devResourcePath, pathsToOpen, urlsToOpen, executedFrom, test,
version, pidToKillWhenClosed, devMode, safeMode, newWindow, logFile, socketPath,
userDataDir, profileStartup, timeout, setPortable, clearWindowState,
addToLastWindow, mainProcess, env: process.env
}
}
function normalizeDriveLetterName (filePath) {
if (process.platform === 'win32') {
return filePath.replace(/^([a-z]):/, ([driveLetter]) => driveLetter.toUpperCase() + ':')
} else {
return filePath
}
}

View File

@@ -26,7 +26,7 @@ class StateStore {
save (key, value) {
return new Promise((resolve, reject) => {
this.dbPromise.then(db => {
if (db == null) resolve()
if (db == null) return resolve()
var request = db.transaction(['states'], 'readwrite')
.objectStore('states')

View File

@@ -12,6 +12,7 @@ class WindowEventHandler
@previousOnbeforeunloadHandler = @window.onbeforeunload
@window.onbeforeunload = @handleWindowBeforeunload
@addEventListener(@window, 'unload', @handleWindowUnload)
@addEventListener(@window, 'focus', @handleWindowFocus)
@addEventListener(@window, 'blur', @handleWindowBlur)