File model cache can end up with stale, disposed entries causing issues (fixes #11684)

This commit is contained in:
Benjamin Pasero 2016-09-12 10:43:40 +02:00
parent 986a2081f7
commit abcac58357
2 changed files with 13 additions and 13 deletions

View file

@ -138,7 +138,6 @@ export class TextFileEditor extends BaseTextEditor {
modelDisposed || // input got disposed meanwhile
inputChanged // a different input was set meanwhile
) {
console.warn('TextFileEditor', 'resource: ', textFileModel.getResource().toString(), 'hasInput: ', hasInput, 'modelDisposed: ', modelDisposed, 'inputChanged: ', inputChanged); // TODO@Ben remove me
return null;
}

View file

@ -32,7 +32,7 @@ export class TextFileEditorModelManager implements ITextFileEditorModelManager {
private mapResourceToDisposeListener: { [resource: string]: IDisposable; };
private mapResourceToStateChangeListener: { [resource: string]: IDisposable; };
private mapResourcePathToModel: { [resource: string]: TextFileEditorModel; };
private mapResourceToModel: { [resource: string]: TextFileEditorModel; };
private mapResourceToPendingModelLoaders: { [resource: string]: TPromise<TextFileEditorModel> };
constructor(
@ -55,7 +55,7 @@ export class TextFileEditorModelManager implements ITextFileEditorModelManager {
this.toUnbind.push(this._onModelReverted);
this.toUnbind.push(this._onModelEncodingChanged);
this.mapResourcePathToModel = Object.create(null);
this.mapResourceToModel = Object.create(null);
this.mapResourceToDisposeListener = Object.create(null);
this.mapResourceToStateChangeListener = Object.create(null);
this.mapResourceToPendingModelLoaders = Object.create(null);
@ -135,6 +135,10 @@ export class TextFileEditorModelManager implements ITextFileEditorModelManager {
return false; // never dispose unsaved models
}
if (this.mapResourceToPendingModelLoaders[textModel.getResource().toString()]) {
return false; // never dispose models that we are about to load at the same time
}
return true;
}
@ -159,7 +163,7 @@ export class TextFileEditorModelManager implements ITextFileEditorModelManager {
}
public get(resource: URI): TextFileEditorModel {
return this.mapResourcePathToModel[resource.toString()];
return this.mapResourceToModel[resource.toString()];
}
public loadOrCreate(resource: URI, encoding: string, refresh?: boolean): TPromise<TextFileEditorModel> {
@ -214,9 +218,6 @@ export class TextFileEditorModelManager implements ITextFileEditorModelManager {
this.mapResourceToPendingModelLoaders[resource.toString()] = modelPromise;
return modelPromise.then(model => {
if (model.isDisposed()) {
console.warn('Adding disposed model into cache!!!', model.getResource().toString()); // TODO@Ben remove me
}
// Make known to manager (if not already known)
this.add(resource, model);
@ -238,13 +239,13 @@ export class TextFileEditorModelManager implements ITextFileEditorModelManager {
}
public getAll(resource?: URI): TextFileEditorModel[] {
return Object.keys(this.mapResourcePathToModel)
return Object.keys(this.mapResourceToModel)
.filter(r => !resource || resource.toString() === r)
.map(r => this.mapResourcePathToModel[r]);
.map(r => this.mapResourceToModel[r]);
}
public add(resource: URI, model: TextFileEditorModel): void {
const knownModel = this.mapResourcePathToModel[resource.toString()];
const knownModel = this.mapResourceToModel[resource.toString()];
if (knownModel === model) {
return; // already cached
}
@ -256,12 +257,12 @@ export class TextFileEditorModelManager implements ITextFileEditorModelManager {
}
// store in cache but remove when model gets disposed
this.mapResourcePathToModel[resource.toString()] = model;
this.mapResourceToModel[resource.toString()] = model;
this.mapResourceToDisposeListener[resource.toString()] = model.onDispose(() => this.remove(resource));
}
public remove(resource: URI): void {
delete this.mapResourcePathToModel[resource.toString()];
delete this.mapResourceToModel[resource.toString()];
const disposeListener = this.mapResourceToDisposeListener[resource.toString()];
if (disposeListener) {
@ -279,7 +280,7 @@ export class TextFileEditorModelManager implements ITextFileEditorModelManager {
public clear(): void {
// model cache
this.mapResourcePathToModel = Object.create(null);
this.mapResourceToModel = Object.create(null);
// dispose dispose listeners
let keys = Object.keys(this.mapResourceToDisposeListener);