Skip to content

Commit

Permalink
Prevent multiple calls to dispose()
Browse files Browse the repository at this point in the history
When the dispose method is called for the first time, overwrite the
method with one that logs a warning. This is to prevent the code
inside the dispose method from executing twice, even if the method
is overloaded in a parent class
  • Loading branch information
Floris Bernard committed Aug 10, 2018
1 parent 6559124 commit 7ae950c
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 16 deletions.
12 changes: 9 additions & 3 deletions src/lib/Disposable.ts
@@ -1,21 +1,27 @@
import IDisposable from './IDisposable';

function logAlreadyDisposed():void {
// tslint:disable-next-line no-console
console.warn('The dispose() method should only be called once. Duplicate calls are ignored.');
}

class Disposable implements IDisposable {
private disposed: boolean = false;
private disposed:boolean = false;

/**
* After {@link dispose} has been called, this method returns true.
* Use this method to determine whether dispose() should be run again.
*/
public isDisposed(): boolean {
public isDisposed():boolean {
return this.disposed;
}

/**
* Destruct this class.
*/
public dispose(): void {
public dispose():void {
this.disposed = true;
this.dispose = logAlreadyDisposed;
}
}

Expand Down
41 changes: 28 additions & 13 deletions test/Disposable.spec.ts
@@ -1,20 +1,35 @@
import Disposable from '../src/lib/Disposable';
import { expect } from 'chai';
import {} from 'mocha';
import { expect, use as chaiUse } from 'chai';
import { spy } from 'sinon';
import sinonChai from 'sinon-chai';

chaiUse(sinonChai);

describe('DisposableSpec', () => {
let disposable:Disposable;
it('isDisposed should return false when instance has not been disposed', () => {
const disposable = new Disposable();
expect(disposable.isDisposed()).equals(false);
});

it('isDisposed should return true when instance has been disposed', () => {
const disposable = new Disposable();
disposable.dispose();
expect(disposable.isDisposed()).equals(true);
});

beforeEach(() => {
disposable = new Disposable();
});
it('dispose() should not be executed multiple times', () => {
const disposeSpy = spy();

it('isDisposed should return false when instance has not been disposed', () => {
expect(disposable.isDisposed()).equals(false);
});
class TestDispose extends Disposable {
public dispose():void {
disposeSpy();
super.dispose();
}
}

it('isDisposed should return true when instance has been disposed', () => {
disposable.dispose();
expect(disposable.isDisposed()).equals(true);
});
const disposable = new TestDispose();
disposable.dispose();
disposable.dispose();
expect(disposeSpy).to.have.been.calledOnce;
});
});

0 comments on commit 7ae950c

Please sign in to comment.