Skip to content

Commit ac0b03f

Browse files
misteroneillgkatsev
authored andcommitted
fix: Support require()-ing video.js (#3889)
Introduce the Dom.isReal() function, which makes an educated assumption about the "realness" of the document object. Wrap code here and there with checks against Dom.isReal() as well as other defensive code. Fixes #3869.
1 parent b7c384e commit ac0b03f

File tree

5 files changed

+53
-30
lines changed

5 files changed

+53
-30
lines changed

src/js/setup.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*
55
* @module setup
66
*/
7+
import * as Dom from './utils/dom';
78
import * as Events from './utils/events.js';
89
import document from 'global/document';
910
import window from 'global/window';
@@ -15,6 +16,12 @@ let videojs;
1516
* Set up any tags that have a data-setup `attribute` when the player is started.
1617
*/
1718
const autoSetup = function() {
19+
20+
// Protect against breakage in non-browser environments.
21+
if (!Dom.isReal()) {
22+
return;
23+
}
24+
1825
// One day, when we stop supporting IE8, go back to this, but in the meantime...*hack hack hack*
1926
// var vids = Array.prototype.slice.call(document.getElementsByTagName('video'));
2027
// var audios = Array.prototype.slice.call(document.getElementsByTagName('audio'));
@@ -89,10 +96,10 @@ function autoSetupTimeout(wait, vjs) {
8996
videojs = vjs;
9097
}
9198

92-
setTimeout(autoSetup, wait);
99+
window.setTimeout(autoSetup, wait);
93100
}
94101

95-
if (document.readyState === 'complete') {
102+
if (Dom.isReal() && document.readyState === 'complete') {
96103
_windowLoaded = true;
97104
} else {
98105
/**

src/js/tech/html5.js

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -798,20 +798,23 @@ class Html5 extends Tech {
798798

799799
/* HTML5 Support Testing ---------------------------------------------------- */
800800

801-
/**
802-
* Element for testing browser HTML5 media capabilities
803-
*
804-
* @type {Element}
805-
* @constant
806-
* @private
807-
*/
808-
Html5.TEST_VID = document.createElement('video');
809-
const track = document.createElement('track');
801+
if (Dom.isReal()) {
810802

811-
track.kind = 'captions';
812-
track.srclang = 'en';
813-
track.label = 'English';
814-
Html5.TEST_VID.appendChild(track);
803+
/**
804+
* Element for testing browser HTML5 media capabilities
805+
*
806+
* @type {Element}
807+
* @constant
808+
* @private
809+
*/
810+
Html5.TEST_VID = document.createElement('video');
811+
const track = document.createElement('track');
812+
813+
track.kind = 'captions';
814+
track.srclang = 'en';
815+
track.label = 'English';
816+
Html5.TEST_VID.appendChild(track);
817+
}
815818

816819
/**
817820
* Check if HTML5 media is supported by this browser/device.
@@ -828,7 +831,7 @@ Html5.isSupported = function() {
828831
return false;
829832
}
830833

831-
return !!Html5.TEST_VID.canPlayType;
834+
return !!(Html5.TEST_VID && Html5.TEST_VID.canPlayType);
832835
};
833836

834837
/**
@@ -895,9 +898,7 @@ Html5.supportsNativeTextTracks = function() {
895898
* - False otherwise
896899
*/
897900
Html5.supportsNativeVideoTracks = function() {
898-
const supportsVideoTracks = !!Html5.TEST_VID.videoTracks;
899-
900-
return supportsVideoTracks;
901+
return !!(Html5.TEST_VID && Html5.TEST_VID.videoTracks);
901902
};
902903

903904
/**
@@ -908,9 +909,7 @@ Html5.supportsNativeVideoTracks = function() {
908909
* - False otherwise
909910
*/
910911
Html5.supportsNativeAudioTracks = function() {
911-
const supportsAudioTracks = !!Html5.TEST_VID.audioTracks;
912-
913-
return supportsAudioTracks;
912+
return !!(Html5.TEST_VID && Html5.TEST_VID.audioTracks);
914913
};
915914

916915
/**
@@ -1026,11 +1025,15 @@ Html5.prototype.featuresNativeVideoTracks = Html5.supportsNativeVideoTracks();
10261025
Html5.prototype.featuresNativeAudioTracks = Html5.supportsNativeAudioTracks();
10271026

10281027
// HTML5 Feature detection and Device Fixes --------------------------------- //
1029-
const canPlayType = Html5.TEST_VID.constructor.prototype.canPlayType;
1028+
const canPlayType = Html5.TEST_VID && Html5.TEST_VID.constructor.prototype.canPlayType;
10301029
const mpegurlRE = /^application\/(?:x-|vnd\.apple\.)mpegurl/i;
10311030
const mp4RE = /^video\/mp4/i;
10321031

10331032
Html5.patchCanPlayType = function() {
1033+
if (!canPlayType) {
1034+
return;
1035+
}
1036+
10341037
// Android 4.0 and above can play HLS to some extent but it reports being unable to do so
10351038
if (browser.ANDROID_VERSION >= 4.0 && !browser.IS_FIREFOX) {
10361039
Html5.TEST_VID.constructor.prototype.canPlayType = function(type) {

src/js/utils/browser.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* @file browser.js
33
* @module browser
44
*/
5-
import document from 'global/document';
5+
import * as Dom from './dom';
66
import window from 'global/window';
77

88
const USER_AGENT = window.navigator && window.navigator.userAgent || '';
@@ -70,5 +70,11 @@ export const IE_VERSION = (function(result) {
7070
export const IS_SAFARI = (/Safari/i).test(USER_AGENT) && !IS_CHROME && !IS_ANDROID && !IS_EDGE;
7171
export const IS_ANY_SAFARI = IS_SAFARI || IS_IOS;
7272

73-
export const TOUCH_ENABLED = !!(('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch);
74-
export const BACKGROUND_SIZE_SUPPORTED = 'backgroundSize' in document.createElement('video').style;
73+
export const TOUCH_ENABLED = Dom.isReal() && (
74+
'ontouchstart' in window ||
75+
window.DocumentTouch &&
76+
window.document instanceof window.DocumentTouch);
77+
78+
export const BACKGROUND_SIZE_SUPPORTED = (
79+
Dom.isReal() &&
80+
'backgroundSize' in window.document.createElement('video').style);

src/js/utils/dom.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,15 @@ function classRegExp(className) {
5555
return new RegExp('(^|\\s)' + className + '($|\\s)');
5656
}
5757

58+
/**
59+
* Whether the current DOM interface appears to be real.
60+
*
61+
* @return {Boolean}
62+
*/
63+
export function isReal() {
64+
return document === window.document && typeof document.createElement === 'function';
65+
}
66+
5867
/**
5968
* Determines, via duck typing, whether or not a value is a DOM element.
6069
*

src/js/video.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,7 @@ import xhr from 'xhr';
3535
import Tech from './tech/tech.js';
3636

3737
// HTML5 Element Shim for IE8
38-
if (typeof HTMLVideoElement === 'undefined' &&
39-
window.document &&
40-
window.document.createElement) {
38+
if (typeof HTMLVideoElement === 'undefined' && Dom.isReal()) {
4139
document.createElement('video');
4240
document.createElement('audio');
4341
document.createElement('track');
@@ -196,7 +194,7 @@ videojs.removeHook = function(type, fn) {
196194
};
197195

198196
// Add default styles
199-
if (window.VIDEOJS_NO_DYNAMIC_STYLE !== true) {
197+
if (window.VIDEOJS_NO_DYNAMIC_STYLE !== true && Dom.isReal()) {
200198
let style = Dom.$('.vjs-styles-defaults');
201199

202200
if (!style) {

0 commit comments

Comments
 (0)