From 3e7014db2b6f7f0bcad7da8dca6c6367bbcd42aa Mon Sep 17 00:00:00 2001 From: Joey Parrish Date: Wed, 9 Dec 2015 15:43:25 -0800 Subject: [PATCH] Fix library load and polyfill for old browsers This will allow support-testing to work on older browsers so that application developers can still load the library and query for support to show an appropriate error message. To accomplish this, we avoid load-time uses of Function.bind, avoid certain polyfills if modern types are not available, and compile down to ES3 to avoid errors caused by use of the reserved word "catch" on Promises. This has been tested back to IE6, Safari 5.1, iOS 6.0, Firefox 6, Chrome 15, and Opera 16. Change-Id: I9deed106a7736758e04452ef85bae40f37c6fe62 --- build/lib.sh | 2 +- build/wrapper.template.js | 2 +- lib/debug/log.js | 106 ++++++++++----------------- lib/polyfill/fullscreen.js | 5 ++ lib/polyfill/mediakeys.js | 8 +- lib/polyfill/patchedmediakeys_nop.js | 4 +- lib/polyfill/videoplaybackquality.js | 5 ++ 7 files changed, 59 insertions(+), 73 deletions(-) diff --git a/build/lib.sh b/build/lib.sh index 5409de581..f4de9c96f 100644 --- a/build/lib.sh +++ b/build/lib.sh @@ -33,7 +33,7 @@ GIT_VERSION=$(calculate_version) closure_opts=" --language_in ECMASCRIPT5 - --language_out ECMASCRIPT5 + --language_out ECMASCRIPT3 --jscomp_error=accessControls --jscomp_error=ambiguousFunctionDecl diff --git a/build/wrapper.template.js b/build/wrapper.template.js index 42604641e..f1ba595b7 100644 --- a/build/wrapper.template.js +++ b/build/wrapper.template.js @@ -1,5 +1,5 @@ (function(){var g={}; -(function(window){%output%}.bind(g,this))(); +(function(window){%output%}.call(g,this)); if (typeof(module)!="undefined"&&module.exports)module.exports=g.shaka; else if (typeof(define)!="undefined" && define.amd)define(function(){return g.shaka}); else this.shaka=g.shaka; diff --git a/lib/debug/log.js b/lib/debug/log.js index 0dee0cf5b..23797735a 100644 --- a/lib/debug/log.js +++ b/lib/debug/log.js @@ -69,75 +69,45 @@ shaka.log.v1 = function() {}; shaka.log.v2 = function() {}; -/** - * @private - * @param {string} logName - */ -shaka.log.patchConsole_ = function(logName) { - var nop = function() {}; - var logFunction = console[logName]; +// IE8 has no console unless it is opened in advance. +// IE9 console methods are not Functions and have no bind. +if (window.console && window.console.log.bind) { + if (!COMPILED) { + /** + * Change the log level. Useful for debugging in uncompiled mode. + * + * @param {number} level + */ + shaka.log.setLevel = function(level) { + var nop = function() {}; + var log = shaka.log; + var Level = shaka.log.Level; - if (!logFunction) { - console[logName] = nop; - } else if (!logFunction.bind) { - // IE 9 does not provide a .bind for the built-in logging functions. - console[logName] = function() { - logFunction.apply(console, arguments); + log.error = (level >= Level.ERROR) ? console.error.bind(console) : nop; + log.warning = (level >= Level.WARNING) ? console.warn.bind(console) : nop; + log.info = (level >= Level.INFO) ? console.info.bind(console) : nop; + log.debug = (level >= Level.DEBUG) ? console.log.bind(console) : nop; + log.v1 = (level >= Level.V1) ? console.debug.bind(console) : nop; + log.v2 = (level >= Level.V2) ? console.debug.bind(console) : nop; }; + } else { + if (shaka.log.MAX_LOG_LEVEL >= shaka.log.Level.ERROR) { + shaka.log.error = console.error.bind(console); + } + if (shaka.log.MAX_LOG_LEVEL >= shaka.log.Level.WARNING) { + shaka.log.warning = console.warn.bind(console); + } + if (shaka.log.MAX_LOG_LEVEL >= shaka.log.Level.INFO) { + shaka.log.info = console.info.bind(console); + } + if (shaka.log.MAX_LOG_LEVEL >= shaka.log.Level.DEBUG) { + shaka.log.debug = console.log.bind(console); + } + if (shaka.log.MAX_LOG_LEVEL >= shaka.log.Level.V1) { + shaka.log.v1 = console.debug.bind(console); + } + if (shaka.log.MAX_LOG_LEVEL >= shaka.log.Level.V2) { + shaka.log.v2 = console.debug.bind(console); + } } -}; - -shaka.log.patchConsole_('error'); -shaka.log.patchConsole_('warn'); -shaka.log.patchConsole_('info'); -shaka.log.patchConsole_('log'); -shaka.log.patchConsole_('debug'); - -if (!COMPILED) { - /** - * Change the log level. Useful for debugging in uncompiled mode. - * - * @param {number} level - */ - shaka.log.setLevel = function(level) { - var nop = function() {}; - var log = shaka.log; - var Level = shaka.log.Level; - - log.error = (level >= Level.ERROR) ? console.error.bind(console) : nop; - log.warning = (level >= Level.WARNING) ? console.warn.bind(console) : nop; - log.info = (level >= Level.INFO) ? console.info.bind(console) : nop; - log.debug = (level >= Level.DEBUG) ? console.log.bind(console) : nop; - log.v1 = (level >= Level.V1) ? console.debug.bind(console) : nop; - log.v2 = (level >= Level.V2) ? console.debug.bind(console) : nop; - }; -} - - -// Although these bindings are redundant with setLevel() above, refactoring to -// call a method here makes it so that the log messages themselves cannot be -// compiled out. - -if (shaka.log.MAX_LOG_LEVEL >= shaka.log.Level.ERROR) { - shaka.log.error = console.error.bind(console); -} - -if (shaka.log.MAX_LOG_LEVEL >= shaka.log.Level.WARNING) { - shaka.log.warning = console.warn.bind(console); -} - -if (shaka.log.MAX_LOG_LEVEL >= shaka.log.Level.INFO) { - shaka.log.info = console.info.bind(console); -} - -if (shaka.log.MAX_LOG_LEVEL >= shaka.log.Level.DEBUG) { - shaka.log.debug = console.log.bind(console); -} - -if (shaka.log.MAX_LOG_LEVEL >= shaka.log.Level.V1) { - shaka.log.v1 = console.debug.bind(console); -} - -if (shaka.log.MAX_LOG_LEVEL >= shaka.log.Level.V2) { - shaka.log.v2 = console.debug.bind(console); } diff --git a/lib/polyfill/fullscreen.js b/lib/polyfill/fullscreen.js index 5527d09dd..d16eee02c 100644 --- a/lib/polyfill/fullscreen.js +++ b/lib/polyfill/fullscreen.js @@ -34,6 +34,11 @@ goog.provide('shaka.polyfill.Fullscreen'); * @export */ shaka.polyfill.Fullscreen.install = function() { + if (!window.Document) { + // Avoid errors on very old browsers. + return; + } + var proto = Element.prototype; proto.requestFullscreen = proto.requestFullscreen || proto.mozRequestFullScreen || diff --git a/lib/polyfill/mediakeys.js b/lib/polyfill/mediakeys.js index 685be0465..389b3e520 100644 --- a/lib/polyfill/mediakeys.js +++ b/lib/polyfill/mediakeys.js @@ -43,7 +43,13 @@ goog.require('shaka.polyfill.PatchedMediaKeys.v20140218'); shaka.polyfill.MediaKeys.install = function() { shaka.log.debug('MediaKeys.install'); - if (Navigator.prototype.requestMediaKeySystemAccess && + if (!window.HTMLVideoElement) { + // Avoid errors on very old browsers. + return; + } + + if (window.Navigator && + Navigator.prototype.requestMediaKeySystemAccess && MediaKeySystemAccess.prototype.getConfiguration) { shaka.log.info('Using native EME as-is.'); } else if (HTMLMediaElement.prototype.webkitGenerateKeyRequest) { diff --git a/lib/polyfill/patchedmediakeys_nop.js b/lib/polyfill/patchedmediakeys_nop.js index 84aab809b..359e9f1d9 100644 --- a/lib/polyfill/patchedmediakeys_nop.js +++ b/lib/polyfill/patchedmediakeys_nop.js @@ -32,7 +32,7 @@ shaka.polyfill.PatchedMediaKeys.nop.install = function() { var nop = shaka.polyfill.PatchedMediaKeys.nop; // Install patches. - Navigator.prototype.requestMediaKeySystemAccess = + navigator.requestMediaKeySystemAccess = nop.requestMediaKeySystemAccess; // Delete mediaKeys to work around strict mode compatibility issues. delete HTMLMediaElement.prototype['mediaKeys']; @@ -57,7 +57,7 @@ shaka.polyfill.PatchedMediaKeys.nop.install = function() { shaka.polyfill.PatchedMediaKeys.nop.requestMediaKeySystemAccess = function(keySystem, supportedConfigurations) { shaka.log.debug('PatchedMediaKeys.nop.requestMediaKeySystemAccess'); - shaka.asserts.assert(this instanceof Navigator); + shaka.asserts.assert(this == navigator); return Promise.reject(new Error( 'The key system specified is not supported.')); diff --git a/lib/polyfill/videoplaybackquality.js b/lib/polyfill/videoplaybackquality.js index 4456079f8..b407e37ae 100644 --- a/lib/polyfill/videoplaybackquality.js +++ b/lib/polyfill/videoplaybackquality.js @@ -33,6 +33,11 @@ goog.provide('shaka.polyfill.VideoPlaybackQuality'); * @export */ shaka.polyfill.VideoPlaybackQuality.install = function() { + if (!window.HTMLVideoElement) { + // Avoid errors on very old browsers. + return; + } + var proto = HTMLVideoElement.prototype; if (proto.getVideoPlaybackQuality) { // No polyfill needed.