diff --git a/build/build.py b/build/build.py index b32e097348..839672cc05 100755 --- a/build/build.py +++ b/build/build.py @@ -54,7 +54,7 @@ shaka_version = shakaBuildHelpers.calculate_version() common_closure_opts = [ - '--language_out', 'ECMASCRIPT3', + '--language_out', 'ECMASCRIPT5', '--jscomp_error=*', diff --git a/build/conformance.textproto b/build/conformance.textproto index d6b52453d8..a2ffb71ef2 100644 --- a/build/conformance.textproto +++ b/build/conformance.textproto @@ -269,6 +269,7 @@ requirement: { whitelist_regexp: "demo/" whitelist_regexp: "test/" whitelist_regexp: "lib/util/delayed_tick.js" + whitelist_regexp: "lib/polyfill/abort_controller.js" } requirement: { type: BANNED_NAME diff --git a/build/types/polyfill b/build/types/polyfill index 93e134a177..f85956aba6 100644 --- a/build/types/polyfill +++ b/build/types/polyfill @@ -1,6 +1,7 @@ # Polyfills used to emulate missing browsers features. +../../node_modules/eme-encryption-scheme-polyfill/index.js ++../../lib/polyfill/abort_controller.js +../../lib/polyfill/aria.js +../../lib/polyfill/encryption_scheme.js +../../lib/polyfill/fullscreen.js diff --git a/lib/polyfill/abort_controller.js b/lib/polyfill/abort_controller.js new file mode 100644 index 0000000000..3ebf1acc6e --- /dev/null +++ b/lib/polyfill/abort_controller.js @@ -0,0 +1,143 @@ +/*! @license + * Shaka Player + * Copyright 2016 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +goog.provide('shaka.polyfill.AbortController'); + +goog.require('shaka.polyfill'); +goog.require('shaka.util.FakeEvent'); +goog.require('shaka.util.FakeEventTarget'); + +/** + * @summary A polyfill for systems that do not implement AbortController. + * This is used both with the fetch API for HTTP requests and inside the HLS + * parser. + * @export + * @extends AbortController + */ +shaka.polyfill.AbortController = class { + /** + * Install the polyfill if needed. + * @export + */ + static install() { + if (window.AbortController) { + // Not needed. + return; + } + + window.AbortController = shaka.polyfill.AbortController; + window.AbortSignal = shaka.polyfill.AbortController.AbortSignal; + } + + /** */ + constructor() { + /** @private {!shaka.polyfill.AbortController.AbortSignal} */ + this.signal_ = new shaka.polyfill.AbortController.AbortSignal(); + } + + /** + * @override + * @suppress {const|duplicate} Since the original is defined as "const", we + * need this suppression to override it. + */ + get signal() { + return this.signal_; + } + + /** + * @param {*=} reason + * @override + */ + abort(reason) { + this.signal_.doAbort_(reason); + } +}; + +/** + * @summary A polyfill for AbortSignal, part of the AbortController API. + * @implements {AbortSignal} + */ +shaka.polyfill.AbortController.AbortSignal = +class extends shaka.util.FakeEventTarget { + /** */ + constructor() { + super(); + + /** @private {boolean} */ + this.aborted_ = false; + + /** @private {*} */ + this.reason_ = undefined; + + /** @type {?function(!Event)} */ + this.onabort = null; + } + + /** @override */ + get aborted() { + return this.aborted_; + } + + /** @return {*} */ + get reason() { + return this.reason_; + } + + /** + * @param {*} reason + * @private + */ + doAbort_(reason) { + if (this.aborted_) { + return; + } + + this.aborted_ = true; + this.reason_ = reason; + if (this.reason_ === undefined) { + // This is equivalent to a native implementation. + this.reason_ = new DOMException( + 'signal is aborted without reason', 'AbortError'); + } + + // According to MDN: + // "Event type - A generic Event with no added properties." + const event = new shaka.util.FakeEvent('abort'); + if (this.onabort) { + this.onabort(event); + } + this.dispatchEvent(event); + } + + + /** + * @param {*=} reason + * @return {!AbortSignal} + */ + static abort(reason) { + const signal = new shaka.polyfill.AbortController.AbortSignal(); + signal.doAbort_(reason); + return signal; + } + + /** + * @param {number} timeMs + * @return {!AbortSignal} + */ + static timeout(timeMs) { + const signal = new shaka.polyfill.AbortController.AbortSignal(); + + window.setTimeout(() => { + // This is equivalent to a native implementation. + signal.doAbort_(new DOMException('signal timed out', 'TimeoutError')); + }, timeMs); + + return signal; + } +}; + + +shaka.polyfill.register(shaka.polyfill.AbortController.install); diff --git a/shaka-player.uncompiled.js b/shaka-player.uncompiled.js index 91f009ceae..880f0c4d79 100644 --- a/shaka-player.uncompiled.js +++ b/shaka-player.uncompiled.js @@ -32,6 +32,7 @@ goog.require('shaka.offline.OfflineManifestParser'); goog.require('shaka.offline.OfflineScheme'); goog.require('shaka.offline.Storage'); goog.require('shaka.offline.indexeddb.StorageMechanism'); +goog.require('shaka.polyfill.AbortController'); goog.require('shaka.polyfill.Aria'); goog.require('shaka.polyfill.EncryptionScheme'); goog.require('shaka.polyfill.Fullscreen');