Skip to content
This repository was archived by the owner on Dec 15, 2022. It is now read-only.

Don't pass destroyed TextEditors to find-and-replace #2105

Merged
merged 7 commits into from
Apr 30, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions lib/items/changed-file-item.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ export default class ChangedFileItem extends React.Component {

this.refEditor = new RefHolder();
this.refEditor.observe(editor => {
this.emitter.emit('did-change-embedded-text-editor', editor);
if (editor.isAlive()) {
this.emitter.emit('did-change-embedded-text-editor', editor);
}
});
}

Expand Down Expand Up @@ -94,7 +96,7 @@ export default class ChangedFileItem extends React.Component {
}

observeEmbeddedTextEditor(cb) {
this.refEditor.map(editor => cb(editor));
this.refEditor.map(editor => editor.isAlive() && cb(editor));
return this.emitter.on('did-change-embedded-text-editor', cb);
}

Expand Down
6 changes: 4 additions & 2 deletions lib/items/commit-detail-item.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ export default class CommitDetailItem extends React.Component {

this.refEditor = new RefHolder();
this.refEditor.observe(editor => {
this.emitter.emit('did-change-embedded-text-editor', editor);
if (editor.isAlive()) {
this.emitter.emit('did-change-embedded-text-editor', editor);
}
});
}

Expand Down Expand Up @@ -81,7 +83,7 @@ export default class CommitDetailItem extends React.Component {
}

observeEmbeddedTextEditor(cb) {
this.refEditor.map(editor => cb(editor));
this.refEditor.map(editor => editor.isAlive() && cb(editor));
return this.emitter.on('did-change-embedded-text-editor', cb);
}

Expand Down
6 changes: 4 additions & 2 deletions lib/items/commit-preview-item.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ export default class CommitPreviewItem extends React.Component {

this.refEditor = new RefHolder();
this.refEditor.observe(editor => {
this.emitter.emit('did-change-embedded-text-editor', editor);
if (editor.isAlive()) {
this.emitter.emit('did-change-embedded-text-editor', editor);
}
});
}

Expand Down Expand Up @@ -83,7 +85,7 @@ export default class CommitPreviewItem extends React.Component {
}

observeEmbeddedTextEditor(cb) {
this.refEditor.map(editor => cb(editor));
this.refEditor.map(editor => editor.isAlive() && cb(editor));
return this.emitter.on('did-change-embedded-text-editor', cb);
}

Expand Down
6 changes: 4 additions & 2 deletions lib/items/issueish-detail-item.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,9 @@ export default class IssueishDetailItem extends Component {

this.refEditor = new RefHolder();
this.refEditor.observe(editor => {
this.emitter.emit('did-change-embedded-text-editor', editor);
if (editor.isAlive()) {
this.emitter.emit('did-change-embedded-text-editor', editor);
}
});
}

Expand Down Expand Up @@ -214,7 +216,7 @@ export default class IssueishDetailItem extends Component {
}

observeEmbeddedTextEditor(cb) {
this.refEditor.map(editor => cb(editor));
this.refEditor.map(editor => editor.isAlive() && cb(editor));
return this.emitter.on('did-change-embedded-text-editor', cb);
}

Expand Down
58 changes: 41 additions & 17 deletions test/items/changed-file-item.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ describe('ChangedFileItem', function() {
);
}

