diff --git a/spec/text-editor-spec.js b/spec/text-editor-spec.js index 89af72137..ab84d88c8 100644 --- a/spec/text-editor-spec.js +++ b/spec/text-editor-spec.js @@ -20,6 +20,17 @@ describe('TextEditor', () => { await atom.packages.activatePackage('language-javascript') }) + it('generates unique ids for each editor', async () => { + // Deserialized editors are initialized with the serialized id. We can + // initialize an editor with what we expect to be the next id: + const deserialized = new TextEditor({id: editor.id+1}) + expect(deserialized.id).toEqual(editor.id+1) + + // The id generator should skip the id used up by the deserialized one: + const fresh = new TextEditor() + expect(fresh.id).toNotEqual(deserialized.id) + }) + describe('when the editor is deserialized', () => { it('restores selections and folds based on markers in the buffer', async () => { editor.setSelectedBufferRange([[1, 2], [3, 4]]) diff --git a/src/main-process/atom-application.coffee b/src/main-process/atom-application.coffee index 8e889ecca..e0d2d691f 100644 --- a/src/main-process/atom-application.coffee +++ b/src/main-process/atom-application.coffee @@ -38,12 +38,15 @@ class AtomApplication # Lowercasing the ATOM_HOME to make sure that we don't get multiple sockets # on case-insensitive filesystems due to arbitrary case differences in paths. atomHomeUnique = path.resolve(process.env.ATOM_HOME).toLowerCase() - hash = crypto.createHash('sha1').update(username).update('|').update(atomHomeUnique) - atomInstanceDigest = hash.digest('hex').substring(0, 32) + hash = crypto.createHash('sha1').update(options.version).update('|').update(process.arch).update('|').update(username).update('|').update(atomHomeUnique) + # We only keep the first 12 characters of the hash as not to have excessively long + # socket file. Note that macOS/BSD limit the length of socket file paths (see #15081). + # The replace calls convert the digest into "URL and Filename Safe" encoding (see RFC 4648). + atomInstanceDigest = hash.digest('base64').substring(0, 12).replace(/\+/g, '-').replace(/\//g, '_') if process.platform is 'win32' - options.socketPath = "\\\\.\\pipe\\atom-#{options.version}-#{process.arch}-#{atomInstanceDigest}-sock" + options.socketPath = "\\\\.\\pipe\\atom-#{atomInstanceDigest}-sock" else - options.socketPath = path.join(os.tmpdir(), "atom-#{options.version}-#{process.arch}-#{atomInstanceDigest}.sock") + options.socketPath = path.join(os.tmpdir(), "atom-#{atomInstanceDigest}.sock") # 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 diff --git a/src/text-editor.js b/src/text-editor.js index fc2d6acd3..dcf8e201e 100644 --- a/src/text-editor.js +++ b/src/text-editor.js @@ -119,6 +119,10 @@ class TextEditor { } this.id = params.id != null ? params.id : nextId++ + if (this.id >= nextId) { + // Ensure that new editors get unique ids: + nextId = this.id + 1 + } this.initialScrollTopRow = params.initialScrollTopRow this.initialScrollLeftColumn = params.initialScrollLeftColumn this.decorationManager = params.decorationManager