-
Notifications
You must be signed in to change notification settings - Fork 35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(FEC-11037): multiple decorator exist after destroy plugin with decorator #544
Merged
Merged
Changes from 12 commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
479c763
fix: multiple decorator exist after destroy plugin with decorator
Yuvalke 2b91d08
check the instance
Yuvalke f25d3c4
Merge branch 'master' into fix-multiple-decorator-after-destroy
Yuvalke cdf8ae8
delete the static providers on destroy
Yuvalke 98c8d34
Add tests
Yuvalke 34eac4a
can't remove EngineDecorator._decoratorProviders on destroty it won't…
Yuvalke 2ee2df5
destroy the _decoratorProviders on player destroy
Yuvalke 2ac29dc
Add an API for add engine decorator
Yuvalke cfa9a05
add type for function
Yuvalke f9c650b
fix naming and internal structure
Yuvalke 9bf8217
fix tests
Yuvalke 6e5815b
change the engine provider
Yuvalke abebf27
move EngineDecoratorProvider to playkit and change to map
Yuvalke 4a52ead
fix flow
Yuvalke c0a3e76
add logger to trace the decorator manager on logs
Yuvalke 67e13a2
add explicit to string
Yuvalke File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,26 @@ | ||
// @flow | ||
import {MultiMap} from '../utils'; | ||
|
||
/** | ||
* Engine decorator manager for plugins. | ||
* @class EngineDecoratorManager | ||
*/ | ||
class EngineDecoratorManager { | ||
_decoratorProviders: MultiMap<string, IEngineDecoratorProvider> = new MultiMap(); | ||
|
||
register(engineDecoratorProvider: IEngineDecoratorProvider): void { | ||
if (!this._decoratorProviders.has(engineDecoratorProvider.getName())) { | ||
this._decoratorProviders.push(engineDecoratorProvider.getName(), engineDecoratorProvider); | ||
} | ||
} | ||
|
||
createDecorators(engine: IEngine, dispatchEvent: Function): Array<IEngineDecorator> { | ||
return this._decoratorProviders.getAll().map(engineDecoratorProvider => engineDecoratorProvider.getEngineDecorator(engine, dispatchEvent)); | ||
} | ||
|
||
destroy(): void { | ||
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
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 | ||||
---|---|---|---|---|---|---|
|
@@ -38,6 +38,7 @@ import {LabelOptions} from './track/label-options'; | |||||
import {AutoPlayType} from './enums/auto-play-type'; | ||||||
import ImageTrack from './track/image-track'; | ||||||
import {ThumbnailInfo} from './thumbnail/thumbnail-info'; | ||||||
import {EngineDecoratorManager} from './engines/engine-decorator-manager'; | ||||||
|
||||||
/** | ||||||
* The black cover class name. | ||||||
|
@@ -390,6 +391,12 @@ export default class Player extends FakeEventTarget { | |||||
* @private | ||||||
*/ | ||||||
_aspectRatio: ?string; | ||||||
/** | ||||||
* The engine manager. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
* @type {?EngineDecoratorManager} | ||||||
* @private | ||||||
*/ | ||||||
_engineDecoratorManager: ?EngineDecoratorManager; | ||||||
|
||||||
/** | ||||||
* @param {Object} config - The configuration for the player instance. | ||||||
|
@@ -627,6 +634,9 @@ export default class Player extends FakeEventTarget { | |||||
if (this._engine) { | ||||||
this._engine.destroy(); | ||||||
} | ||||||
if (this._engineDecoratorManager) { | ||||||
this._engineDecoratorManager.destroy(); | ||||||
} | ||||||
this._resizeWatcher.destroy(); | ||||||
if (this._el) { | ||||||
Utils.Dom.removeChild(this._el.parentNode, this._el); | ||||||
|
@@ -690,6 +700,21 @@ export default class Player extends FakeEventTarget { | |||||
} | ||||||
} | ||||||
|
||||||
/** | ||||||
* detach the engine's media source | ||||||
* @public | ||||||
* @returns {void} | ||||||
* @param {IEngineDecoratorProvider} engineDecoratorProvider - function to create the decorator | ||||||
*/ | ||||||
registerEngineDecoratorProvider(engineDecoratorProvider: IEngineDecoratorProvider): void { | ||||||
if (!this._engineDecoratorManager) { | ||||||
this._engineDecoratorManager = new EngineDecoratorManager(); | ||||||
} | ||||||
if (engineDecoratorProvider) { | ||||||
this._engineDecoratorManager.register(engineDecoratorProvider); | ||||||
} | ||||||
} | ||||||
|
||||||
/** | ||||||
* Get the first buffered range of the engine. | ||||||
* @returns {TimeRanges} - First buffered range of the engine in seconds. | ||||||
|
@@ -1694,7 +1719,7 @@ export default class Player extends FakeEventTarget { | |||||
*/ | ||||||
_createEngine(Engine: IEngineStatic, source: PKMediaSourceObject): void { | ||||||
const engine = Engine.createEngine(source, this._config, this._playerId); | ||||||
this._engine = EngineDecorator.getDecorator(engine) || engine; | ||||||
this._engine = this._engineDecoratorManager ? new EngineDecorator(engine, this._engineDecoratorManager) : engine; | ||||||
} | ||||||
|
||||||
/** | ||||||
|
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}; |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this can be a simple map, multi map is were the value is array but we only have one decorator per plugin