Skip to content

Commit

Permalink
fix: Support require()-ing video.js (#3889)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
misteroneill authored and gkatsev committed Dec 23, 2016
1 parent b7c384e commit ac0b03f
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 30 deletions.
11 changes: 9 additions & 2 deletions src/js/setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*
* @module setup
*/
import * as Dom from './utils/dom';
import * as Events from './utils/events.js';
import document from 'global/document';
import window from 'global/window';
Expand All @@ -15,6 +16,12 @@ let videojs;
* Set up any tags that have a data-setup `attribute` when the player is started.
*/
const autoSetup = function() {

// Protect against breakage in non-browser environments.
if (!Dom.isReal()) {
return;
}

// One day, when we stop supporting IE8, go back to this, but in the meantime...*hack hack hack*
// var vids = Array.prototype.slice.call(document.getElementsByTagName('video'));
// var audios = Array.prototype.slice.call(document.getElementsByTagName('audio'));
Expand Down Expand Up @@ -89,10 +96,10 @@ function autoSetupTimeout(wait, vjs) {
videojs = vjs;
}

setTimeout(autoSetup, wait);
window.setTimeout(autoSetup, wait);
}

if (document.readyState === 'complete') {
if (Dom.isReal() && document.readyState === 'complete') {
_windowLoaded = true;
} else {
/**
Expand Down
45 changes: 24 additions & 21 deletions src/js/tech/html5.js
Original file line number Diff line number Diff line change
Expand Up @@ -798,20 +798,23 @@ class Html5 extends Tech {

/* HTML5 Support Testing ---------------------------------------------------- */

/**
* Element for testing browser HTML5 media capabilities
*
* @type {Element}
* @constant
* @private
*/
Html5.TEST_VID = document.createElement('video');
const track = document.createElement('track');
if (Dom.isReal()) {

track.kind = 'captions';
track.srclang = 'en';
track.label = 'English';
Html5.TEST_VID.appendChild(track);
/**
* Element for testing browser HTML5 media capabilities
*
* @type {Element}
* @constant
* @private
*/
Html5.TEST_VID = document.createElement('video');
const track = document.createElement('track');

track.kind = 'captions';
track.srclang = 'en';
track.label = 'English';
Html5.TEST_VID.appendChild(track);
}

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

return !!Html5.TEST_VID.canPlayType;
return !!(Html5.TEST_VID && Html5.TEST_VID.canPlayType);
};

/**
Expand Down Expand Up @@ -895,9 +898,7 @@ Html5.supportsNativeTextTracks = function() {
* - False otherwise
*/
Html5.supportsNativeVideoTracks = function() {
const supportsVideoTracks = !!Html5.TEST_VID.videoTracks;

return supportsVideoTracks;
return !!(Html5.TEST_VID && Html5.TEST_VID.videoTracks);
};

/**
Expand All @@ -908,9 +909,7 @@ Html5.supportsNativeVideoTracks = function() {
* - False otherwise
*/
Html5.supportsNativeAudioTracks = function() {
const supportsAudioTracks = !!Html5.TEST_VID.audioTracks;

return supportsAudioTracks;
return !!(Html5.TEST_VID && Html5.TEST_VID.audioTracks);
};

/**
Expand Down Expand Up @@ -1026,11 +1025,15 @@ Html5.prototype.featuresNativeVideoTracks = Html5.supportsNativeVideoTracks();
Html5.prototype.featuresNativeAudioTracks = Html5.supportsNativeAudioTracks();

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

Html5.patchCanPlayType = function() {
if (!canPlayType) {
return;
}

// Android 4.0 and above can play HLS to some extent but it reports being unable to do so
if (browser.ANDROID_VERSION >= 4.0 && !browser.IS_FIREFOX) {
Html5.TEST_VID.constructor.prototype.canPlayType = function(type) {
Expand Down
12 changes: 9 additions & 3 deletions src/js/utils/browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* @file browser.js
* @module browser
*/
import document from 'global/document';
import * as Dom from './dom';
import window from 'global/window';

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

export const TOUCH_ENABLED = !!(('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch);
export const BACKGROUND_SIZE_SUPPORTED = 'backgroundSize' in document.createElement('video').style;
export const TOUCH_ENABLED = Dom.isReal() && (
'ontouchstart' in window ||
window.DocumentTouch &&
window.document instanceof window.DocumentTouch);

export const BACKGROUND_SIZE_SUPPORTED = (
Dom.isReal() &&
'backgroundSize' in window.document.createElement('video').style);
9 changes: 9 additions & 0 deletions src/js/utils/dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,15 @@ function classRegExp(className) {
return new RegExp('(^|\\s)' + className + '($|\\s)');
}

/**
* Whether the current DOM interface appears to be real.
*
* @return {Boolean}
*/
export function isReal() {
return document === window.document && typeof document.createElement === 'function';
}

/**
* Determines, via duck typing, whether or not a value is a DOM element.
*
Expand Down
6 changes: 2 additions & 4 deletions src/js/video.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,7 @@ import xhr from 'xhr';
import Tech from './tech/tech.js';

// HTML5 Element Shim for IE8
if (typeof HTMLVideoElement === 'undefined' &&
window.document &&
window.document.createElement) {
if (typeof HTMLVideoElement === 'undefined' && Dom.isReal()) {
document.createElement('video');
document.createElement('audio');
document.createElement('track');
Expand Down Expand Up @@ -196,7 +194,7 @@ videojs.removeHook = function(type, fn) {
};

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

if (!style) {
Expand Down

0 comments on commit ac0b03f

Please sign in to comment.