Merge branch 'master' into async-git-bumps

This commit is contained in:
joshaber 2016-02-18 09:40:43 -05:00
commit 95cdbde1ec
54 changed files with 742 additions and 478 deletions

View File

@ -406,10 +406,6 @@ Please open an issue on `atom/atom` if you have suggestions for new labels, and
| Label name | `atom/atom` :mag_right: | `atom`org :mag_right: | Description |
| --- | --- | --- | --- |
| `in-progress` | [search][search-atom-repo-label-in-progress] | [search][search-atom-org-label-in-progress] | Tasks which the Atom core team is working on currently. |
| `on-deck` | [search][search-atom-repo-label-on-deck] | [search][search-atom-org-label-on-deck] | Tasks which the Atom core team plans to work on next. |
| `shipping` | [search][search-atom-repo-label-shipping] | [search][search-atom-org-label-shipping] | Tasks which the Atom core team completed and will be released in one of the next releases. |
| `post-1.0-roadmap` | [search][search-atom-repo-label-post-1.0-roadmap] | [search][search-atom-org-label-post-1.0-roadmap] | The Atom core team's roadmap post version 1.0.0. |
| `atom` | [search][search-atom-repo-label-atom] | [search][search-atom-org-label-atom] | Topics discussed for prioritization at the next meeting of Atom core team members. |
#### Pull Request Labels
@ -498,14 +494,6 @@ Please open an issue on `atom/atom` if you have suggestions for new labels, and
[search-atom-org-label-deprecation-help]: https://github.com/issues?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Adeprecation-help
[search-atom-repo-label-electron]: https://github.com/issues?q=is%3Aissue+repo%3Aatom%2Fatom+is%3Aopen+label%3Aelectron
[search-atom-org-label-electron]: https://github.com/issues?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Aelectron
[search-atom-repo-label-on-deck]: https://github.com/issues?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Aon-deck
[search-atom-org-label-on-deck]: https://github.com/issues?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Aon-deck
[search-atom-repo-label-in-progress]: https://github.com/issues?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Ain-progress
[search-atom-org-label-in-progress]: https://github.com/issues?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Ain-progress
[search-atom-repo-label-shipping]: https://github.com/issues?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Ashipping
[search-atom-org-label-shipping]: https://github.com/issues?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Ashipping
[search-atom-repo-label-post-1.0-roadmap]: https://github.com/issues?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Apost-1.0-roadmap
[search-atom-org-label-post-1.0-roadmap]: https://github.com/issues?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Apost-1.0-roadmap
[search-atom-repo-label-atom]: https://github.com/issues?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Aatom
[search-atom-org-label-atom]: https://github.com/issues?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Aatom
[search-atom-repo-label-work-in-progress]: https://github.com/pulls?q=is%3Aopen+is%3Apr+repo%3Aatom%2Fatom+label%3Awork-in-progress

View File

@ -25,7 +25,7 @@
"grunt-contrib-less": "~0.8.0",
"grunt-cson": "0.16.0",
"grunt-download-electron": "^2.1.1",
"grunt-electron-installer": "1.0.6",
"grunt-electron-installer": "1.2.2",
"grunt-lesslint": "0.17.0",
"grunt-peg": "~1.1.0",
"grunt-shell": "~0.3.1",

View File

@ -1,5 +1,6 @@
fs = require 'fs'
path = require 'path'
temp = require('temp').track()
_ = require 'underscore-plus'
async = require 'async'
@ -94,7 +95,7 @@ module.exports = (grunt) ->
if process.platform in ['darwin', 'linux']
options =
cmd: appPath
args: ['--test', "--resource-path=#{resourcePath}", coreSpecsPath]
args: ['--test', "--resource-path=#{resourcePath}", coreSpecsPath, "--user-data-dir=#{temp.mkdirSync('atom-user-data-dir')}"]
opts:
env: _.extend({}, process.env,
ATOM_INTEGRATION_TESTS_ENABLED: true

View File

@ -12,7 +12,7 @@
"url": "https://github.com/atom/atom/issues"
},
"license": "MIT",
"electronVersion": "0.34.5",
"electronVersion": "0.36.7",
"dependencies": {
"async": "0.2.6",
"atom-keymap": "^6.2.0",
@ -54,7 +54,7 @@
"service-hub": "^0.7.0",
"source-map-support": "^0.3.2",
"temp": "0.8.1",
"text-buffer": "8.3.0",
"text-buffer": "8.3.1",
"typescript-simple": "1.0.0",
"underscore-plus": "^1.6.6",
"yargs": "^3.23.0"
@ -173,7 +173,8 @@
"runs",
"spyOn",
"waitsFor",
"waitsForPromise"
"waitsForPromise",
"indexedDB"
]
}
}

View File

@ -4,15 +4,16 @@ var fs = require('fs');
var path = require('path');
var os = require('os');
var removeCommand = process.platform === 'win32' ? 'rmdir /S /Q ' : 'rm -rf ';
var isWindows = process.platform === 'win32';
var removeCommand = isWindows ? 'rmdir /S /Q ' : 'rm -rf ';
var productName = require('../package.json').productName;
process.chdir(path.dirname(__dirname));
var home = process.env[(process.platform === 'win32') ? 'USERPROFILE' : 'HOME'];
var home = process.env[isWindows ? 'USERPROFILE' : 'HOME'];
var tmpdir = os.tmpdir();
// Windows: Use START as a way to ignore error if Atom.exe isnt running
var killatom = process.platform === 'win32' ? 'START taskkill /F /IM ' + productName + '.exe' : 'pkill -9 ' + productName + ' || true';
var killatom = isWindows ? 'START taskkill /F /IM ' + productName + '.exe' : 'pkill -9 ' + productName + ' || true';
var commands = [
killatom,
@ -39,12 +40,32 @@ var run = function() {
if (Array.isArray(next)) {
var pathToRemove = path.resolve.apply(path.resolve, next);
if (fs.existsSync(pathToRemove))
next = removeCommand + pathToRemove;
else
if (fs.existsSync(pathToRemove)) {
if (isWindows) {
removeFolderRecursive(pathToRemove);
} else {
next = removeCommand + pathToRemove;
cp.safeExec(next, run);
}
}
else {
return run();
}
}
cp.safeExec(next, run);
else
cp.safeExec(next, run);
};
run();
// Windows has a 260-char path limit for rmdir etc. Just recursively delete in Node.
var removeFolderRecursive = function(folderPath) {
fs.readdirSync(folderPath).forEach(function(entry, index) {
var entryPath = path.join(folderPath, entry);
if (fs.lstatSync(entryPath).isDirectory()) {
removeFolderRecursive(entryPath);
} else {
fs.unlinkSync(entryPath);
}
});
fs.rmdirSync(folderPath);
};

View File

@ -152,6 +152,8 @@ describe "AtomEnvironment", ->
atom.enablePersistence = false
it "selects the state based on the current project paths", ->
jasmine.useRealClock()
[dir1, dir2] = [temp.mkdirSync("dir1-"), temp.mkdirSync("dir2-")]
loadSettings = _.extend atom.getLoadSettings(),
@ -159,20 +161,40 @@ describe "AtomEnvironment", ->
windowState: null
spyOn(atom, 'getLoadSettings').andCallFake -> loadSettings
spyOn(atom.getStorageFolder(), 'getPath').andReturn(temp.mkdirSync("storage-dir-"))
spyOn(atom, 'serialize').andReturn({stuff: 'cool'})
spyOn(atom, 'deserialize')
atom.state.stuff = "cool"
atom.project.setPaths([dir1, dir2])
atom.saveStateSync()
# State persistence will fail if other Atom instances are running
waitsForPromise ->
atom.stateStore.connect().then (isConnected) ->
expect(isConnected).toBe true
atom.state = {}
atom.loadStateSync()
expect(atom.state.stuff).toBeUndefined()
waitsForPromise ->
atom.saveState().then ->
atom.loadState()
loadSettings.initialPaths = [dir2, dir1]
atom.state = {}
atom.loadStateSync()
expect(atom.state.stuff).toBe("cool")
runs ->
expect(atom.deserialize).not.toHaveBeenCalled()
waitsForPromise ->
loadSettings.initialPaths = [dir2, dir1]
atom.loadState()
runs ->
expect(atom.deserialize).toHaveBeenCalledWith({stuff: 'cool'})
it "saves state on keydown and mousedown events", ->
spyOn(atom, 'saveState')
keydown = new KeyboardEvent('keydown')
atom.document.dispatchEvent(keydown)
advanceClock atom.saveStateDebounceInterval
expect(atom.saveState).toHaveBeenCalled()
mousedown = new MouseEvent('mousedown')
atom.document.dispatchEvent(mousedown)
advanceClock atom.saveStateDebounceInterval
expect(atom.saveState).toHaveBeenCalled()
describe "openInitialEmptyEditorIfNecessary", ->
describe "when there are no paths set", ->
@ -230,23 +252,6 @@ describe "AtomEnvironment", ->
atomEnvironment.destroy()
it "saves the serialized state of the window so it can be deserialized after reload", ->
atomEnvironment = new AtomEnvironment({applicationDelegate: atom.applicationDelegate, window, document})
spyOn(atomEnvironment, 'saveStateSync')
workspaceState = atomEnvironment.workspace.serialize()
grammarsState = {grammarOverridesByPath: atomEnvironment.grammars.grammarOverridesByPath}
projectState = atomEnvironment.project.serialize()
atomEnvironment.unloadEditorWindow()
expect(atomEnvironment.state.workspace).toEqual workspaceState
expect(atomEnvironment.state.grammars).toEqual grammarsState
expect(atomEnvironment.state.project).toEqual projectState
expect(atomEnvironment.saveStateSync).toHaveBeenCalled()
atomEnvironment.destroy()
describe "::destroy()", ->
it "does not throw exceptions when unsubscribing from ipc events (regression)", ->
configDirPath = temp.mkdirSync()

View File

@ -172,7 +172,7 @@ class AtomReporter
listen document, 'click', '.stack-trace', (event) ->
event.currentTarget.classList.toggle('expanded')
@reloadButton.addEventListener('click', -> require('ipc').send('call-window-method', 'restart'))
@reloadButton.addEventListener('click', -> require('electron').ipcRenderer.send('call-window-method', 'restart'))
updateSpecCounts: ->
if @skippedCount

View File

@ -15,6 +15,8 @@ ChromedriverPort = 9515
ChromedriverURLBase = "/wd/hub"
ChromedriverStatusURL = "http://localhost:#{ChromedriverPort}#{ChromedriverURLBase}/status"
userDataDir = temp.mkdirSync('atom-user-data-dir')
chromeDriverUp = (done) ->
checkStatus = ->
http
@ -48,7 +50,7 @@ buildAtomClient = (args, env) ->
"atom-env=#{map(env, (value, key) -> "#{key}=#{value}").join(" ")}"
"dev"
"safe"
"user-data-dir=#{temp.mkdirSync('atom-user-data-dir')}"
"user-data-dir=#{userDataDir}"
"socket-path=#{SocketPath}"
])
@ -124,7 +126,7 @@ buildAtomClient = (args, env) ->
.addCommand "simulateQuit", (done) ->
@execute -> atom.unloadEditorWindow()
.execute -> require("remote").require("app").emit("before-quit")
.execute -> require("electron").remote.app.emit("before-quit")
.call(done)
module.exports = (args, env, fn) ->

View File

@ -28,13 +28,12 @@ describe "Starting Atom", ->
it "opens the parent directory and creates an empty text editor", ->
runAtom [path.join(tempDirPath, "new-file")], {ATOM_HOME: atomHome}, (client) ->
client
.waitForPaneItemCount(1, 1000)
.treeViewRootDirectories()
.then ({value}) -> expect(value).toEqual([tempDirPath])
.waitForExist("atom-text-editor", 5000)
.then (exists) -> expect(exists).toBe true
.waitForPaneItemCount(1, 1000)
.click("atom-text-editor")
.keys("Hello!")
.execute -> atom.workspace.getActiveTextEditor().getText()
@ -153,6 +152,8 @@ describe "Starting Atom", ->
.waitForPaneItemCount(0, 3000)
.execute -> atom.workspace.open()
.waitForPaneItemCount(1, 3000)
.keys("Hello!")
.waitUntil((-> Promise.resolve(false)), 1100)
runAtom [tempDirPath], {ATOM_HOME: atomHome}, (client) ->
client

View File

