-
Notifications
You must be signed in to change notification settings - Fork 35
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(FEC-11037): multiple decorator exist after destroy plugin with de…
…corator (#544) Issue: when the plugin has the decorator, every re-create of player will register again to static that contains the decorator and multiple instances will be created for next time. Solution: change the decorator registration from static to instance to make sure every player has his own decorator manager.
- Loading branch information
Showing
8 changed files
with
250 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// @flow | ||
import getLogger from '../utils/logger'; | ||
|
||
/** | ||
* Engine decorator manager for plugins. | ||
* @class EngineDecoratorManager | ||
*/ | ||
class EngineDecoratorManager { | ||
_decoratorProviders: Map<string, IEngineDecoratorProvider> = new Map(); | ||
_logger: any = getLogger('EngineDecoratorManager'); | ||
|
||
register(engineDecoratorProvider: IEngineDecoratorProvider): void { | ||
if (!this._decoratorProviders.has(engineDecoratorProvider.getName())) { | ||
this._decoratorProviders.set(engineDecoratorProvider.getName(), engineDecoratorProvider); | ||
} else { | ||
this._logger.warn(`decorator already registered for ${engineDecoratorProvider.getName()}`); | ||
} | ||
} | ||
|
||
createDecorators(engine: IEngine, dispatchEvent: Function): Array<IEngineDecorator> { | ||
this._logger.debug(`decorators created for ${Array.from(this._decoratorProviders.keys()).toString()}`); | ||
return Array.from(this._decoratorProviders.values(), engineDecoratorProvider => | ||
engineDecoratorProvider.getEngineDecorator(engine, dispatchEvent) | ||
); | ||
} | ||
|
||
destroy(): void { | ||
this._logger.debug(`decorators destroyed`); | ||
this._decoratorProviders.clear(); | ||
} | ||
} | ||
|
||
export {EngineDecoratorManager}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
// @flow | ||
|
||
/** | ||
* Engine decorator provider. | ||
* @class EngineDecoratorProvider | ||
* @param {IEngineDecoratorProvider} plugin - The plugin which have implemented decorator. | ||
* @implements {IEngineDecorator} | ||
*/ | ||
class EngineDecoratorProvider implements IEngineDecoratorProvider { | ||
_name: string; | ||
_getEngineDecorator: (engine: IEngine, dispatchEventHandler: Function) => IEngineDecorator; | ||
|
||
constructor(plugin: IEngineDecoratorProvider) { | ||
this._name = plugin.getName(); | ||
this._getEngineDecorator = plugin.getEngineDecorator.bind(plugin); | ||
} | ||
|
||
getEngineDecorator(engine: IEngine, dispatchEventHandler: Function): IEngineDecorator { | ||
return this._getEngineDecorator(engine, dispatchEventHandler); | ||
} | ||
|
||
getName(): string { | ||
return this._name; | ||
} | ||
} | ||
|
||
export {EngineDecoratorProvider}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import {FakeDecoratorProvider, FakeDecoratorProviderActive, FakeHTML5Engine} from './test-engine-decorator-providers'; | ||
import {EngineDecorator} from '../../../src/engines/engine-decorator'; | ||
import Player from '../../../src/player'; | ||
import {createElement, getConfigStructure} from '../utils/test-utils'; | ||
import {EngineDecoratorManager} from '../../../src/engines/engine-decorator-manager'; | ||
|
||
describe('EngineDecorator', () => { | ||
let engine; | ||
beforeEach(() => { | ||
engine = new FakeHTML5Engine(); | ||
}); | ||
afterEach(() => { | ||
engine = null; | ||
}); | ||
|
||
it('should decorator be able to register once for same plugin name', () => { | ||
const decoratorManager = new EngineDecoratorManager(); | ||
decoratorManager.register(FakeDecoratorProviderActive); | ||
decoratorManager.register(FakeDecoratorProviderActive); | ||
decoratorManager.register(FakeDecoratorProviderActive); | ||
decoratorManager.createDecorators(null, null).length.should.equal(1); | ||
}); | ||
|
||
it('should decorator use the engine for non implemented methods on active decorator', () => { | ||
const decoratorManager = new EngineDecoratorManager(); | ||
decoratorManager.register(FakeDecoratorProviderActive); | ||
const engineDecorator = new EngineDecorator(engine, decoratorManager); | ||
engineDecorator.isAdaptiveBitrateEnabled().should.be.true; | ||
}); | ||
|
||
it('should decorator use the engine for implemented methods on non active decorator', () => { | ||
const decoratorManager = new EngineDecoratorManager(); | ||
decoratorManager.register(FakeDecoratorProvider); | ||
const engineDecorator = new EngineDecorator(engine, decoratorManager); | ||
engineDecorator.isLive().should.be.false; | ||
}); | ||
|
||
it('should decorator use the decorator for implemented methods on active decorator', () => { | ||
let engineDecorator, decoratorManager; | ||
decoratorManager = new EngineDecoratorManager(); | ||
decoratorManager.register(FakeDecoratorProviderActive); | ||
engineDecorator = new EngineDecorator(engine, decoratorManager); | ||
engineDecorator.isLive().should.be.true; | ||
|
||
decoratorManager = new EngineDecoratorManager(); | ||
decoratorManager.register(FakeDecoratorProvider); | ||
engineDecorator = new EngineDecorator(engine, decoratorManager); | ||
engineDecorator.isLive().should.be.false; | ||
}); | ||
|
||
it('should decorator providers should destroy on destroy', () => { | ||
const targetId = 'player-placeholder_engine-decorator.spec'; | ||
const playerContainer = createElement('DIV', targetId); | ||
|
||
const player = new Player(getConfigStructure()); | ||
player.registerEngineDecoratorProvider(FakeDecoratorProviderActive); | ||
player.registerEngineDecoratorProvider(FakeDecoratorProvider); | ||
playerContainer.appendChild(player.getView()); | ||
|
||
player.destroy(); | ||
player._engineDecoratorManager.createDecorators(null, null).length.should.equal(0); | ||
}); | ||
|
||
it.skip('should decorator use the decorator instance as context of the function', done => { | ||
const decoratorManager = new EngineDecoratorManager(); | ||
const decoratorProvider = FakeDecoratorProviderActive; | ||
decoratorManager.register(decoratorProvider); | ||
const engineDecorator = new EngineDecorator(engine, decoratorManager); | ||
const loadPromise = engineDecorator.load(); | ||
loadPromise.then(context => { | ||
try { | ||
(context === decoratorProvider.getEngineDecorator()).should.be.true; | ||
done(); | ||
} catch (e) { | ||
done(e); | ||
} | ||
}); | ||
}); | ||
|
||
it.skip('should decorator use the engine when decorator not active', done => { | ||
const decoratorManager = new EngineDecoratorManager(); | ||
decoratorManager.register(FakeDecoratorProvider); | ||
const engineDecorator = new EngineDecorator(engine, decoratorManager); | ||
const loadPromise = engineDecorator.load(); | ||
loadPromise.then(context => { | ||
try { | ||
(context === engine).should.be.true; | ||
done(); | ||
} catch (e) { | ||
done(e); | ||
} | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import type {IEngine, IEngineDecorator} from '../../../flow-typed/interfaces/engine'; | ||
import FakeEventTarget from '../../../src/event/fake-event-target'; | ||
|
||
class FakeHTML5Engine extends FakeEventTarget implements IEngine { | ||
constructor() { | ||
super(); | ||
} | ||
load(): Promise<*> { | ||
return Promise.resolve(this); | ||
} | ||
isAdaptiveBitrateEnabled() { | ||
return true; | ||
} | ||
|
||
isLive(): boolean { | ||
return false; | ||
} | ||
|
||
destroy() {} | ||
} | ||
|
||
const FakeDecoratorProvider = { | ||
getEngineDecorator: () => { | ||
return new (class EngineDecorator implements IEngineDecorator { | ||
constructor() {} | ||
|
||
get active(): boolean { | ||
return false; | ||
} | ||
})(); | ||
}, | ||
getName: () => { | ||
return 'fake'; | ||
} | ||
}; | ||
|
||
const FakeDecoratorProviderActive = { | ||
_decorator: new (class EngineDecorator implements IEngineDecorator { | ||
constructor() {} | ||
|
||
load(): Promise<*> { | ||
return Promise.resolve(this); | ||
} | ||
|
||
isLive(): boolean { | ||
return true; | ||
} | ||
|
||
get active(): boolean { | ||
return true; | ||
} | ||
})(), | ||
getEngineDecorator: () => { | ||
return FakeDecoratorProviderActive._decorator; | ||
}, | ||
getName: () => { | ||
return 'fakeActive'; | ||
} | ||
}; | ||
|
||
export {FakeDecoratorProvider, FakeDecoratorProviderActive, FakeHTML5Engine}; |