-
Notifications
You must be signed in to change notification settings - Fork 7.5k
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
setSrc clears currentSource_ after loadstart #3285
Changes from 4 commits
06dcc61
8d89829
132e107
47873df
f10fc92
84810c2
64be2ab
43aac04
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -11,7 +11,7 @@ EventTarget.prototype.on = function(type, fn) { | |||||||||||||||||||||||||
// Remove the addEventListener alias before calling Events.on | ||||||||||||||||||||||||||
// so we don't get into an infinite type loop | ||||||||||||||||||||||||||
let ael = this.addEventListener; | ||||||||||||||||||||||||||
this.addEventListener = Function.prototype; | ||||||||||||||||||||||||||
this.addEventListener = () => {}; | ||||||||||||||||||||||||||
Events.on(this, type, fn); | ||||||||||||||||||||||||||
this.addEventListener = ael; | ||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||
|
@@ -23,7 +23,12 @@ EventTarget.prototype.off = function(type, fn) { | |||||||||||||||||||||||||
EventTarget.prototype.removeEventListener = EventTarget.prototype.off; | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
EventTarget.prototype.one = function(type, fn) { | ||||||||||||||||||||||||||
// Remove the addEventListener alias before calling Events.on | ||||||||||||||||||||||||||
// so we don't get into an infinite type loop | ||||||||||||||||||||||||||
let ael = this.addEventListener; | ||||||||||||||||||||||||||
this.addEventListener = () => {}; | ||||||||||||||||||||||||||
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. What would happen if one of the listeners registers an event listener? Something like this: function maybeReRegister() {
if (someCondition()) {
player.one('play', maybeReRegister);
return;
}
alert('done!');
};
player.one('play', maybeReRegister); 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. After reviewing, I don't think this is a problem right now but the event stuff sure is confusing. 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. I think it works fine because the event system creates a clone of the handlers before it starts triggering events: video.js/src/js/utils/events.js Lines 52 to 63 in 2e2dbde
|
||||||||||||||||||||||||||
Events.one(this, type, fn); | ||||||||||||||||||||||||||
this.addEventListener = ael; | ||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
EventTarget.prototype.trigger = function(event) { | ||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -549,9 +549,19 @@ class Html5 extends Tech { | |||||||||
* @method setSrc | ||||||||||
*/ | ||||||||||
setSrc(src) { | ||||||||||
let loadstartlistener = Html5.prototype.loadStartListener_; | ||||||||||
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. Are we explicitly using the 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. No, it's just arbitrary. |
||||||||||
|
||||||||||
this.off(this.el_, 'loadstart', loadstartlistener); | ||||||||||
this.one(this.el_, 'loadstart', () => this.one(this.el_, 'loadstart', loadstartlistener)); | ||||||||||
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. Does this assume setSrc() is the only valid way to modify the video element's source? What about setSource()? Is there a way this can be written that doesn't require adding and removing listeners after the tech's creation? You might be able to use the 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. Also, this function literal wouldn't get cleared properly on subsequent calls to setSrc() which would cause the 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. Yeah, this doesn't account for Lines 1916 to 1919 in 2e2dbde
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. why would 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. Here's the scenario:
loadStartListener_() would be removed on the second call to setSrc() but the inline listener that triggers the loadstartlistener on the next 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. Oh, right, the first |
||||||||||
|
||||||||||
this.el_.src = src; | ||||||||||
} | ||||||||||
|
||||||||||
loadStartListener_() { | ||||||||||
this.currentSource_ = null; | ||||||||||
this.disposeSourceHandler(); | ||||||||||
} | ||||||||||
|
||||||||||
/** | ||||||||||
* Load media into player | ||||||||||
* | ||||||||||
|
@@ -1148,7 +1158,6 @@ Html5.prototype['featuresNativeVideoTracks'] = Html5.supportsNativeVideoTracks() | |||||||||
*/ | ||||||||||
Html5.prototype['featuresNativeAudioTracks'] = Html5.supportsNativeAudioTracks(); | ||||||||||
|
||||||||||
|
||||||||||
// HTML5 Feature detection and Device Fixes --------------------------------- // | ||||||||||
let canPlayType; | ||||||||||
const mpegurlRE = /^application\/(?:x-|vnd\.apple\.)mpegurl/i; | ||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,8 @@ var player, tech, el; | |
import Html5 from '../../../src/js/tech/html5.js'; | ||
import * as browser from '../../../src/js/utils/browser.js'; | ||
import document from 'global/document'; | ||
import EventTarget from '../../../src/js/event-target.js'; | ||
import * as Fn from '../../../src/js/utils/fn.js'; | ||
|
||
q.module('HTML5', { | ||
'setup': function() { | ||
|
@@ -442,3 +444,30 @@ test('Html5#reset calls Html5.resetMediaElement when called', function() { | |
|
||
Html5.resetMediaElement = oldResetMedia; | ||
}); | ||
|
||
test('Html5#setSrc clears currentSource_ after loadstart', function() { | ||
|
||
let disposed = false; | ||
let thing = { | ||
off: () => {}, | ||
one: (el, type, fun) => { | ||
el.one(type, Fn.bind(thing, fun)); | ||
}, | ||
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. Mocking one() and off() may make this test a little too artificial. 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. It does successfully test that setSrc clears contentSource_ after loadstart. Do you have any suggestions on how to make this more real? 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. I'd create an object that inherited from EventTarget right in the test here and use that. 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. We tried that. |
||
disposeSourceHandler: () => disposed = true, | ||
el_: new EventTarget() | ||
}; | ||
|
||
Html5.prototype.setSrc.call(thing, 'test'); | ||
|
||
thing.currentSource_ = 'test'; | ||
|
||
thing.el_.trigger('loadstart'); | ||
|
||
equal(thing.currentSource_, 'test'); | ||
|
||
thing.el_.trigger('loadstart'); | ||
|
||
equal(thing.currentSource_, null); | ||
equal(disposed, true); | ||
|
||
}); |
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.
Point for discussion: should we be careful about using fat-arrows all over the place? I know calling addEventListener() with a non-
this
receiver is a weird thing to do but we could use a plain function here and avoid possibly subverting people's expectations.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.
We're gonna change this to
function() {}
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.
I don't think it matters here at all since we just want an empty function while
Events.on
runs so we don't get into an infinite loop, so, there's no expectations being subverted here.As for elsewhere, it really depends on what you want the context of your function to be since in arrow functions
this
andarguments
are never bound.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.
That's the crux of the discussion I think we should have. Using fat-arrows removes the ability of the caller to rebind
this
. I've felt it necessary to rebindthis
more than once in my life. Are we intentionally removing that ability or just doing it to save some keystrokes?