1
0
mirror of https://github.com/videojs/video.js.git synced 2025-02-02 11:34:50 +02:00

perf: Another 5ms of startup time improvements (#6145)

This commit is contained in:
Brandon Casey 2019-08-29 16:44:06 -04:00 committed by Gary Katsevman
parent f324d1f23c
commit 22782b8425
10 changed files with 147 additions and 96 deletions

50
package-lock.json generated
View File

@ -626,6 +626,15 @@
"@babel/helper-plugin-utils": "^7.0.0"
}
},
"@babel/plugin-transform-object-assign": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-assign/-/plugin-transform-object-assign-7.2.0.tgz",
"integrity": "sha512-nmE55cZBPFgUktbF2OuoZgPRadfxosLOpSgzEPYotKSls9J4pEPcembi8r78RU37Rph6UApCpNmsQA4QMWK9Ng==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.0.0"
}
},
"@babel/plugin-transform-object-super": {
"version": "7.5.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.5.5.tgz",
@ -5168,8 +5177,7 @@
"ansi-regex": {
"version": "2.1.1",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"aproba": {
"version": "1.2.0",
@ -5190,14 +5198,12 @@
"balanced-match": {
"version": "1.0.0",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@ -5212,20 +5218,17 @@
"code-point-at": {
"version": "1.1.0",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"core-util-is": {
"version": "1.0.2",
@ -5342,8 +5345,7 @@
"inherits": {
"version": "2.0.3",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"ini": {
"version": "1.3.5",
@ -5355,7 +5357,6 @@
"version": "1.0.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@ -5370,7 +5371,6 @@
"version": "3.0.4",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@ -5378,14 +5378,12 @@
"minimist": {
"version": "0.0.8",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"minipass": {
"version": "2.3.5",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
@ -5404,7 +5402,6 @@
"version": "0.5.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"minimist": "0.0.8"
}
@ -5485,8 +5482,7 @@
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"object-assign": {
"version": "4.1.1",
@ -5498,7 +5494,6 @@
"version": "1.4.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"wrappy": "1"
}
@ -5584,8 +5579,7 @@
"safe-buffer": {
"version": "5.1.2",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"safer-buffer": {
"version": "2.1.2",
@ -5621,7 +5615,6 @@
"version": "1.0.2",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@ -5641,7 +5634,6 @@
"version": "3.0.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@ -5685,14 +5677,12 @@
"wrappy": {
"version": "1.0.2",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"yallist": {
"version": "3.0.3",
"bundled": true,
"dev": true,
"optional": true
"dev": true
}
}
},

View File

@ -93,6 +93,7 @@
"@babel/cli": "^7.4.4",
"@babel/core": "^7.4.5",
"@babel/node": "^7.4.5",
"@babel/plugin-transform-object-assign": "^7.2.0",
"@babel/plugin-transform-runtime": "^7.4.4",
"@babel/preset-env": "^7.4.5",
"@babel/register": "^7.4.4",

View File

@ -45,6 +45,9 @@ const primedBabel = babel({
loose: true,
modules: false
}]
],
plugins: [
'@babel/plugin-transform-object-assign'
]
});

View File

@ -3,7 +3,6 @@
*/
import Component from './component';
import ModalDialog from './modal-dialog';
import mergeOptions from './utils/merge-options';
/**
* A display that indicates an error has occurred. This means that the video
@ -57,7 +56,7 @@ class ErrorDisplay extends ModalDialog {
*
* @private
*/
ErrorDisplay.prototype.options_ = mergeOptions(ModalDialog.prototype.options_, {
ErrorDisplay.prototype.options_ = Object.assign({}, ModalDialog.prototype.options_, {
pauseOnOpen: false,
fillAlways: true,
temporary: false,

View File

@ -13,6 +13,7 @@ import mergeOptions from '../utils/merge-options.js';
import {toTitleCase} from '../utils/string-cases.js';
import {NORMAL as TRACK_TYPES} from '../tracks/track-types';
import setupSourceset from './setup-sourceset';
import defineLazyProperty from '../utils/define-lazy-property.js';
/**
* HTML5 Media Controller - Wrapper for HTML5 Media API
@ -887,23 +888,27 @@ class Html5 extends Tech {
/* HTML5 Support Testing ---------------------------------------------------- */
if (Dom.isReal()) {
/**
* Element for testing browser HTML5 media capabilities
*
* @type {Element}
* @constant
* @private
*/
Html5.TEST_VID = document.createElement('video');
/**
* Element for testing browser HTML5 media capabilities
*
* @type {Element}
* @constant
* @private
*/
defineLazyProperty(Html5, 'TEST_VID', function() {
if (!Dom.isReal()) {
return;
}
const video = document.createElement('video');
const track = document.createElement('track');
track.kind = 'captions';
track.srclang = 'en';
track.label = 'English';
Html5.TEST_VID.appendChild(track);
}
video.appendChild(track);
return video;
});
/**
* Check if HTML5 media is supported by this browser/device.
@ -1115,15 +1120,12 @@ Html5.Events = [
* @type {boolean}
* @default {@link Html5.canControlVolume}
*/
Html5.prototype.featuresVolumeControl = Html5.canControlVolume();
/**
* Boolean indicating whether the `Tech` supports muting volume.
*
* @type {bolean}
* @default {@link Html5.canMuteVolume}
*/
Html5.prototype.featuresMuteControl = Html5.canMuteVolume();
/**
* Boolean indicating whether the `Tech` supports changing the speed at which the media
@ -1134,7 +1136,6 @@ Html5.prototype.featuresMuteControl = Html5.canMuteVolume();
* @type {boolean}
* @default {@link Html5.canControlPlaybackRate}
*/
Html5.prototype.featuresPlaybackRate = Html5.canControlPlaybackRate();
/**
* Boolean indicating whether the `Tech` supports the `sourceset` event.
@ -1142,7 +1143,35 @@ Html5.prototype.featuresPlaybackRate = Html5.canControlPlaybackRate();
* @type {boolean}
* @default
*/
Html5.prototype.featuresSourceset = Html5.canOverrideAttributes();
/**
* Boolean indicating whether the `HTML5` tech currently supports native `TextTrack`s.
*
* @type {boolean}
* @default {@link Html5.supportsNativeTextTracks}
*/
/**
* Boolean indicating whether the `HTML5` tech currently supports native `VideoTrack`s.
*
* @type {boolean}
* @default {@link Html5.supportsNativeVideoTracks}
*/
/**
* Boolean indicating whether the `HTML5` tech currently supports native `AudioTrack`s.
*
* @type {boolean}
* @default {@link Html5.supportsNativeAudioTracks}
*/
[
['featuresVolumeControl', 'canControlVolume'],
['featuresMuteControl', 'canMuteVolume'],
['featuresPlaybackRate', 'canControlPlaybackRate'],
['featuresSourceset', 'canOverrideAttributes'],
['featuresNativeTextTracks', 'supportsNativeTextTracks'],
['featuresNativeVideoTracks', 'supportsNativeVideoTracks'],
['featuresNativeAudioTracks', 'supportsNativeAudioTracks']
].forEach(function([key, fn]) {
defineLazyProperty(Html5.prototype, key, () => Html5[fn](), false);
});
/**
* Boolean indicating whether the `HTML5` tech currently supports the media element
@ -1182,40 +1211,18 @@ Html5.prototype.featuresProgressEvents = true;
*/
Html5.prototype.featuresTimeupdateEvents = true;
/**
* Boolean indicating whether the `HTML5` tech currently supports native `TextTrack`s.
*
* @type {boolean}
* @default {@link Html5.supportsNativeTextTracks}
*/
Html5.prototype.featuresNativeTextTracks = Html5.supportsNativeTextTracks();
/**
* Boolean indicating whether the `HTML5` tech currently supports native `VideoTrack`s.
*
* @type {boolean}
* @default {@link Html5.supportsNativeVideoTracks}
*/
Html5.prototype.featuresNativeVideoTracks = Html5.supportsNativeVideoTracks();
/**
* Boolean indicating whether the `HTML5` tech currently supports native `AudioTrack`s.
*
* @type {boolean}
* @default {@link Html5.supportsNativeAudioTracks}
*/
Html5.prototype.featuresNativeAudioTracks = Html5.supportsNativeAudioTracks();
// HTML5 Feature detection and Device Fixes --------------------------------- //
const canPlayType = Html5.TEST_VID && Html5.TEST_VID.constructor.prototype.canPlayType;
const mpegurlRE = /^application\/(?:x-|vnd\.apple\.)mpegurl/i;
let canPlayType;
Html5.patchCanPlayType = function() {
// Android 4.0 and above can play HLS to some extent but it reports being unable to do so
// Firefox and Chrome report correctly
if (browser.ANDROID_VERSION >= 4.0 && !browser.IS_FIREFOX && !browser.IS_CHROME) {
canPlayType = Html5.TEST_VID && Html5.TEST_VID.constructor.prototype.canPlayType;
Html5.TEST_VID.constructor.prototype.canPlayType = function(type) {
const mpegurlRE = /^application\/(?:x-|vnd\.apple\.)mpegurl/i;
if (type && mpegurlRE.test(type)) {
return 'maybe';
}
@ -1227,7 +1234,9 @@ Html5.patchCanPlayType = function() {
Html5.unpatchCanPlayType = function() {
const r = Html5.TEST_VID.constructor.prototype.canPlayType;
Html5.TEST_VID.constructor.prototype.canPlayType = canPlayType;
if (canPlayType) {
Html5.TEST_VID.constructor.prototype.canPlayType = canPlayType;
}
return r;
};

View File

@ -8,8 +8,6 @@ import AudioTrack from './audio-track';
import VideoTrack from './video-track';
import HTMLTrackElement from './html-track-element';
import mergeOptions from '../utils/merge-options';
/*
* This file contains all track properties that are used in
* player.js, tech.js, html5.js and possibly other techs in the future.
@ -55,7 +53,7 @@ const REMOTE = {
}
};
const ALL = mergeOptions(NORMAL, REMOTE);
const ALL = Object.assign({}, NORMAL, REMOTE);
REMOTE.names = Object.keys(REMOTE);
NORMAL.names = Object.keys(NORMAL);

View File

@ -0,0 +1,33 @@
/**
* Object.defineProperty but "lazy", which means that the value is only set after
* it retrieved the first time, rather than being set right away.
*
* @param {Object} obj the object to set the property on
* @param {string} key the key for the property to set
* @param {Function} getValue the function used to get the value when it is needed.
* @param {boolean} setter wether a setter shoould be allowed or not
*/
const defineLazyProperty = function(obj, key, getValue, setter = true) {
const set = (value) =>
Object.defineProperty(obj, key, {value, enumerable: true, writable: true});
const options = {
configurable: true,
enumerable: true,
get() {
const value = getValue();
set(value);
return value;
}
};
if (setter) {
options.set = set;
}
return Object.defineProperty(obj, key, options);
};
export default defineLazyProperty;

View File

@ -20,7 +20,12 @@ import computedStyle from './computed-style';
*
*/
function isNonBlankString(str) {
return typeof str === 'string' && (/\S/).test(str);
// we use str.trim as it will trim any whitespace characters
// from the front or back of non-whitespace characters. aka
// Any string that contains non-whitespace characters will
// still contain them after `trim` but whitespace only strings
// will have a length of 0, failing this check.
return typeof str === 'string' && Boolean(str.trim());
}
/**
@ -35,7 +40,8 @@ function isNonBlankString(str) {
* Throws an error if there is whitespace in the string.
*/
function throwIfWhitespace(str) {
if ((/\s/).test(str)) {
// str.indexOf instead of regex because str.indexOf is faster performance wise.
if (str.indexOf(' ') >= 0) {
throw new Error('class has illegal whitespace characters');
}
}
@ -159,7 +165,7 @@ export function createEl(tagName = 'div', properties = {}, attributes = {}, cont
// method for it.
} else if (propName === 'textContent') {
textContent(el, val);
} else {
} else if (el[propName] !== val) {
el[propName] = val;
}
});

View File

@ -87,6 +87,9 @@ function _handleMultipleEvents(fn, elem, types, callback) {
* Fixed event object.
*/
export function fixEvent(event) {
if (event.fixed_) {
return event;
}
function returnTrue() {
return true;
@ -201,6 +204,7 @@ export function fixEvent(event) {
}
}
event.fixed_ = true;
// Returns fixed-up instance
return event;
}
@ -208,22 +212,27 @@ export function fixEvent(event) {
/**
* Whether passive event listeners are supported
*/
let _supportsPassive = false;
let _supportsPassive;
(function() {
try {
const opts = Object.defineProperty({}, 'passive', {
get() {
_supportsPassive = true;
}
});
const supportsPassive = function() {
if (typeof _supportsPassive !== 'boolean') {
_supportsPassive = false;
try {
const opts = Object.defineProperty({}, 'passive', {
get() {
_supportsPassive = true;
}
});
window.addEventListener('test', null, opts);
window.removeEventListener('test', null, opts);
} catch (e) {
// disregard
window.addEventListener('test', null, opts);
window.removeEventListener('test', null, opts);
} catch (e) {
// disregard
}
}
})();
return _supportsPassive;
};
/**
* Touch events Chrome expects to be passive
@ -310,7 +319,7 @@ export function on(elem, type, fn) {
if (elem.addEventListener) {
let options = false;
if (_supportsPassive &&
if (supportsPassive() &&
passiveEvents.indexOf(type) > -1) {
options = {passive: true};
}

View File

@ -31,6 +31,7 @@ import xhr from 'xhr';
// Include the built-in techs
import Tech from './tech/tech.js';
import { use as middlewareUse, TERMINATOR } from './tech/middleware.js';
import defineLazyProperty from './utils/define-lazy-property.js';
/**
* Normalize an `id` value by trimming off a leading `#`
@ -566,5 +567,7 @@ videojs.dom = Dom;
*/
videojs.url = Url;
videojs.defineLazyProperty = defineLazyProperty;
export default videojs;