@ -1,7 +1,7 @@
_ = require 'underscore-plus'
fs = require 'fs-plus'
path = require 'path'
ipc = require 'ipc'
{ipcRenderer} = require 'electron'
module.exports = ({logFile, headless, testPaths, buildAtomEnvironment}) ->
window[key] = value for key, value of require '../vendor/jasmine'
@ -88,7 +88,7 @@ buildTerminalReporter = (logFile, resolveWithExitCode) ->
if logStream?
fs.writeSync(logStream, str)
else
ipc.send 'write-to-stderr', str
ipcRenderer.send 'write-to-stderr', str
{TerminalReporter} = require 'jasmine-tagged'
new TerminalReporter

View File

@ -463,17 +463,6 @@ describe "LanguageMode", ->
fold2 = editor.tokenizedLineForScreenRow(5).fold
expect(fold2).toBeFalsy()
describe ".isFoldableAtBufferRow(bufferRow)", ->
it "returns true if the line starts a multi-line comment", ->
expect(languageMode.isFoldableAtBufferRow(1)).toBe true
expect(languageMode.isFoldableAtBufferRow(6)).toBe true
expect(languageMode.isFoldableAtBufferRow(17)).toBe false
it "does not return true for a line in the middle of a comment that's followed by an indented line", ->
expect(languageMode.isFoldableAtBufferRow(7)).toBe false
editor.buffer.insert([8, 0], ' ')
expect(languageMode.isFoldableAtBufferRow(7)).toBe false
describe "css", ->
beforeEach ->
waitsForPromise ->

View File

@ -446,16 +446,15 @@ describe "PackageManager", ->
pack = null
waitsForPromise ->
atom.packages.activatePackage("package-with-serialization").then (p) -> pack = p
runs ->
expect(pack.mainModule.someNumber).not.toBe 77
pack.mainModule.someNumber = 77
atom.packages.deactivatePackage("package-with-serialization")
spyOn(pack.mainModule, 'activate').andCallThrough()
waitsForPromise ->
atom.packages.activatePackage("package-with-serialization")
runs ->
expect(pack.mainModule.activate).toHaveBeenCalledWith({someNumber: 77})
waitsForPromise ->
atom.packages.activatePackage("package-with-serialization")
runs ->
expect(pack.mainModule.activate).toHaveBeenCalledWith({someNumber: 77})
it "invokes ::onDidActivatePackage listeners with the activated package", ->
activatedPackage = null
@ -819,6 +818,34 @@ describe "PackageManager", ->
expect(atom.packages.isPackageActive("package-with-missing-provided-services")).toBe true
expect(addErrorHandler.callCount).toBe 0
describe "::serialize", ->
it "does not serialize packages that threw an error during activation", ->
spyOn(console, 'warn')
badPack = null
waitsForPromise ->
atom.packages.activatePackage("package-that-throws-on-activate").then (p) -> badPack = p
runs ->
spyOn(badPack.mainModule, 'serialize').andCallThrough()
atom.packages.serialize()
expect(badPack.mainModule.serialize).not.toHaveBeenCalled()
it "absorbs exceptions that are thrown by the package module's serialize method", ->
spyOn(console, 'error')
waitsForPromise ->
atom.packages.activatePackage('package-with-serialize-error')
waitsForPromise ->
atom.packages.activatePackage('package-with-serialization')
runs ->
atom.packages.serialize()
expect(atom.packages.packageStates['package-with-serialize-error']).toBeUndefined()
expect(atom.packages.packageStates['package-with-serialization']).toEqual someNumber: 1
expect(console.error).toHaveBeenCalled()
describe "::deactivatePackage(id)", ->
afterEach ->
atom.packages.unloadPackages()
@ -850,33 +877,6 @@ describe "PackageManager", ->
expect(badPack.mainModule.deactivate).not.toHaveBeenCalled()
expect(atom.packages.isPackageActive("package-that-throws-on-activate")).toBeFalsy()
it "does not serialize packages that have not been activated called on their main module", ->
spyOn(console, 'warn')
badPack = null
waitsForPromise ->
atom.packages.activatePackage("package-that-throws-on-activate").then (p) -> badPack = p
runs ->
spyOn(badPack.mainModule, 'serialize').andCallThrough()
atom.packages.deactivatePackage("package-that-throws-on-activate")
expect(badPack.mainModule.serialize).not.toHaveBeenCalled()
it "absorbs exceptions that are thrown by the package module's serialize method", ->
spyOn(console, 'error')
waitsForPromise ->
atom.packages.activatePackage('package-with-serialize-error')
waitsForPromise ->
atom.packages.activatePackage('package-with-serialization')
runs ->
atom.packages.deactivatePackages()
expect(atom.packages.packageStates['package-with-serialize-error']).toBeUndefined()
expect(atom.packages.packageStates['package-with-serialization']).toEqual someNumber: 1
expect(console.error).toHaveBeenCalled()
it "absorbs exceptions that are thrown by the package module's deactivate method", ->
spyOn(console, 'error')

61
spec/state-store-spec.js Normal file
View File

@ -0,0 +1,61 @@
/** @babel */
import {it, fit, ffit, fffit, beforeEach, afterEach} from './async-spec-helpers'
const StateStore = require('../src/state-store.js')
describe("StateStore", () => {
let databaseName = `test-database-${Date.now()}`
let version = 1
it("can save and load states", () => {
const store = new StateStore(databaseName, version)
return store.save('key', {foo:'bar'})
.then(() => store.load('key'))
.then((state) => {
expect(state).toEqual({foo:'bar'})
})
})
it("resolves with null when a non-existent key is loaded", () => {
const store = new StateStore(databaseName, version)
return store.load('no-such-key').then((value) => {
expect(value).toBeNull()
})
})
it("can clear the state object store", () => {
const store = new StateStore(databaseName, version)
return store.save('key', {foo:'bar'})
.then(() => store.count())
.then((count) =>
expect(count).toBe(1)
)
.then(() => store.clear())
.then(() => store.count())
.then((count) => {
expect(count).toBe(0)
})
})
describe("when there is an error reading from the database", () => {
it("rejects the promise returned by load", () => {
const store = new StateStore(databaseName, version)
const fakeErrorEvent = {target: {errorCode: "Something bad happened"}}
spyOn(IDBObjectStore.prototype, 'get').andCallFake((key) => {
let request = {}
process.nextTick(() => request.onerror(fakeErrorEvent))
return request
})
return store.load('nonexistentKey')
.then(() => {
throw new Error("Promise should have been rejected")
})
.catch((event) => {
expect(event).toBe(fakeErrorEvent)
})
})
})
})

View File