function open(wrapper, options = {}) {
function open(options = {}) {
const opts = {
relPath: 'a.txt',
workingDirectory: repository.getWorkingDirectoryPath(),
Expand All @@ -70,37 +70,37 @@ describe('ChangedFileItem', function() {

it('locates the repository from the context pool', async function() {
const wrapper = mount(buildPaneApp());
await open(wrapper);
await open();

assert.strictEqual(wrapper.update().find('ChangedFileContainer').prop('repository'), repository);
});

it('passes an absent repository if the working directory is unrecognized', async function() {
const wrapper = mount(buildPaneApp());
await open(wrapper, {workingDirectory: '/nope'});
await open({workingDirectory: '/nope'});

assert.isTrue(wrapper.update().find('ChangedFileContainer').prop('repository').isAbsent());
});

it('passes other props to the container', async function() {
const other = Symbol('other');
const wrapper = mount(buildPaneApp({other}));
await open(wrapper);
await open();

assert.strictEqual(wrapper.update().find('ChangedFileContainer').prop('other'), other);
});

describe('getTitle()', function() {
it('renders an unstaged title', async function() {
const wrapper = mount(buildPaneApp());
const item = await open(wrapper, {stagingStatus: 'unstaged'});
mount(buildPaneApp());
const item = await open({stagingStatus: 'unstaged'});

assert.strictEqual(item.getTitle(), 'Unstaged Changes: a.txt');
});

it('renders a staged title', async function() {
const wrapper = mount(buildPaneApp());
const item = await open(wrapper, {stagingStatus: 'staged'});
mount(buildPaneApp());
const item = await open({stagingStatus: 'staged'});

assert.strictEqual(item.getTitle(), 'Staged Changes: a.txt');
});
Expand Down Expand Up @@ -150,23 +150,23 @@ describe('ChangedFileItem', function() {
});

it('serializes itself as a FilePatchControllerStub', async function() {
const wrapper = mount(buildPaneApp());
const item0 = await open(wrapper, {relPath: 'a.txt', workingDirectory: '/dir0', stagingStatus: 'unstaged'});
mount(buildPaneApp());
const item0 = await open({relPath: 'a.txt', workingDirectory: '/dir0', stagingStatus: 'unstaged'});
assert.deepEqual(item0.serialize(), {
deserializer: 'FilePatchControllerStub',
uri: 'atom-github://file-patch/a.txt?workdir=%2Fdir0&stagingStatus=unstaged',
});

const item1 = await open(wrapper, {relPath: 'b.txt', workingDirectory: '/dir1', stagingStatus: 'staged'});
const item1 = await open({relPath: 'b.txt', workingDirectory: '/dir1', stagingStatus: 'staged'});
assert.deepEqual(item1.serialize(), {
deserializer: 'FilePatchControllerStub',
uri: 'atom-github://file-patch/b.txt?workdir=%2Fdir1&stagingStatus=staged',
});
});

it('has some item-level accessors', async function() {
const wrapper = mount(buildPaneApp());
const item = await open(wrapper, {relPath: 'a.txt', workingDirectory: '/dir', stagingStatus: 'unstaged'});
mount(buildPaneApp());
const item = await open({relPath: 'a.txt', workingDirectory: '/dir', stagingStatus: 'unstaged'});

assert.strictEqual(item.getStagingStatus(), 'unstaged');
assert.strictEqual(item.getFilePath(), 'a.txt');
Expand All @@ -178,16 +178,18 @@ describe('ChangedFileItem', function() {
let sub, editor;

beforeEach(function() {
editor = Symbol('editor');
editor = {
isAlive() { return true; },
};
});

afterEach(function() {
sub && sub.dispose();
});

it('calls its callback immediately if an editor is present', async function() {
it('calls its callback immediately if an editor is present and alive', async function() {
const wrapper = mount(buildPaneApp());
const item = await open(wrapper);
const item = await open();

wrapper.update().find('ChangedFileContainer').prop('refEditor').setter(editor);

Expand All @@ -196,15 +198,37 @@ describe('ChangedFileItem', function() {
assert.isTrue(cb.calledWith(editor));
});

it('does not call its callback if an editor is present but destroyed', async function() {
const wrapper = mount(buildPaneApp());
const item = await open();

wrapper.update().find('ChangedFileContainer').prop('refEditor').setter({isAlive() { return false; }});

const cb = sinon.spy();
sub = item.observeEmbeddedTextEditor(cb);
assert.isFalse(cb.called);
});

it('calls its callback later if the editor changes', async function() {
const wrapper = mount(buildPaneApp());
const item = await open(wrapper);
const item = await open();

const cb = sinon.spy();
sub = item.observeEmbeddedTextEditor(cb);

wrapper.update().find('ChangedFileContainer').prop('refEditor').setter(editor);
assert.isTrue(cb.calledWith(editor));
});

it('does not call its callback after its editor is destroyed', async function() {
const wrapper = mount(buildPaneApp());
const item = await open();

const cb = sinon.spy();
sub = item.observeEmbeddedTextEditor(cb);

wrapper.update().find('ChangedFileContainer').prop('refEditor').setter({isAlive() { return false; }});
assert.isFalse(cb.called);
});
});
});
32 changes: 28 additions & 4 deletions test/items/commit-detail-item.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,16 +192,18 @@ describe('CommitDetailItem', function() {
let sub, editor;

beforeEach(function() {
editor = Symbol('editor');
editor = {
isAlive() { return true; },
};
});

afterEach(function() {
sub && sub.dispose();
});

it('calls its callback immediately if an editor is present', async function() {
it('calls its callback immediately if an editor is present and alive', async function() {
const wrapper = mount(buildPaneApp());
const item = await open(wrapper);
const item = await open();

wrapper.update().find('CommitDetailContainer').prop('refEditor').setter(editor);

Expand All @@ -210,15 +212,37 @@ describe('CommitDetailItem', function() {
assert.isTrue(cb.calledWith(editor));
});

it('does not call its callback if an editor is present but destroyed', async function() {
const wrapper = mount(buildPaneApp());
const item = await open();

wrapper.update().find('CommitDetailContainer').prop('refEditor').setter({isAlive() { return false; }});

const cb = sinon.spy();
sub = item.observeEmbeddedTextEditor(cb);
assert.isFalse(cb.called);
});

it('calls its callback later if the editor changes', async function() {
const wrapper = mount(buildPaneApp());
const item = await open(wrapper);
const item = await open();

const cb = sinon.spy();
sub = item.observeEmbeddedTextEditor(cb);

wrapper.update().find('CommitDetailContainer').prop('refEditor').setter(editor);
assert.isTrue(cb.calledWith(editor));
});

it('does not call its callback after its editor is destroyed', async function() {
const wrapper = mount(buildPaneApp());
const item = await open();

const cb = sinon.spy();
sub = item.observeEmbeddedTextEditor(cb);

wrapper.update().find('CommitDetailContainer').prop('refEditor').setter({isAlive() { return false; }});
assert.isFalse(cb.called);
});
});
});
Loading