@ -2151,10 +2151,11 @@ describe('TextEditorComponent', function () {
item.style.height = itemHeight + 'px'
wrapperNode.style.width = windowWidth + 'px'
wrapperNode.style.height = windowHeight + 'px'
atom.setWindowDimensions({
await atom.setWindowDimensions({
width: windowWidth,
height: windowHeight
})
component.measureDimensions()
component.measureWindowSize()
await nextViewUpdatePromise()
@ -4834,7 +4835,7 @@ describe('TextEditorComponent', function () {
it('pastes the previously selected text at the clicked location', async function () {
let clipboardWrittenTo = false
spyOn(require('ipc'), 'send').andCallFake(function (eventName, selectedText) {
spyOn(require('electron').ipcRenderer, 'send').andCallFake(function (eventName, selectedText) {
if (eventName === 'write-text-to-selection-clipboard') {
require('../src/safe-clipboard').writeText(selectedText, 'selection')
clipboardWrittenTo = true

View File

@ -202,8 +202,7 @@ describe "TokenizedBuffer", ->
expect(tokenizedBuffer.firstInvalidRow()).toBe 3
advanceClock()
# we discover that row 2 starts a foldable region when line 3 gets tokenized
expect(changeHandler).toHaveBeenCalledWith(start: 2, end: 7, delta: 0)
expect(changeHandler).toHaveBeenCalledWith(start: 3, end: 7, delta: 0)
expect(tokenizedBuffer.firstInvalidRow()).toBe 8
describe "when there is a buffer change surrounding an invalid row", ->
@ -253,7 +252,7 @@ describe "TokenizedBuffer", ->
expect(changeHandler).toHaveBeenCalled()
[event] = changeHandler.argsForCall[0]
delete event.bufferChange
expect(event).toEqual(start: 1, end: 2, delta: 0)
expect(event).toEqual(start: 2, end: 2, delta: 0)
changeHandler.reset()
advanceClock()
@ -263,8 +262,7 @@ describe "TokenizedBuffer", ->
expect(changeHandler).toHaveBeenCalled()
[event] = changeHandler.argsForCall[0]
delete event.bufferChange
# we discover that row 2 starts a foldable region when line 3 gets tokenized
expect(event).toEqual(start: 2, end: 5, delta: 0)
expect(event).toEqual(start: 3, end: 5, delta: 0)
it "resumes highlighting with the state of the previous line", ->
buffer.insert([0, 0], '/*')
@ -292,7 +290,7 @@ describe "TokenizedBuffer", ->
expect(changeHandler).toHaveBeenCalled()
[event] = changeHandler.argsForCall[0]
delete event.bufferChange
expect(event).toEqual(start: 0, end: 3, delta: -2) # starts at 0 because foldable on row 0 becomes false
expect(event).toEqual(start: 1, end: 3, delta: -2)
describe "when the change invalidates the tokenization of subsequent lines", ->
it "schedules the invalidated lines to be tokenized in the background", ->
@ -305,7 +303,7 @@ describe "TokenizedBuffer", ->
expect(changeHandler).toHaveBeenCalled()
[event] = changeHandler.argsForCall[0]
delete event.bufferChange
expect(event).toEqual(start: 1, end: 3, delta: -1)
expect(event).toEqual(start: 2, end: 3, delta: -1)
changeHandler.reset()
advanceClock()
@ -314,8 +312,7 @@ describe "TokenizedBuffer", ->
expect(changeHandler).toHaveBeenCalled()
[event] = changeHandler.argsForCall[0]
delete event.bufferChange
# we discover that row 2 starts a foldable region when line 3 gets tokenized
expect(event).toEqual(start: 2, end: 4, delta: 0)
expect(event).toEqual(start: 3, end: 4, delta: 0)
describe "when lines are both updated and inserted", ->
it "updates tokens to reflect the change", ->
@ -339,7 +336,7 @@ describe "TokenizedBuffer", ->
expect(changeHandler).toHaveBeenCalled()
[event] = changeHandler.argsForCall[0]
delete event.bufferChange
expect(event).toEqual(start: 0, end: 2, delta: 2) # starts at 0 because .foldable becomes false on row 0
expect(event).toEqual(start: 1, end: 2, delta: 2)
describe "when the change invalidates the tokenization of subsequent lines", ->
it "schedules the invalidated lines to be tokenized in the background", ->
@ -350,7 +347,7 @@ describe "TokenizedBuffer", ->
expect(changeHandler).toHaveBeenCalled()
[event] = changeHandler.argsForCall[0]
delete event.bufferChange
expect(event).toEqual(start: 1, end: 2, delta: 2)
expect(event).toEqual(start: 2, end: 2, delta: 2)
expect(tokenizedBuffer.tokenizedLineForRow(2).tokens[0].scopes).toEqual ['source.js', 'comment.block.js', 'punctuation.definition.comment.js']
expect(tokenizedBuffer.tokenizedLineForRow(3).tokens[0].scopes).toEqual ['source.js', 'comment.block.js']
expect(tokenizedBuffer.tokenizedLineForRow(4).tokens[0].scopes).toEqual ['source.js', 'comment.block.js']
@ -894,7 +891,7 @@ describe "TokenizedBuffer", ->
buffer.setTextInRange([[7, 0], [8, 65]], ' ok')
delete changeHandler.argsForCall[0][0].bufferChange
expect(changeHandler).toHaveBeenCalledWith(start: 4, end: 10, delta: -1) # starts at row 4 because it became foldable
expect(changeHandler).toHaveBeenCalledWith(start: 5, end: 10, delta: -1)
expect(tokenizedBuffer.tokenizedLineForRow(5).indentLevel).toBe 2
expect(tokenizedBuffer.tokenizedLineForRow(6).indentLevel).toBe 2
@ -903,7 +900,7 @@ describe "TokenizedBuffer", ->
expect(tokenizedBuffer.tokenizedLineForRow(9).indentLevel).toBe 2
expect(tokenizedBuffer.tokenizedLineForRow(10).indentLevel).toBe 2 # }
describe ".foldable on tokenized lines", ->
describe "::isFoldableAtRow(row)", ->
changes = null
beforeEach ->
@ -915,74 +912,66 @@ describe "TokenizedBuffer", ->
buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages, assert: atom.assert
})
fullyTokenize(tokenizedBuffer)
tokenizedBuffer.onDidChange (change) ->
delete change.bufferChange
changes.push(change)
it "sets .foldable to true on the first line of multi-line comments", ->
expect(tokenizedBuffer.tokenizedLineForRow(0).foldable).toBe true
expect(tokenizedBuffer.tokenizedLineForRow(1).foldable).toBe false
expect(tokenizedBuffer.tokenizedLineForRow(2).foldable).toBe false
expect(tokenizedBuffer.tokenizedLineForRow(3).foldable).toBe true # because of indent
expect(tokenizedBuffer.tokenizedLineForRow(13).foldable).toBe true
expect(tokenizedBuffer.tokenizedLineForRow(14).foldable).toBe false
expect(tokenizedBuffer.tokenizedLineForRow(15).foldable).toBe false
expect(tokenizedBuffer.tokenizedLineForRow(16).foldable).toBe false
it "includes the first line of multi-line comments", ->
expect(tokenizedBuffer.isFoldableAtRow(0)).toBe true
expect(tokenizedBuffer.isFoldableAtRow(1)).toBe false
expect(tokenizedBuffer.isFoldableAtRow(2)).toBe false
expect(tokenizedBuffer.isFoldableAtRow(3)).toBe true # because of indent
expect(tokenizedBuffer.isFoldableAtRow(13)).toBe true
expect(tokenizedBuffer.isFoldableAtRow(14)).toBe false
expect(tokenizedBuffer.isFoldableAtRow(15)).toBe false
expect(tokenizedBuffer.isFoldableAtRow(16)).toBe false
buffer.insert([0, Infinity], '\n')
expect(changes).toEqual [{start: 0, end: 1, delta: 1}]
expect(tokenizedBuffer.tokenizedLineForRow(0).foldable).toBe false
expect(tokenizedBuffer.tokenizedLineForRow(1).foldable).toBe false
expect(tokenizedBuffer.tokenizedLineForRow(2).foldable).toBe true
expect(tokenizedBuffer.tokenizedLineForRow(3).foldable).toBe false
expect(tokenizedBuffer.isFoldableAtRow(0)).toBe false
expect(tokenizedBuffer.isFoldableAtRow(1)).toBe false
expect(tokenizedBuffer.isFoldableAtRow(2)).toBe true
expect(tokenizedBuffer.isFoldableAtRow(3)).toBe false
changes = []
buffer.undo()
expect(changes).toEqual [{start: 0, end: 2, delta: -1}]
expect(tokenizedBuffer.tokenizedLineForRow(0).foldable).toBe true
expect(tokenizedBuffer.tokenizedLineForRow(1).foldable).toBe false
expect(tokenizedBuffer.tokenizedLineForRow(2).foldable).toBe false
expect(tokenizedBuffer.tokenizedLineForRow(3).foldable).toBe true # because of indent
it "sets .foldable to true on non-comment lines that precede an increase in indentation", ->
expect(tokenizedBuffer.isFoldableAtRow(0)).toBe true
expect(tokenizedBuffer.isFoldableAtRow(1)).toBe false
expect(tokenizedBuffer.isFoldableAtRow(2)).toBe false
expect(tokenizedBuffer.isFoldableAtRow(3)).toBe true # because of indent
it "includes non-comment lines that precede an increase in indentation", ->
buffer.insert([2, 0], ' ') # commented lines preceding an indent aren't foldable
expect(tokenizedBuffer.tokenizedLineForRow(1).foldable).toBe false
expect(tokenizedBuffer.tokenizedLineForRow(2).foldable).toBe false
expect(tokenizedBuffer.tokenizedLineForRow(3).foldable).toBe true
expect(tokenizedBuffer.tokenizedLineForRow(4).foldable).toBe true
expect(tokenizedBuffer.tokenizedLineForRow(5).foldable).toBe false
expect(tokenizedBuffer.tokenizedLineForRow(6).foldable).toBe false
expect(tokenizedBuffer.tokenizedLineForRow(7).foldable).toBe true
expect(tokenizedBuffer.tokenizedLineForRow(8).foldable).toBe false
changes = []
expect(tokenizedBuffer.isFoldableAtRow(1)).toBe false
expect(tokenizedBuffer.isFoldableAtRow(2)).toBe false
expect(tokenizedBuffer.isFoldableAtRow(3)).toBe true
expect(tokenizedBuffer.isFoldableAtRow(4)).toBe true
expect(tokenizedBuffer.isFoldableAtRow(5)).toBe false
expect(tokenizedBuffer.isFoldableAtRow(6)).toBe false
expect(tokenizedBuffer.isFoldableAtRow(7)).toBe true
expect(tokenizedBuffer.isFoldableAtRow(8)).toBe false
buffer.insert([7, 0], ' ')
expect(changes).toEqual [{start: 6, end: 7, delta: 0}]
expect(tokenizedBuffer.tokenizedLineForRow(6).foldable).toBe true
expect(tokenizedBuffer.tokenizedLineForRow(7).foldable).toBe false
expect(tokenizedBuffer.tokenizedLineForRow(8).foldable).toBe false
changes = []
expect(tokenizedBuffer.isFoldableAtRow(6)).toBe true
expect(tokenizedBuffer.isFoldableAtRow(7)).toBe false
expect(tokenizedBuffer.isFoldableAtRow(8)).toBe false
buffer.undo()
expect(changes).toEqual [{start: 6, end: 7, delta: 0}]
expect(tokenizedBuffer.tokenizedLineForRow(6).foldable).toBe false
expect(tokenizedBuffer.tokenizedLineForRow(7).foldable).toBe true
expect(tokenizedBuffer.tokenizedLineForRow(8).foldable).toBe false
changes = []
expect(tokenizedBuffer.isFoldableAtRow(6)).toBe false
expect(tokenizedBuffer.isFoldableAtRow(7)).toBe true
expect(tokenizedBuffer.isFoldableAtRow(8)).toBe false
buffer.insert([7, 0], " \n x\n")
expect(changes).toEqual [{start: 6, end: 7, delta: 2}]
expect(tokenizedBuffer.tokenizedLineForRow(6).foldable).toBe true
expect(tokenizedBuffer.tokenizedLineForRow(7).foldable).toBe false
expect(tokenizedBuffer.tokenizedLineForRow(8).foldable).toBe false
changes = []
expect(tokenizedBuffer.isFoldableAtRow(6)).toBe true
expect(tokenizedBuffer.isFoldableAtRow(7)).toBe false
expect(tokenizedBuffer.isFoldableAtRow(8)).toBe false
buffer.insert([9, 0], " ")
expect(changes).toEqual [{start: 9, end: 9, delta: 0}]
expect(tokenizedBuffer.tokenizedLineForRow(6).foldable).toBe true
expect(tokenizedBuffer.tokenizedLineForRow(7).foldable).toBe false
expect(tokenizedBuffer.tokenizedLineForRow(8).foldable).toBe false
expect(tokenizedBuffer.isFoldableAtRow(6)).toBe true
expect(tokenizedBuffer.isFoldableAtRow(7)).toBe false
expect(tokenizedBuffer.isFoldableAtRow(8)).toBe false
describe "when the buffer is configured with the null grammar", ->
it "uses the placeholder tokens and does not actually tokenize using the grammar", ->

View File

@ -4,7 +4,7 @@ fs = require 'fs-plus'
temp = require 'temp'
TextEditor = require '../src/text-editor'
WindowEventHandler = require '../src/window-event-handler'
ipc = require 'ipc'
{ipcRenderer} = require 'electron'
describe "WindowEventHandler", ->
[projectPath, windowEventHandler] = []
@ -53,7 +53,7 @@ describe "WindowEventHandler", ->
describe "beforeunload event", ->
beforeEach ->
jasmine.unspy(TextEditor.prototype, "shouldPromptToSave")
spyOn(ipc, 'send')
spyOn(ipcRenderer, 'send')
describe "when pane items are modified", ->
editor = null
@ -65,13 +65,13 @@ describe "WindowEventHandler", ->
spyOn(atom.workspace, 'confirmClose').andReturn(true)
window.dispatchEvent(new CustomEvent('beforeunload'))
expect(atom.workspace.confirmClose).toHaveBeenCalled()
expect(ipc.send).not.toHaveBeenCalledWith('did-cancel-window-unload')
expect(ipcRenderer.send).not.toHaveBeenCalledWith('did-cancel-window-unload')
it "cancels the unload if the user selects cancel", ->
spyOn(atom.workspace, 'confirmClose').andReturn(false)
window.dispatchEvent(new CustomEvent('beforeunload'))
expect(atom.workspace.confirmClose).toHaveBeenCalled()
expect(ipc.send).toHaveBeenCalledWith('did-cancel-window-unload')
expect(ipcRenderer.send).toHaveBeenCalledWith('did-cancel-window-unload')
describe "when a link is clicked", ->
it "opens the http/https links in an external application", ->

View File

@ -1,4 +1,4 @@
ipc = require 'ipc'
{ipcRenderer} = require 'electron'
path = require 'path'
temp = require('temp').track()
@ -127,35 +127,35 @@ describe "WorkspaceElement", ->
describe "the 'window:run-package-specs' command", ->
it "runs the package specs for the active item's project path, or the first project path", ->
workspaceElement = atom.views.getView(atom.workspace)
spyOn(ipc, 'send')
spyOn(ipcRenderer, 'send')
# No project paths. Don't try to run specs.
atom.commands.dispatch(workspaceElement, "window:run-package-specs")
expect(ipc.send).not.toHaveBeenCalledWith("run-package-specs")
expect(ipcRenderer.send).not.toHaveBeenCalledWith("run-package-specs")
projectPaths = [temp.mkdirSync("dir1-"), temp.mkdirSync("dir2-")]
atom.project.setPaths(projectPaths)
# No active item. Use first project directory.
atom.commands.dispatch(workspaceElement, "window:run-package-specs")
expect(ipc.send).toHaveBeenCalledWith("run-package-specs", path.join(projectPaths[0], "spec"))
ipc.send.reset()
expect(ipcRenderer.send).toHaveBeenCalledWith("run-package-specs", path.join(projectPaths[0], "spec"))
ipcRenderer.send.reset()
# Active item doesn't implement ::getPath(). Use first project directory.
item = document.createElement("div")
atom.workspace.getActivePane().activateItem(item)
atom.commands.dispatch(workspaceElement, "window:run-package-specs")
expect(ipc.send).toHaveBeenCalledWith("run-package-specs", path.join(projectPaths[0], "spec"))
ipc.send.reset()
expect(ipcRenderer.send).toHaveBeenCalledWith("run-package-specs", path.join(projectPaths[0], "spec"))
ipcRenderer.send.reset()
# Active item has no path. Use first project directory.
item.getPath = -> null
atom.commands.dispatch(workspaceElement, "window:run-package-specs")
expect(ipc.send).toHaveBeenCalledWith("run-package-specs", path.join(projectPaths[0], "spec"))
ipc.send.reset()
expect(ipcRenderer.send).toHaveBeenCalledWith("run-package-specs", path.join(projectPaths[0], "spec"))
ipcRenderer.send.reset()
# Active item has path. Use project path for item path.
item.getPath = -> path.join(projectPaths[1], "a-file.txt")
atom.commands.dispatch(workspaceElement, "window:run-package-specs")
expect(ipc.send).toHaveBeenCalledWith("run-package-specs", path.join(projectPaths[1], "spec"))
ipc.send.reset()
expect(ipcRenderer.send).toHaveBeenCalledWith("run-package-specs", path.join(projectPaths[1], "spec"))
ipcRenderer.send.reset()

View File

@ -585,6 +585,22 @@ describe "Workspace", ->
open = -> workspace.open('file1', workspace.getActivePane())
expect(open).toThrow()
describe "when the file is already open in pending state", ->
it "should terminate the pending state", ->
editor = null
waitsForPromise ->
atom.workspace.open('sample.js', pending: true).then (o) -> editor = o
runs ->
expect(editor.isPending()).toBe true
waitsForPromise ->
atom.workspace.open('sample.js').then (o) -> editor = o
runs ->
expect(editor.isPending()).toBe false
describe "::reopenItem()", ->
it "opens the uri associated with the last closed pane that isn't currently open", ->
pane = workspace.getActivePane()
@ -1532,3 +1548,14 @@ describe "Workspace", ->
atom.workspace.closeActivePaneItemOrEmptyPaneOrWindow()
expect(atom.close).toHaveBeenCalled()
describe "when the core.allowPendingPaneItems option is falsey", ->
it "does not open item with `pending: true` option as pending", ->
editor = null
atom.config.set('core.allowPendingPaneItems', false)
waitsForPromise ->
atom.workspace.open('sample.js', pending: true).then (o) -> editor = o
runs ->
expect(editor.isPending()).toBeFalsy()

View File

@ -1,69 +1,67 @@
_ = require 'underscore-plus'
ipc = require 'ipc'
remote = require 'remote'
shell = require 'shell'
webFrame = require 'web-frame'
{ipcRenderer, remote, shell, webFrame} = require 'electron'
ipcHelpers = require './ipc-helpers'
{Disposable} = require 'event-kit'
{getWindowLoadSettings, setWindowLoadSettings} = require './window-load-settings-helpers'
module.exports =
class ApplicationDelegate
open: (params) ->
ipc.send('open', params)
ipcRenderer.send('open', params)
pickFolder: (callback) ->
responseChannel = "atom-pick-folder-response"
ipc.on responseChannel, (path) ->
ipc.removeAllListeners(responseChannel)
ipcRenderer.on responseChannel, (event, path) ->
ipcRenderer.removeAllListeners(responseChannel)
callback(path)
ipc.send("pick-folder", responseChannel)
ipcRenderer.send("pick-folder", responseChannel)
getCurrentWindow: ->
remote.getCurrentWindow()
closeWindow: ->
ipc.send("call-window-method", "close")
ipcRenderer.send("call-window-method", "close")
getWindowSize: ->
[width, height] = remote.getCurrentWindow().getSize()
{width, height}
setWindowSize: (width, height) ->
remote.getCurrentWindow().setSize(width, height)
ipcHelpers.call('set-window-size', width, height)
getWindowPosition: ->
[x, y] = remote.getCurrentWindow().getPosition()
{x, y}
setWindowPosition: (x, y) ->
ipc.send("call-window-method", "setPosition", x, y)
ipcHelpers.call('set-window-position', x, y)
centerWindow: ->
ipc.send("call-window-method", "center")
ipcHelpers.call('center-window')
focusWindow: ->
ipc.send("call-window-method", "focus")
ipcHelpers.call('focus-window')
showWindow: ->
ipc.send("call-window-method", "show")
ipcHelpers.call('show-window')
hideWindow: ->
ipc.send("call-window-method", "hide")
ipcHelpers.call('hide-window')
restartWindow: ->
ipc.send("call-window-method", "restart")
reloadWindow: ->
ipcRenderer.send("call-window-method", "reload")
isWindowMaximized: ->
remote.getCurrentWindow().isMaximized()
maximizeWindow: ->
ipc.send("call-window-method", "maximize")
ipcRenderer.send("call-window-method", "maximize")
isWindowFullScreen: ->
remote.getCurrentWindow().isFullScreen()
setWindowFullScreen: (fullScreen=false) ->
ipc.send("call-window-method", "setFullScreen", fullScreen)
ipcRenderer.send("call-window-method", "setFullScreen", fullScreen)
openWindowDevTools: ->
new Promise (resolve) ->
@ -75,7 +73,7 @@ class ApplicationDelegate
resolve()
else
remote.getCurrentWindow().once("devtools-opened", -> resolve())
ipc.send("call-window-method", "openDevTools")
ipcRenderer.send("call-window-method", "openDevTools")
closeWindowDevTools: ->
new Promise (resolve) ->
@ -87,7 +85,7 @@ class ApplicationDelegate
resolve()
else
remote.getCurrentWindow().once("devtools-closed", -> resolve())
ipc.send("call-window-method", "closeDevTools")
ipcRenderer.send("call-window-method", "closeDevTools")
toggleWindowDevTools: ->
new Promise (resolve) =>
@ -101,16 +99,16 @@ class ApplicationDelegate
@openWindowDevTools().then(resolve)
executeJavaScriptInWindowDevTools: (code) ->
ipc.send("call-window-method", "executeJavaScriptInDevTools", code)
ipcRenderer.send("execute-javascript-in-dev-tools", code)
setWindowDocumentEdited: (edited) ->
ipc.send("call-window-method", "setDocumentEdited", edited)
ipcRenderer.send("call-window-method", "setDocumentEdited", edited)
setRepresentedFilename: (filename) ->
ipc.send("call-window-method", "setRepresentedFilename", filename)
ipcRenderer.send("call-window-method", "setRepresentedFilename", filename)
addRecentDocument: (filename) ->
ipc.send("add-recent-document", filename)
ipcRenderer.send("add-recent-document", filename)
setRepresentedDirectoryPaths: (paths) ->
loadSettings = getWindowLoadSettings()
@ -118,14 +116,13 @@ class ApplicationDelegate
setWindowLoadSettings(loadSettings)
setAutoHideWindowMenuBar: (autoHide) ->
ipc.send("call-window-method", "setAutoHideMenuBar", autoHide)
ipcRenderer.send("call-window-method", "setAutoHideMenuBar", autoHide)
setWindowMenuBarVisibility: (visible) ->
remote.getCurrentWindow().setMenuBarVisibility(visible)
getPrimaryDisplayWorkAreaSize: ->
screen = remote.require 'screen'
screen.getPrimaryDisplay().workAreaSize
remote.screen.getPrimaryDisplay().workAreaSize
confirm: ({message, detailedMessage, buttons}) ->
buttons ?= {}
@ -134,8 +131,7 @@ class ApplicationDelegate
else
buttonLabels = Object.keys(buttons)
dialog = remote.require('dialog')
chosen = dialog.showMessageBox(remote.getCurrentWindow(), {
chosen = remote.dialog.showMessageBox(remote.getCurrentWindow(), {
type: 'info'
message: message
detail: detailedMessage
@ -157,42 +153,47 @@ class ApplicationDelegate
params = _.clone(params)
params.title ?= 'Save File'
params.defaultPath ?= getWindowLoadSettings().initialPaths[0]
dialog = remote.require('dialog')
dialog.showSaveDialog remote.getCurrentWindow(), params
remote.dialog.showSaveDialog remote.getCurrentWindow(), params
playBeepSound: ->
shell.beep()
onDidOpenLocations: (callback) ->
outerCallback = (message, detail) ->
outerCallback = (event, message, detail) ->
if message is 'open-locations'
callback(detail)
ipc.on('message', outerCallback)
ipcRenderer.on('message', outerCallback)
new Disposable ->
ipc.removeListener('message', outerCallback)
ipcRenderer.removeListener('message', outerCallback)
onUpdateAvailable: (callback) ->
outerCallback = (message, detail) ->
outerCallback = (event, message, detail) ->
if message is 'update-available'
callback(detail)
ipc.on('message', outerCallback)
ipcRenderer.on('message', outerCallback)
new Disposable ->
ipc.removeListener('message', outerCallback)
ipcRenderer.removeListener('message', outerCallback)
onApplicationMenuCommand: (callback) ->
ipc.on('command', callback)
outerCallback = (event, args...) ->
callback(args...)
ipcRenderer.on('command', outerCallback)
new Disposable ->
ipc.removeListener('command', callback)
ipcRenderer.removeListener('command', outerCallback)
onContextMenuCommand: (callback) ->
ipc.on('context-command', callback)
outerCallback = (event, args...) ->
callback(args...)
ipcRenderer.on('context-command', outerCallback)
new Disposable ->
ipc.removeListener('context-command', callback)
ipcRenderer.removeListener('context-command', outerCallback)
didCancelWindowUnload: ->
ipc.send('did-cancel-window-unload')
ipcRenderer.send('did-cancel-window-unload')
openExternal: (url) ->
shell.openExternal(url)

View File

@ -1,16 +1,16 @@
crypto = require 'crypto'
path = require 'path'
ipc = require 'ipc'
{ipcRenderer} = require 'electron'
_ = require 'underscore-plus'
{deprecate} = require 'grim'
{CompositeDisposable, Emitter} = require 'event-kit'
{CompositeDisposable, Disposable, Emitter} = require 'event-kit'
fs = require 'fs-plus'
{mapSourcePosition} = require 'source-map-support'
Model = require './model'
WindowEventHandler = require './window-event-handler'
StylesElement = require './styles-element'
StorageFolder = require './storage-folder'
StateStore = require './state-store'
{getWindowLoadSettings, setWindowLoadSettings} = require './window-load-settings-helpers'
registerDefaultCommands = require './register-default-commands'
@ -111,6 +111,8 @@ class AtomEnvironment extends Model
# Public: A {Workspace} instance
workspace: null
saveStateDebounceInterval: 1000
###
Section: Construction and Destruction
###
@ -119,14 +121,16 @@ class AtomEnvironment extends Model
constructor: (params={}) ->
{@blobStore, @applicationDelegate, @window, @document, configDirPath, @enablePersistence, onlyLoadBaseStyleSheets} = params
@state = {version: @constructor.version}
@loadTime = null
{devMode, safeMode, resourcePath} = @getLoadSettings()
{devMode, safeMode, resourcePath, clearWindowState} = @getLoadSettings()
@emitter = new Emitter
@disposables = new CompositeDisposable
@stateStore = new StateStore('AtomEnvironments', 1)
@stateStore.clear() if clearWindowState
@deserializers = new DeserializerManager(this)
@deserializeTimings = {}
@ -200,19 +204,28 @@ class AtomEnvironment extends Model
@registerDefaultViewProviders()
@installUncaughtErrorHandler()
@attachSaveStateListeners()
@installWindowEventHandler()
@observeAutoHideMenuBar()
checkPortableHomeWritable = ->
responseChannel = "check-portable-home-writable-response"
ipc.on responseChannel, (response) ->
ipc.removeAllListeners(responseChannel)
ipcRenderer.on responseChannel, (event, response) ->
ipcRenderer.removeAllListeners(responseChannel)
atom.notifications.addWarning("#{response.message.replace(/([\\\.+\\-_#!])/g, '\\$1')}") if not response.writable
ipc.send('check-portable-home-writable', responseChannel)
ipcRenderer.send('check-portable-home-writable', responseChannel)
checkPortableHomeWritable()
attachSaveStateListeners: ->
debouncedSaveState = _.debounce((=> @saveState()), @saveStateDebounceInterval)
@document.addEventListener('mousedown', debouncedSaveState, true)
@document.addEventListener('keydown', debouncedSaveState, true)
@disposables.add new Disposable =>
@document.removeEventListener('mousedown', debouncedSaveState, true)
@document.removeEventListener('keydown', debouncedSaveState, true)
setConfigSchema: ->
@config.setSchema null, {type: 'object', properties: _.clone(require('./config-schema'))}
@ -302,9 +315,6 @@ class AtomEnvironment extends Model
@views.clear()
@registerDefaultViewProviders()
@state.packageStates = {}
delete @state.workspace
destroy: ->
return if not @project
@ -497,7 +507,7 @@ class AtomEnvironment extends Model
# Extended: Reload the current window.
reload: ->
@applicationDelegate.restartWindow()
@applicationDelegate.reloadWindow()
# Extended: Returns a {Boolean} that is `true` if the current window is maximized.
isMaximized: ->
@ -524,16 +534,18 @@ class AtomEnvironment extends Model
# Restore the window to its previous dimensions and show it.
#
# Also restores the full screen and maximized state on the next tick to
# Restores the full screen and maximized state after the window has resized to
# prevent resize glitches.
displayWindow: ->
dimensions = @restoreWindowDimensions()
@show()
@focus()
setImmediate =>
@setFullScreen(true) if @workspace?.fullScreen
@maximize() if dimensions?.maximized and process.platform isnt 'darwin'
@restoreWindowDimensions().then (dimensions) =>
steps = [
@restoreWindowBackground(),
@show(),
@focus()
]
steps.push(@setFullScreen(true)) if @workspace.fullScreen
steps.push(@maximize()) if dimensions?.maximized and process.platform isnt 'darwin'
Promise.all(steps)
if @isFirstLoad()
loadSettings = getWindowLoadSettings()
@ -566,12 +578,14 @@ class AtomEnvironment extends Model
# * `width` The new width.
# * `height` The new height.
setWindowDimensions: ({x, y, width, height}) ->
steps = []
if width? and height?
@setSize(width, height)
steps.push(@setSize(width, height))
if x? and y?
@setPosition(x, y)
steps.push(@setPosition(x, y))
else
@center()
steps.push(@center())
Promise.all(steps)
# Returns true if the dimensions are useable, false if they should be ignored.
# Work around for https://github.com/atom/atom-shell/issues/473
@ -607,16 +621,22 @@ class AtomEnvironment extends Model
# But after that, e.g., when the window's been reloaded, we want to use the
# dimensions we've saved for it.
if not @isFirstLoad()
dimensions = @state.windowDimensions
dimensions = @windowDimensions
unless @isValidDimensions(dimensions)
dimensions = @getDefaultWindowDimensions()
@setWindowDimensions(dimensions)
dimensions
@setWindowDimensions(dimensions).then -> dimensions
storeWindowDimensions: ->
dimensions = @getWindowDimensions()
@state.windowDimensions = dimensions if @isValidDimensions(dimensions)
@windowDimensions = dimensions if @isValidDimensions(dimensions)
restoreWindowBackground: ->
if backgroundColor = window.localStorage.getItem('atom:window-background-color')
@backgroundStylesheet = document.createElement('style')
@backgroundStylesheet.type = 'text/css'
@backgroundStylesheet.innerText = 'html, body { background: ' + backgroundColor + ' !important; }'
document.head.appendChild(@backgroundStylesheet)
storeWindowBackground: ->
return if @inSpecMode()
@ -642,6 +662,7 @@ class AtomEnvironment extends Model
@packages.loadPackages()
@document.body.appendChild(@views.getView(@workspace))
@backgroundStylesheet?.remove()
@watchProjectPath()
@ -653,17 +674,20 @@ class AtomEnvironment extends Model
@openInitialEmptyEditorIfNecessary()
serialize: ->
version: @constructor.version
project: @project.serialize()
workspace: @workspace.serialize()
packageStates: @packages.serialize()
grammars: {grammarOverridesByPath: @grammars.grammarOverridesByPath}
fullScreen: @isFullScreen()
windowDimensions: @windowDimensions
unloadEditorWindow: ->
return if not @project
@storeWindowBackground()
@state.grammars = {grammarOverridesByPath: @grammars.grammarOverridesByPath}
@state.project = @project.serialize()
@state.workspace = @workspace.serialize()
@packages.deactivatePackages()
@state.packageStates = @packages.packageStates
@state.fullScreen = @isFullScreen()
@saveStateSync()
@saveBlobStoreSync()
openInitialEmptyEditorIfNecessary: ->
@ -797,45 +821,54 @@ class AtomEnvironment extends Model
@blobStore.save()
saveStateSync: ->
return unless @enablePersistence
saveState: ->
return Promise.resolve() unless @enablePersistence
state = @serialize()
if storageKey = @getStateKey(@project?.getPaths())
@getStorageFolder().store(storageKey, @state)
@stateStore.save(storageKey, state)
else
@getCurrentWindow().loadSettings.windowState = JSON.stringify(@state)
@getCurrentWindow().loadSettings.windowState = JSON.stringify(state)
Promise.resolve()
loadStateSync: ->
return unless @enablePersistence
loadState: ->
return Promise.resolve() unless @enablePersistence
startTime = Date.now()
statePromise = null
if stateKey = @getStateKey(@getLoadSettings().initialPaths)
if state = @getStorageFolder().load(stateKey)
@state = state
statePromise = @stateStore.load(stateKey)
if not @state? and windowState = @getLoadSettings().windowState
if not statePromise? and windowState = @getLoadSettings().windowState
try
if state = JSON.parse(@getLoadSettings().windowState)
@state = state
statePromise = Promise.resolve(JSON.parse(@getLoadSettings().windowState))
catch error
console.warn "Error parsing window state: #{statePath} #{error.stack}", error
@deserializeTimings.atom = Date.now() - startTime
if statePromise?
statePromise.then (state) =>
@deserializeTimings.atom = Date.now() - startTime
@deserialize(state) if state?
else
Promise.resolve()
if grammarOverridesByPath = @state.grammars?.grammarOverridesByPath
deserialize: (state) ->
if grammarOverridesByPath = state.grammars?.grammarOverridesByPath
@grammars.grammarOverridesByPath = grammarOverridesByPath
@setFullScreen(@state.fullScreen)
@setFullScreen(state.fullScreen)
@packages.packageStates = @state.packageStates ? {}
@windowDimensions = state.windowDimensions if state.windowDimensions
@packages.packageStates = state.packageStates ? {}
startTime = Date.now()
@project.deserialize(@state.project, @deserializers) if @state.project?
@project.deserialize(state.project, @deserializers) if state.project?
@deserializeTimings.project = Date.now() - startTime
startTime = Date.now()
@workspace.deserialize(@state.workspace, @deserializers) if @state.workspace?
@workspace.deserialize(state.workspace, @deserializers) if state.workspace?
@deserializeTimings.workspace = Date.now() - startTime
getStateKey: (paths) ->
@ -848,9 +881,6 @@ class AtomEnvironment extends Model
getConfigDirPath: ->
@configDirPath ?= process.env.ATOM_HOME
getStorageFolder: ->
@storageFolder ?= new StorageFolder(@getConfigDirPath())
getUserInitScriptPath: ->
initScriptPath = fs.resolve(@getConfigDirPath(), 'init', ['js', 'coffee'])
initScriptPath ? path.join(@getConfigDirPath(), 'init.coffee')

View File

@ -1,6 +1,4 @@
app = require 'app'
ipc = require 'ipc'
Menu = require 'menu'
{app, Menu} = require 'electron'
_ = require 'underscore-plus'
# Used to manage the global application menu.

View File

@ -2,14 +2,10 @@ AtomWindow = require './atom-window'
ApplicationMenu = require './application-menu'
AtomProtocolHandler = require './atom-protocol-handler'
AutoUpdateManager = require './auto-update-manager'
BrowserWindow = require 'browser-window'
StorageFolder = require '../storage-folder'
Menu = require 'menu'
app = require 'app'
dialog = require 'dialog'
shell = require 'shell'
ipcHelpers = require '../ipc-helpers'
{BrowserWindow, Menu, app, dialog, ipcMain, shell} = require 'electron'
fs = require 'fs-plus'
ipc = require 'ipc'
path = require 'path'
os = require 'os'
net = require 'net'
@ -51,7 +47,7 @@ class AtomApplication
client = net.connect {path: options.socketPath}, ->
client.write JSON.stringify(options), ->
client.end()
app.terminate()
app.quit()
client.on 'error', createAtomApplication
@ -65,7 +61,7 @@ class AtomApplication
exit: (status) -> app.exit(status)
constructor: (options) ->
{@resourcePath, @devResourcePath, @version, @devMode, @safeMode, @socketPath, timeout} = options
{@resourcePath, @devResourcePath, @version, @devMode, @safeMode, @socketPath, timeout, clearWindowState} = options
@socketPath = null if options.test
@ -89,16 +85,16 @@ class AtomApplication
else
@loadState(options) or @openPath(options)
openWithOptions: ({pathsToOpen, executedFrom, urlsToOpen, test, pidToKillWhenClosed, devMode, safeMode, newWindow, logFile, profileStartup, timeout}) ->
openWithOptions: ({pathsToOpen, executedFrom, urlsToOpen, test, pidToKillWhenClosed, devMode, safeMode, newWindow, logFile, profileStartup, timeout, clearWindowState}) ->
if test
@runTests({headless: true, devMode, @resourcePath, executedFrom, pathsToOpen, logFile, timeout})
else if pathsToOpen.length > 0
@openPaths({pathsToOpen, executedFrom, pidToKillWhenClosed, newWindow, devMode, safeMode, profileStartup})
@openPaths({pathsToOpen, executedFrom, pidToKillWhenClosed, newWindow, devMode, safeMode, profileStartup, clearWindowState})
else if urlsToOpen.length > 0
@openUrl({urlToOpen, devMode, safeMode}) for urlToOpen in urlsToOpen
else
# Always open a editor window if this is the first instance of Atom.
@openPath({pidToKillWhenClosed, newWindow, devMode, safeMode, profileStartup})
@openPath({pidToKillWhenClosed, newWindow, devMode, safeMode, profileStartup, clearWindowState})
# Public: Removes the {AtomWindow} from the global window list.
removeWindow: (window) ->
@ -212,7 +208,6 @@ class AtomApplication
@openPathOnEvent('application:open-license', path.join(process.resourcesPath, 'LICENSE.md'))
app.on 'before-quit', =>
@saveState(false)
@quitting = true
app.on 'will-quit', =>
@ -232,7 +227,7 @@ class AtomApplication
@emit('application:new-window')
# A request from the associated render process to open a new render process.
ipc.on 'open', (event, options) =>
ipcMain.on 'open', (event, options) =>
window = @windowForEvent(event)
if options?
if typeof options.pathsToOpen is 'string'
@ -245,44 +240,65 @@ class AtomApplication
else
@promptForPathToOpen('all', {window})
ipc.on 'update-application-menu', (event, template, keystrokesByCommand) =>
ipcMain.on 'update-application-menu', (event, template, keystrokesByCommand) =>
win = BrowserWindow.fromWebContents(event.sender)
@applicationMenu.update(win, template, keystrokesByCommand)
ipc.on 'run-package-specs', (event, packageSpecPath) =>
ipcMain.on 'run-package-specs', (event, packageSpecPath) =>
@runTests({resourcePath: @devResourcePath, pathsToOpen: [packageSpecPath], headless: false})
ipc.on 'command', (event, command) =>
ipcMain.on 'command', (event, command) =>
@emit(command)
ipc.on 'window-command', (event, command, args...) ->
ipcMain.on 'window-command', (event, command, args...) ->
win = BrowserWindow.fromWebContents(event.sender)
win.emit(command, args...)
ipc.on 'call-window-method', (event, method, args...) ->
ipcMain.on 'call-window-method', (event, method, args...) ->
win = BrowserWindow.fromWebContents(event.sender)
win[method](args...)
ipc.on 'pick-folder', (event, responseChannel) =>
ipcMain.on 'pick-folder', (event, responseChannel) =>
@promptForPath "folder", (selectedPaths) ->
event.sender.send(responseChannel, selectedPaths)
ipc.on 'did-cancel-window-unload', =>
ipcHelpers.respondTo 'set-window-size', (win, width, height) ->
win.setSize(width, height)
ipcHelpers.respondTo 'set-window-position', (win, x, y) ->
win.setPosition(x, y)
ipcHelpers.respondTo 'center-window', (win) ->
win.center()
ipcHelpers.respondTo 'focus-window', (win) ->
win.focus()
ipcHelpers.respondTo 'show-window', (win) ->
win.show()
ipcHelpers.respondTo 'hide-window', (win) ->
win.hide()
ipcMain.on 'did-cancel-window-unload', =>
@quitting = false
clipboard = require '../safe-clipboard'
ipc.on 'write-text-to-selection-clipboard', (event, selectedText) ->
ipcMain.on 'write-text-to-selection-clipboard', (event, selectedText) ->
clipboard.writeText(selectedText, 'selection')
ipc.on 'write-to-stdout', (event, output) ->
ipcMain.on 'write-to-stdout', (event, output) ->
process.stdout.write(output)
ipc.on 'write-to-stderr', (event, output) ->
ipcMain.on 'write-to-stderr', (event, output) ->
process.stderr.write(output)
ipc.on 'add-recent-document', (event, filename) ->
ipcMain.on 'add-recent-document', (event, filename) ->
app.addRecentDocument(filename)
ipcMain.on 'execute-javascript-in-dev-tools', (event, code) ->
event.sender.devToolsWebContents?.executeJavaScript(code)
setupDockMenu: ->
if process.platform is 'darwin'
dockMenu = Menu.buildFromTemplate [
@ -350,7 +366,7 @@ class AtomApplication
_.find @windows, (atomWindow) ->
atomWindow.devMode is devMode and atomWindow.containsPaths(pathsToOpen)
# Returns the {AtomWindow} for the given ipc event.
# Returns the {AtomWindow} for the given ipcMain event.
windowForEvent: ({sender}) ->
window = BrowserWindow.fromWebContents(sender)
_.find @windows, ({browserWindow}) -> window is browserWindow
@ -387,8 +403,8 @@ class AtomApplication
# :safeMode - Boolean to control the opened window's safe mode.
# :profileStartup - Boolean to control creating a profile of the startup time.
# :window - {AtomWindow} to open file paths in.
openPath: ({pathToOpen, pidToKillWhenClosed, newWindow, devMode, safeMode, profileStartup, window} = {}) ->
@openPaths({pathsToOpen: [pathToOpen], pidToKillWhenClosed, newWindow, devMode, safeMode, profileStartup, window})
openPath: ({pathToOpen, pidToKillWhenClosed, newWindow, devMode, safeMode, profileStartup, window, clearWindowState} = {}) ->
@openPaths({pathsToOpen: [pathToOpen], pidToKillWhenClosed, newWindow, devMode, safeMode, profileStartup, window, clearWindowState})
# Public: Opens multiple paths, in existing windows if possible.
#
@ -400,9 +416,10 @@ class AtomApplication
# :safeMode - Boolean to control the opened window's safe mode.
# :windowDimensions - Object with height and width keys.
# :window - {AtomWindow} to open file paths in.
openPaths: ({pathsToOpen, executedFrom, pidToKillWhenClosed, newWindow, devMode, safeMode, windowDimensions, profileStartup, window}={}) ->
openPaths: ({pathsToOpen, executedFrom, pidToKillWhenClosed, newWindow, devMode, safeMode, windowDimensions, profileStartup, window, clearWindowState}={}) ->
devMode = Boolean(devMode)
safeMode = Boolean(safeMode)
clearWindowState = Boolean(clearWindowState)
locationsToOpen = (@locationForPathToOpen(pathToOpen, executedFrom) for pathToOpen in pathsToOpen)
pathsToOpen = (locationToOpen.pathToOpen for locationToOpen in locationsToOpen)
@ -435,7 +452,7 @@ class AtomApplication
windowInitializationScript ?= require.resolve('../initialize-application-window')
resourcePath ?= @resourcePath
windowDimensions ?= @getDimensionsForNewWindow()
openedWindow = new AtomWindow({locationsToOpen, windowInitializationScript, resourcePath, devMode, safeMode, windowDimensions, profileStartup})
openedWindow = new AtomWindow({locationsToOpen, windowInitializationScript, resourcePath, devMode, safeMode, windowDimensions, profileStartup, clearWindowState})
if pidToKillWhenClosed?
@pidsToOpenWindows[pidToKillWhenClosed] = openedWindow
@ -472,7 +489,7 @@ class AtomApplication
if loadSettings = window.getLoadSettings()
states.push(initialPaths: loadSettings.initialPaths)
if states.length > 0 or allowEmpty
@storageFolder.store('application.json', states)
@storageFolder.storeSync('application.json', states)
loadState: (options) ->
if (states = @storageFolder.load('application.json'))?.length > 0

View File

@ -1,6 +1,6 @@
fs = require 'fs-plus'
path = require 'path'
ipc = require 'ipc'
{ipcMain} = require 'electron'
module.exports =
class AtomPortable
@ -30,6 +30,6 @@ class AtomPortable
catch error
message = "Failed to use portable Atom home directory (#{@getPortableAtomHomePath()}). Using the default instead (#{defaultHome}). #{error.message}"
ipc.on 'check-portable-home-writable', (event) ->
ipcMain.on 'check-portable-home-writable', (event) ->
event.sender.send 'check-portable-home-writable-response', {writable, message}
writable

View File

@ -1,7 +1,6 @@
app = require 'app'
{app, protocol} = require 'electron'
fs = require 'fs'
path = require 'path'
protocol = require 'protocol'
# Handles requests with 'atom' protocol.
#

View File

@ -1,6 +1,4 @@
BrowserWindow = require 'browser-window'
app = require 'app'
dialog = require 'dialog'
{BrowserWindow, app, dialog} = require 'electron'
path = require 'path'
fs = require 'fs'
url = require 'url'
@ -50,6 +48,7 @@ class AtomWindow
loadSettings.safeMode ?= false
loadSettings.atomHome = process.env.ATOM_HOME
loadSettings.firstLoad = true
loadSettings.clearWindowState ?= false
# Only send to the first non-spec window created
if @constructor.includeShellLoadTime and not @isSpec
@ -82,7 +81,7 @@ class AtomWindow
loadSettings = _.clone(loadSettingsObj)
delete loadSettings['windowState']
@browserWindow.loadUrl url.format
@browserWindow.loadURL url.format
protocol: 'file'
pathname: "#{@resourcePath}/static/index.html"
slashes: true
@ -90,7 +89,7 @@ class AtomWindow
getLoadSettings: ->
if @browserWindow.webContents? and not @browserWindow.webContents.isLoading()
hash = url.parse(@browserWindow.webContents.getUrl()).hash.substr(1)
hash = url.parse(@browserWindow.webContents.getURL()).hash.substr(1)
JSON.parse(decodeURIComponent(hash))
hasProjectPath: -> @getLoadSettings().initialPaths?.length > 0
@ -122,6 +121,9 @@ class AtomWindow
false
handleEvents: ->
@browserWindow.on 'close', ->
global.atomApplication.saveState(false)
@browserWindow.on 'closed', =>
global.atomApplication.removeWindow(this)
@ -145,10 +147,10 @@ class AtomWindow
detail: 'Please report this issue to https://github.com/atom/atom'
switch chosen
when 0 then @browserWindow.destroy()
when 1 then @browserWindow.restart()
when 1 then @browserWindow.reload()
@browserWindow.webContents.on 'will-navigate', (event, url) =>
unless url is @browserWindow.webContents.getUrl()
unless url is @browserWindow.webContents.getURL()
event.preventDefault()
@setupContextMenu()
@ -221,6 +223,6 @@ class AtomWindow
isSpecWindow: -> @isSpec
reload: -> @browserWindow.restart()
reload: -> @browserWindow.reload()
toggleDevTools: -> @browserWindow.toggleDevTools()

View File

@ -29,13 +29,13 @@ class AutoUpdateManager
if process.platform is 'win32'
autoUpdater = require './auto-updater-win32'
else
autoUpdater = require 'auto-updater'
{autoUpdater} = require 'electron'
autoUpdater.on 'error', (event, message) =>
@setState(ErrorState)
console.error "Error Downloading Update: #{message}"
autoUpdater.setFeedUrl @feedUrl
autoUpdater.setFeedURL @feedUrl
autoUpdater.on 'checking-for-update', =>
@setState(CheckingState)
@ -104,7 +104,7 @@ class AutoUpdateManager
onUpdateNotAvailable: =>
autoUpdater.removeListener 'error', @onUpdateError
dialog = require 'dialog'
{dialog} = require 'electron'
dialog.showMessageBox
type: 'info'
buttons: ['OK']
@ -115,7 +115,7 @@ class AutoUpdateManager
onUpdateError: (event, message) =>
autoUpdater.removeListener 'update-not-available', @onUpdateNotAvailable
dialog = require 'dialog'
{dialog} = require 'electron'
dialog.showMessageBox
type: 'warning'
buttons: ['OK']

View File

@ -5,13 +5,13 @@ SquirrelUpdate = require './squirrel-update'
class AutoUpdater
_.extend @prototype, EventEmitter.prototype
setFeedUrl: (@updateUrl) ->
setFeedURL: (@updateUrl) ->
quitAndInstall: ->
if SquirrelUpdate.existsSync()
SquirrelUpdate.restartAtom(require('app'))
SquirrelUpdate.restartAtom(require('electron').app)
else
require('auto-updater').quitAndInstall()
require('electron').autoUpdater.quitAndInstall()
downloadUpdate: (callback) ->
SquirrelUpdate.spawn ['--download', @updateUrl], (error, stdout) ->

View File

@ -1,4 +1,4 @@
Menu = require 'menu'
{Menu} = require 'electron'
module.exports =
class ContextMenu

View File

@ -4,8 +4,7 @@ process.on 'uncaughtException', (error={}) ->
console.log(error.message) if error.message?
console.log(error.stack) if error.stack?
crashReporter = require 'crash-reporter'
app = require 'app'
{crashReporter, app} = require 'electron'
fs = require 'fs-plus'
path = require 'path'
yargs = require 'yargs'
@ -32,6 +31,9 @@ start = ->
app.on 'open-url', addUrlToOpen
app.on 'will-finish-launching', setupCrashReporter
if args.userDataDir?
app.setPath('userData', args.userDataDir)
app.on 'ready', ->
app.removeListener 'open-file', addPathToOpen
app.removeListener 'open-url', addUrlToOpen
@ -54,12 +56,12 @@ handleStartupEventWithSquirrel = ->
SquirrelUpdate.handleStartupEvent(app, squirrelCommand)
setupCrashReporter = ->
crashReporter.start(productName: 'Atom', companyName: 'GitHub')
crashReporter.start(productName: 'Atom', companyName: 'GitHub', submitURL: 'http://54.249.141.255:1127/post')
setupAtomHome = ({setPortable}) ->
return if process.env.ATOM_HOME
atomHome = path.join(app.getHomeDir(), '.atom')
atomHome = path.join(app.getPath('home'), '.atom')
AtomPortable = require './atom-portable'
if setPortable and not AtomPortable.isPortableInstall(process.platform, process.env.ATOM_HOME, atomHome)
@ -119,6 +121,8 @@ parseCommandLine = ->
options.alias('v', 'version').boolean('v').describe('v', 'Print the version.')
options.alias('w', 'wait').boolean('w').describe('w', 'Wait for window to be closed before returning.')
options.string('socket-path')
options.string('user-data-dir')
options.boolean('clear-window-state').describe('clear-window-state', 'Delete all Atom environment state.')
args = options.argv
@ -140,9 +144,11 @@ parseCommandLine = ->
pidToKillWhenClosed = args['pid'] if args['wait']
logFile = args['log-file']
socketPath = args['socket-path']
userDataDir = args['user-data-dir']
profileStartup = args['profile-startup']
clearWindowState = args['clear-window-state']
urlsToOpen = []
devResourcePath = process.env.ATOM_DEV_RESOURCE_PATH ? path.join(app.getHomeDir(), 'github', 'atom')
devResourcePath = process.env.ATOM_DEV_RESOURCE_PATH ? path.join(app.getPath('home'), 'github', 'atom')
setPortable = args.portable
if args['resource-path']
@ -164,6 +170,7 @@ parseCommandLine = ->
{resourcePath, devResourcePath, pathsToOpen, urlsToOpen, executedFrom, test,
version, pidToKillWhenClosed, devMode, safeMode, newWindow,
logFile, socketPath, profileStartup, timeout, setPortable}
logFile, socketPath, userDataDir, profileStartup, timeout, setPortable,
clearWindowState}
start()

View File

@ -20,6 +20,7 @@ else
fileKeyPath = 'HKCU\\Software\\Classes\\*\\shell\\Atom'
directoryKeyPath = 'HKCU\\Software\\Classes\\directory\\shell\\Atom'
backgroundKeyPath = 'HKCU\\Software\\Classes\\directory\\background\\shell\\Atom'
applicationsKeyPath = 'HKCU\\Software\\Classes\\Applications\\atom.exe'
environmentKeyPath = 'HKCU\\Environment'
# Spawn a command and invoke the callback when it completes with an error
@ -64,6 +65,10 @@ installContextMenu = (callback) ->
args.push('/f')
spawnReg(args, callback)
installFileHandler = (callback) ->
args = ["#{applicationsKeyPath}\\shell\\open\\command", '/ve', '/d', "\"#{process.execPath}\" \"%1\""]
addToRegistry(args, callback)
installMenu = (keyPath, arg, callback) ->
args = [keyPath, '/ve', '/d', 'Open with Atom']
addToRegistry args, ->
@ -74,7 +79,8 @@ installContextMenu = (callback) ->
installMenu fileKeyPath, '%1', ->
installMenu directoryKeyPath, '%1', ->
installMenu(backgroundKeyPath, '%V', callback)
installMenu backgroundKeyPath, '%V', ->
installFileHandler(callback)
isAscii = (text) ->
index = 0
@ -124,7 +130,8 @@ uninstallContextMenu = (callback) ->
deleteFromRegistry fileKeyPath, ->
deleteFromRegistry directoryKeyPath, ->
deleteFromRegistry(backgroundKeyPath, callback)
deleteFromRegistry backgroundKeyPath, ->
deleteFromRegistry(applicationsKeyPath, callback)
# Add atom and apm to the PATH
#

View File

@ -108,6 +108,10 @@ module.exports =
description: 'Automatically update Atom when a new release is available.'
type: 'boolean'
default: true
allowPendingPaneItems:
description: 'Allow items to be previewed without adding them to a pane permanently, such as when single clicking files in the tree view.'
type: 'boolean'
default: true
editor:
type: 'object'

View File

@ -4,7 +4,7 @@ CSON = require 'season'
fs = require 'fs-plus'
{calculateSpecificity, validateSelector} = require 'clear-cut'
{Disposable} = require 'event-kit'
remote = require 'remote'
{remote} = require 'electron'
MenuHelpers = require './menu-helpers'
platformContextMenu = require('../package.json')?._atomMenu?['context-menu']

View File

@ -413,6 +413,9 @@ class DisplayBuffer extends Model
isFoldedAtScreenRow: (screenRow) ->
@largestFoldContainingBufferRow(@bufferRowForScreenRow(screenRow))?
isFoldableAtBufferRow: (row) ->
@tokenizedBuffer.isFoldableAtRow(row)
# Destroys the fold with the given id
destroyFoldWithId: (id) ->
@foldsByMarkerId[id]?.destroy()

View File

@ -23,12 +23,12 @@ module.exports = ({blobStore}) ->
enablePersistence: true
})
atom.loadStateSync()
atom.displayWindow()
atom.startEditorWindow()
atom.loadState().then ->
atom.displayWindow().then ->
atom.startEditorWindow()
# Workaround for focus getting cleared upon window creation
windowFocused = ->
window.removeEventListener('focus', windowFocused)
setTimeout (-> document.querySelector('atom-workspace').focus()), 0
window.addEventListener('focus', windowFocused)
# Workaround for focus getting cleared upon window creation
windowFocused = ->
window.removeEventListener('focus', windowFocused)
setTimeout (-> document.querySelector('atom-workspace').focus()), 0
window.addEventListener('focus', windowFocused)

View File

@ -4,17 +4,17 @@ cloneObject = (object) ->
clone
module.exports = ({blobStore}) ->
{crashReporter, remote} = require 'electron'
# Start the crash reporter before anything else.
require('crash-reporter').start(productName: 'Atom', companyName: 'GitHub')
remote = require 'remote'
crashReporter.start(productName: 'Atom', companyName: 'GitHub', submitURL: 'http://54.249.141.255:1127/post')
exitWithStatusCode = (status) ->
remote.require('app').emit('will-quit')
remote.app.emit('will-quit')
remote.process.exit(status)
try
path = require 'path'
ipc = require 'ipc'
{ipcRenderer} = require 'electron'
{getWindowLoadSettings} = require './window-load-settings-helpers'
AtomEnvironment = require '../src/atom-environment'
ApplicationDelegate = require '../src/application-delegate'
@ -29,15 +29,15 @@ module.exports = ({blobStore}) ->
handleKeydown = (event) ->
# Reload: cmd-r / ctrl-r
if (event.metaKey or event.ctrlKey) and event.keyCode is 82
ipc.send('call-window-method', 'restart')
ipcRenderer.send('call-window-method', 'reload')
# Toggle Dev Tools: cmd-alt-i / ctrl-alt-i
if (event.metaKey or event.ctrlKey) and event.altKey and event.keyCode is 73
ipc.send('call-window-method', 'toggleDevTools')
ipcRenderer.send('call-window-method', 'toggleDevTools')
# Reload: cmd-w / ctrl-w
if (event.metaKey or event.ctrlKey) and event.keyCode is 87
ipc.send('call-window-method', 'close')
ipcRenderer.send('call-window-method', 'close')
window.addEventListener('keydown', handleKeydown, true)
@ -68,7 +68,8 @@ module.exports = ({blobStore}) ->
logFile, headless, testPaths, buildAtomEnvironment, buildDefaultApplicationDelegate, legacyTestRunner
})
promise.then(exitWithStatusCode) if getWindowLoadSettings().headless
promise.then (statusCode) ->
exitWithStatusCode(statusCode) if getWindowLoadSettings().headless
catch error
if getWindowLoadSettings().headless
console.error(error.stack ? error)

40
src/ipc-helpers.js Normal file
View File

@ -0,0 +1,40 @@
var ipcRenderer = null
var ipcMain = null
var BrowserWindow = null
exports.call = function (methodName, ...args) {
if (!ipcRenderer) {
ipcRenderer = require('electron').ipcRenderer
}
var responseChannel = getResponseChannel(methodName)
return new Promise(function (resolve) {
ipcRenderer.on(responseChannel, function (event, result) {
ipcRenderer.removeAllListeners(responseChannel)
resolve(result)
})
ipcRenderer.send(methodName, ...args)
})
}
exports.respondTo = function (methodName, callback) {
if (!ipcMain) {
var electron = require('electron')
ipcMain = electron.ipcMain
BrowserWindow = electron.BrowserWindow
}
var responseChannel = getResponseChannel(methodName)
ipcMain.on(methodName, function (event, ...args) {
var browserWindow = BrowserWindow.fromWebContents(event.sender)
var result = callback(browserWindow, ...args)
event.sender.send(responseChannel, result)
})
}
function getResponseChannel (methodName) {
return 'ipc-helpers-' + methodName + '-response'
}

View File

@ -1,7 +1,7 @@
path = require 'path'
_ = require 'underscore-plus'
ipc = require 'ipc'
{ipcRenderer} = require 'electron'
CSON = require 'season'
fs = require 'fs-plus'
{Disposable} = require 'event-kit'
@ -191,7 +191,7 @@ class MenuManager
sendToBrowserProcess: (template, keystrokesByCommand) ->
keystrokesByCommand = @filterMultipleKeystroke(keystrokesByCommand)
ipc.send 'update-application-menu', template, keystrokesByCommand
ipcRenderer.send 'update-application-menu', template, keystrokesByCommand
# Get an {Array} of {String} classes for the given element.
classesForElement: (element) ->

View File

@ -208,7 +208,7 @@ registerBuiltins = (devMode) ->
cache.builtins[builtin] = path.join(commonRoot, "#{builtin}.js")
rendererRoot = path.join(atomShellRoot, 'renderer', 'api', 'lib')
rendererBuiltins = ['ipc', 'remote']
rendererBuiltins = ['ipc-renderer', 'remote']
for builtin in rendererBuiltins
cache.builtins[builtin] = path.join(rendererRoot, "#{builtin}.js")

View File

@ -357,7 +357,9 @@ class PackageManager
packagePaths = @getAvailablePackagePaths()
packagePaths = packagePaths.filter (packagePath) => not @isPackageDisabled(path.basename(packagePath))
packagePaths = _.uniq packagePaths, (packagePath) -> path.basename(packagePath)
@loadPackage(packagePath) for packagePath in packagePaths
@config.transact =>
@loadPackage(packagePath) for packagePath in packagePaths
return
@emitter.emit 'did-load-initial-packages'
loadPackage: (nameOrPath) ->
@ -467,6 +469,14 @@ class PackageManager
return unless hook? and _.isString(hook) and hook.length > 0
@activationHookEmitter.on(hook, callback)
serialize: ->
for pack in @getActivePackages()
@serializePackage(pack)
@packageStates
serializePackage: (pack) ->
@setPackageState(pack.name, state) if state = pack.serialize?()
# Deactivate all packages
deactivatePackages: ->
@config.transact =>
@ -478,8 +488,7 @@ class PackageManager
# Deactivate the package with the given name
deactivatePackage: (name) ->
pack = @getLoadedPackage(name)
if @isPackageActive(name)
@setPackageState(pack.name, state) if state = pack.serialize?()
@serializePackage(pack) if @isPackageActive(pack.name)
pack.deactivate()
delete @activePackages[pack.name]
delete @activatingPackages[pack.name]

View File

@ -1,4 +1,4 @@
ipc = require 'ipc'
{ipcRenderer} = require 'electron'
module.exports = ({commandRegistry, commandInstaller, config}) ->
commandRegistry.add 'atom-workspace',
@ -18,30 +18,30 @@ module.exports = ({commandRegistry, commandInstaller, config}) ->
'window:increase-font-size': -> @getModel().increaseFontSize()
'window:decrease-font-size': -> @getModel().decreaseFontSize()
'window:reset-font-size': -> @getModel().resetFontSize()
'application:about': -> ipc.send('command', 'application:about')
'application:show-preferences': -> ipc.send('command', 'application:show-settings')
'application:show-settings': -> ipc.send('command', 'application:show-settings')
'application:quit': -> ipc.send('command', 'application:quit')
'application:hide': -> ipc.send('command', 'application:hide')
'application:hide-other-applications': -> ipc.send('command', 'application:hide-other-applications')
'application:install-update': -> ipc.send('command', 'application:install-update')
'application:unhide-all-applications': -> ipc.send('command', 'application:unhide-all-applications')
'application:new-window': -> ipc.send('command', 'application:new-window')
'application:new-file': -> ipc.send('command', 'application:new-file')
'application:open': -> ipc.send('command', 'application:open')
'application:open-file': -> ipc.send('command', 'application:open-file')
'application:open-folder': -> ipc.send('command', 'application:open-folder')
'application:open-dev': -> ipc.send('command', 'application:open-dev')
'application:open-safe': -> ipc.send('command', 'application:open-safe')
'application:about': -> ipcRenderer.send('command', 'application:about')
'application:show-preferences': -> ipcRenderer.send('command', 'application:show-settings')
'application:show-settings': -> ipcRenderer.send('command', 'application:show-settings')
'application:quit': -> ipcRenderer.send('command', 'application:quit')
'application:hide': -> ipcRenderer.send('command', 'application:hide')
'application:hide-other-applications': -> ipcRenderer.send('command', 'application:hide-other-applications')
'application:install-update': -> ipcRenderer.send('command', 'application:install-update')
'application:unhide-all-applications': -> ipcRenderer.send('command', 'application:unhide-all-applications')
'application:new-window': -> ipcRenderer.send('command', 'application:new-window')
'application:new-file': -> ipcRenderer.send('command', 'application:new-file')
'application:open': -> ipcRenderer.send('command', 'application:open')
'application:open-file': -> ipcRenderer.send('command', 'application:open-file')
'application:open-folder': -> ipcRenderer.send('command', 'application:open-folder')
'application:open-dev': -> ipcRenderer.send('command', 'application:open-dev')
'application:open-safe': -> ipcRenderer.send('command', 'application:open-safe')
'application:add-project-folder': -> atom.addProjectFolder()
'application:minimize': -> ipc.send('command', 'application:minimize')
'application:zoom': -> ipc.send('command', 'application:zoom')
'application:bring-all-windows-to-front': -> ipc.send('command', 'application:bring-all-windows-to-front')
'application:open-your-config': -> ipc.send('command', 'application:open-your-config')
'application:open-your-init-script': -> ipc.send('command', 'application:open-your-init-script')
'application:open-your-keymap': -> ipc.send('command', 'application:open-your-keymap')
'application:open-your-snippets': -> ipc.send('command', 'application:open-your-snippets')
'application:open-your-stylesheet': -> ipc.send('command', 'application:open-your-stylesheet')
'application:minimize': -> ipcRenderer.send('command', 'application:minimize')
'application:zoom': -> ipcRenderer.send('command', 'application:zoom')
'application:bring-all-windows-to-front': -> ipcRenderer.send('command', 'application:bring-all-windows-to-front')
'application:open-your-config': -> ipcRenderer.send('command', 'application:open-your-config')
'application:open-your-init-script': -> ipcRenderer.send('command', 'application:open-your-init-script')
'application:open-your-keymap': -> ipcRenderer.send('command', 'application:open-your-keymap')
'application:open-your-snippets': -> ipcRenderer.send('command', 'application:open-your-snippets')
'application:open-your-stylesheet': -> ipcRenderer.send('command', 'application:open-your-stylesheet')
'application:open-license': -> @getModel().openLicense()
'window:run-package-specs': -> @runPackageSpecs()
'window:focus-next-pane': -> @getModel().activateNextPane()

View File

@ -1,6 +1,6 @@
# Using clipboard in renderer process is not safe on Linux.
module.exports =
if process.platform is 'linux' and process.type is 'renderer'
require('remote').require('clipboard')
require('electron').remote.clipboard
else
require('clipboard')
require('electron').clipboard

View File

@ -755,7 +755,7 @@ class Selection extends Model
#
# * `otherSelection` A {Selection} to compare against
compare: (otherSelection) ->
@getBufferRange().compare(otherSelection.getBufferRange())
@marker.compare(otherSelection.marker)
###
Section: Private Utilities

91
src/state-store.js Normal file
View File

@ -0,0 +1,91 @@
'use strict'
module.exports =
class StateStore {
constructor (databaseName, version) {
this.dbPromise = new Promise((resolve) => {
let dbOpenRequest = indexedDB.open(databaseName, version)
dbOpenRequest.onupgradeneeded = (event) => {
let db = event.target.result
db.createObjectStore('states')
}
dbOpenRequest.onsuccess = () => {
resolve(dbOpenRequest.result)
}
dbOpenRequest.onerror = (error) => {
console.error('Could not connect to indexedDB', error)
resolve(null)
}
})
}
connect () {
return this.dbPromise.then(db => !!db)
}
save (key, value) {
return this.dbPromise.then(db => {
if (!db) return
return new Promise((resolve, reject) => {
var request = db.transaction(['states'], 'readwrite')
.objectStore('states')
.put({value: value, storedAt: new Date().toString()}, key)
request.onsuccess = resolve
request.onerror = reject
})
})
}
load (key) {
return this.dbPromise.then(db => {
if (!db) return
return new Promise((resolve, reject) => {
var request = db.transaction(['states'])
.objectStore('states')
.get(key)
request.onsuccess = (event) => {
let result = event.target.result
resolve(result ? result.value : null)
}
request.onerror = (event) => reject(event)
})
})
}
clear () {
return this.dbPromise.then(db => {
if (!db) return
return new Promise((resolve, reject) => {
var request = db.transaction(['states'], 'readwrite')
.objectStore('states')
.clear()
request.onsuccess = resolve
request.onerror = reject
})
})
}
count () {
return this.dbPromise.then(db => {
if (!db) return
return new Promise((resolve, reject) => {
var request = db.transaction(['states'])
.objectStore('states')
.count()
request.onsuccess = () => {
resolve(request.result)
}
request.onerror = reject
})
})
}
}

View File

@ -6,7 +6,7 @@ class StorageFolder
constructor: (containingPath) ->
@path = path.join(containingPath, "storage") if containingPath?
store: (name, object) ->
storeSync: (name, object) ->
return unless @path?
fs.writeFileSync(@pathForKey(name), JSON.stringify(object), 'utf8')

View File

@ -2,7 +2,7 @@ _ = require 'underscore-plus'
scrollbarStyle = require 'scrollbar-style'
{Range, Point} = require 'text-buffer'
{CompositeDisposable} = require 'event-kit'
ipc = require 'ipc'
{ipcRenderer} = require 'electron'
TextEditorPresenter = require './text-editor-presenter'
GutterContainerComponent = require './gutter-container-component'
@ -279,10 +279,10 @@ class TextEditorComponent
writeSelectedTextToSelectionClipboard = =>
return if @editor.isDestroyed()
if selectedText = @editor.getSelectedText()
# This uses ipc.send instead of clipboard.writeText because
# clipboard.writeText is a sync ipc call on Linux and that
# This uses ipcRenderer.send instead of clipboard.writeText because
# clipboard.writeText is a sync ipcRenderer call on Linux and that
# will slow down selections.
ipc.send('write-text-to-selection-clipboard', selectedText)
ipcRenderer.send('write-text-to-selection-clipboard', selectedText)
@disposables.add @editor.onDidChangeSelectionRange ->
clearTimeout(timeoutId)
timeoutId = setTimeout(writeSelectedTextToSelectionClipboard)

View File

@ -432,18 +432,14 @@ class TextEditorPresenter
return
updateCursorsState: ->
@state.content.cursors = {}
@updateCursorState(cursor) for cursor in @model.cursors # using property directly to avoid allocation
return
updateCursorState: (cursor) ->
return unless @startRow? and @endRow? and @hasPixelRectRequirements() and @baseCharacterWidth?
screenRange = cursor.getScreenRange()
return unless cursor.isVisible() and @startRow <= screenRange.start.row < @endRow
pixelRect = @pixelRectForScreenRange(screenRange)
pixelRect.width = Math.round(@baseCharacterWidth) if pixelRect.width is 0
@state.content.cursors[cursor.id] = pixelRect
@state.content.cursors = {}
for cursor in @model.cursorsForScreenRowRange(@startRow, @endRow - 1) when cursor.isVisible()
pixelRect = @pixelRectForScreenRange(cursor.getScreenRange())
pixelRect.width = Math.round(@baseCharacterWidth) if pixelRect.width is 0
@state.content.cursors[cursor.id] = pixelRect
return
updateOverlaysState: ->
return unless @hasOverlayPositionRequirements()
@ -603,7 +599,14 @@ class TextEditorPresenter
if endRow > startRow
bufferRows = @model.bufferRowsForScreenRows(startRow, endRow - 1)
previousBufferRow = -1
foldable = false
for bufferRow, i in bufferRows
# don't compute foldability more than once per buffer row
if previousBufferRow isnt bufferRow
foldable = @model.isFoldableAtBufferRow(bufferRow)
previousBufferRow = bufferRow
if bufferRow is lastBufferRow
softWrapped = true
else
@ -613,7 +616,6 @@ class TextEditorPresenter
screenRow = startRow + i
line = @model.tokenizedLineForScreenRow(screenRow)
decorationClasses = @lineNumberDecorationClassesForRow(screenRow)
foldable = @model.isFoldableAtScreenRow(screenRow)
blockDecorationsBeforeCurrentScreenRowHeight = @lineTopIndex.pixelPositionAfterBlocksForRow(screenRow) - @lineTopIndex.pixelPositionBeforeBlocksForRow(screenRow)
blockDecorationsHeight = blockDecorationsBeforeCurrentScreenRowHeight
if screenRow % @tileSize isnt 0

View File

@ -109,6 +109,7 @@ class TextEditor extends Model
@emitter = new Emitter
@disposables = new CompositeDisposable
@cursors = []
@cursorsByMarkerId = new Map
@selections = []
buffer ?= new TextBuffer
@ -1944,10 +1945,18 @@ class TextEditor extends Model
getCursorsOrderedByBufferPosition: ->
@getCursors().sort (a, b) -> a.compare(b)
cursorsForScreenRowRange: (startScreenRow, endScreenRow) ->
cursors = []
for marker in @selectionsMarkerLayer.findMarkers(intersectsScreenRowRange: [startScreenRow, endScreenRow])
if cursor = @cursorsByMarkerId.get(marker.id)
cursors.push(cursor)
cursors
# Add a cursor based on the given {TextEditorMarker}.
addCursor: (marker) ->
cursor = new Cursor(editor: this, marker: marker, config: @config)
@cursors.push(cursor)
@cursorsByMarkerId.set(marker.id, cursor)
@decorateMarker(marker, type: 'line-number', class: 'cursor-line')
@decorateMarker(marker, type: 'line-number', class: 'cursor-line-no-selection', onlyHead: true, onlyEmpty: true)
@decorateMarker(marker, type: 'line', class: 'cursor-line', onlyEmpty: true)
@ -2446,6 +2455,7 @@ class TextEditor extends Model
removeSelection: (selection) ->
_.remove(@cursors, selection.cursor)
_.remove(@selections, selection)
@cursorsByMarkerId.delete(selection.cursor.marker.id)
@emitter.emit 'did-remove-cursor', selection.cursor
@emitter.emit 'did-remove-selection', selection
@ -2929,8 +2939,7 @@ class TextEditor extends Model
#
# Returns a {Boolean}.
isFoldableAtBufferRow: (bufferRow) ->
# @languageMode.isFoldableAtBufferRow(bufferRow)
@displayBuffer.tokenizedBuffer.tokenizedLineForRow(bufferRow)?.foldable ? false
@displayBuffer.isFoldableAtBufferRow(bufferRow)
# Extended: Determine whether the given row in screen coordinates is foldable.
#

View File

@ -210,8 +210,6 @@ class TokenizedBuffer extends Model
@validateRow(endRow)
@invalidateRow(endRow + 1) unless filledRegion
[startRow, endRow] = @updateFoldableStatus(startRow, endRow)
event = {start: startRow, end: endRow, delta: 0}
@emitter.emit 'did-change', event
@ -271,9 +269,6 @@ class TokenizedBuffer extends Model
if newEndStack and not _.isEqual(newEndStack, previousEndStack)
@invalidateRow(end + delta + 1)
[start, end] = @updateFoldableStatus(start, end + delta)
end -= delta
event = {start, end, delta, bufferChange: e}
@emitter.emit 'did-change', event
@ -287,23 +282,6 @@ class TokenizedBuffer extends Model
row - increment
updateFoldableStatus: (startRow, endRow) ->
return [startRow, endRow] if @largeFileMode
scanStartRow = @buffer.previousNonBlankRow(startRow) ? startRow
scanStartRow-- while scanStartRow > 0 and @tokenizedLineForRow(scanStartRow).isComment()
scanEndRow = @buffer.nextNonBlankRow(endRow) ? endRow
for row in [scanStartRow..scanEndRow] by 1
foldable = @isFoldableAtRow(row)
line = @tokenizedLineForRow(row)
unless line.foldable is foldable
line.foldable = foldable
startRow = Math.min(startRow, row)
endRow = Math.max(endRow, row)
[startRow, endRow]
isFoldableAtRow: (row) ->
if @largeFileMode
false

View File

@ -33,7 +33,6 @@ class TokenizedLine
endOfLineInvisibles: null
lineIsWhitespaceOnly: false
firstNonWhitespaceIndex: 0
foldable: false
constructor: (properties) ->
@id = idCounter++
@ -492,15 +491,20 @@ class TokenizedLine
@endOfLineInvisibles.push(eol) if eol
isComment: ->
return @isCommentLine if @isCommentLine?
@isCommentLine = false
iterator = @getTokenIterator()
while iterator.next()
scopes = iterator.getScopes()
continue if scopes.length is 1
continue unless NonWhitespaceRegex.test(iterator.getText())
for scope in scopes
return true if CommentScopeRegex.test(scope)
if CommentScopeRegex.test(scope)
@isCommentLine = true
break
break
false
@isCommentLine
isOnlyWhitespace: ->
@lineIsWhitespaceOnly

View File

@ -1,4 +1,4 @@
remote = require 'remote'
{remote} = require 'electron'
_ = require 'underscore-plus'
windowLoadSettings = null

View File

@ -1,4 +1,4 @@
ipc = require 'ipc'
{ipcRenderer} = require 'electron'
path = require 'path'
{Disposable, CompositeDisposable} = require 'event-kit'
Grim = require 'grim'
@ -117,6 +117,6 @@ class WorkspaceElement extends HTMLElement
[projectPath] = @project.relativizePath(activePath)
else
[projectPath] = @project.getPaths()
ipc.send('run-package-specs', path.join(projectPath, 'spec')) if projectPath
ipcRenderer.send('run-package-specs', path.join(projectPath, 'spec')) if projectPath
module.exports = WorkspaceElement = document.registerElement 'atom-workspace', prototype: WorkspaceElement.prototype

View File

@ -414,6 +414,9 @@ class Workspace extends Model
split = options.split
uri = @project.resolvePath(uri)
if not atom.config.get('core.allowPendingPaneItems')
options.pending = false
# Avoid adding URLs as recent documents to work-around this Spotlight crash:
# https://github.com/atom/atom/issues/10071
if uri? and not url.parse(uri).protocol?
@ -473,7 +476,8 @@ class Workspace extends Model
activateItem = options.activateItem ? true
if uri?
item = pane.itemForURI(uri)
if item = pane.itemForURI(uri)
item.terminatePendingState?() if item.isPending?() and not options.pending
item ?= opener(uri, options) for opener in @getOpeners() when not item
try

View File

@ -1,7 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Security-Policy" content="default-src *; script-src 'self'; style-src 'self' 'unsafe-inline';">
<meta http-equiv="Content-Security-Policy" content="default-src *; img-src data: *; script-src 'self'; style-src 'self' 'unsafe-inline';">
<script src="index.js"></script>
</head>
<body tabindex="-1">

View File

@ -54,7 +54,7 @@
}
function handleSetupError (error) {
var currentWindow = require('remote').getCurrentWindow()
var currentWindow = require('electron').remote.getCurrentWindow()
currentWindow.setSize(800, 600)
currentWindow.center()
currentWindow.show()
@ -71,9 +71,10 @@
ModuleCache.add(loadSettings.resourcePath)
// Start the crash reporter before anything else.
require('crash-reporter').start({
require('electron').crashReporter.start({
productName: 'Atom',
companyName: 'GitHub',
submitURL: 'http://54.249.141.255:1127/post',
// By explicitly passing the app version here, we could save the call
// of "require('remote').require('app').getVersion()".
extra: {_version: loadSettings.appVersion}
@ -83,8 +84,9 @@
setupCsonCache(CompileCache.getCacheDirectory())
var initialize = require(loadSettings.windowInitializationScript)
initialize({blobStore: blobStore})
require('ipc').sendChannel('window-command', 'window:loaded')
return initialize({blobStore: blobStore}).then(function () {
require('electron').ipcRenderer.send('window-command', 'window:loaded')
})
}
function setupCsonCache (cacheDir) {
@ -112,19 +114,15 @@
function profileStartup (loadSettings, initialTime) {
function profile () {
console.profile('startup')
try {
var startTime = Date.now()
setupWindow(loadSettings)
var startTime = Date.now()
setupWindow(loadSettings).then(function () {
setLoadTime(Date.now() - startTime + initialTime)
} catch (error) {
handleSetupError(error)
} finally {
console.profileEnd('startup')
console.log('Switch to the Profiles tab to view the created startup profile')
}
})
}
var currentWindow = require('remote').getCurrentWindow()
var currentWindow = require('electron').remote.getCurrentWindow()
if (currentWindow.devToolsWebContents) {
profile()
} else {
@ -145,31 +143,6 @@
}
}
function setupWindowBackground () {
if (loadSettings && loadSettings.isSpec) {
return
}
var backgroundColor = window.localStorage.getItem('atom:window-background-color')
if (!backgroundColor) {
return
}
var backgroundStylesheet = document.createElement('style')
backgroundStylesheet.type = 'text/css'
backgroundStylesheet.innerText = 'html, body { background: ' + backgroundColor + ' !important; }'
document.head.appendChild(backgroundStylesheet)
// Remove once the page loads
window.addEventListener('load', function loadWindow () {
window.removeEventListener('load', loadWindow, false)
setTimeout(function () {
backgroundStylesheet.remove()
backgroundStylesheet = null
}, 1000)
}, false)
}
var setupAtomHome = function () {
if (process.env.ATOM_HOME) {
return
@ -185,5 +158,4 @@
parseLoadSettings()
setupAtomHome()
setupWindowBackground()
})()