diff --git a/lib/util/stream_utils.js b/lib/util/stream_utils.js index 9cdc80f06a..13d2ae12f1 100644 --- a/lib/util/stream_utils.js +++ b/lib/util/stream_utils.js @@ -501,6 +501,40 @@ shaka.util.StreamUtils = class { } + /** + * Constructs a string out of an object, similar to the JSON.stringify method. + * Unlike that method, this guarantees that the order of the keys is + * alphabetical, so it can be used as a way to reliably compare two objects. + * + * @param {!Object} obj + * @return {string} + * @private + */ + static alphabeticalKeyOrderStringify_(obj) { + const keys = []; + for (const key in obj) { + keys.push(key); + } + // Alphabetically sort the keys, so they will be in a reliable order. + keys.sort(); + + const terms = []; + for (const key of keys) { + const escapedKey = JSON.stringify(key); + const value = obj[key]; + if (value instanceof Object) { + const stringifiedValue = + shaka.util.StreamUtils.alphabeticalKeyOrderStringify_(value); + terms.push(escapedKey + ':' + stringifiedValue); + } else { + const escapedValue = JSON.stringify(value); + terms.push(escapedKey + ':' + escapedValue); + } + } + return '{' + terms.join(',') + '}'; + } + + /** * Queries mediaCapabilities for the decoding info for that decoding config, * and assigns it to the given variant. @@ -510,10 +544,14 @@ shaka.util.StreamUtils = class { * @private */ static async getDecodingInfosForVariant_(variant, decodingConfig) { + const cacheKey = + shaka.util.StreamUtils.alphabeticalKeyOrderStringify_(decodingConfig); + try { - const cacheKey = JSON.stringify(decodingConfig); - const cache = shaka.util.StreamUtils.decodingConfigCache; + const cache = shaka.util.StreamUtils.decodingConfigCache_; if (cache[cacheKey]) { + shaka.log.v2('Using cached results of mediaCapabilities.decodingInfo', + 'for key', cacheKey); variant.decodingInfos.push(cache[cacheKey]); } else { const result = @@ -1601,9 +1639,9 @@ shaka.util.StreamUtils = class { * (stringified) decodingConfig. * * @type {Object.<(!string), (!MediaCapabilitiesDecodingInfo)>} - * @export + * @private */ -shaka.util.StreamUtils.decodingConfigCache = {}; +shaka.util.StreamUtils.decodingConfigCache_ = {}; /** @private {number} */ diff --git a/test/test/boot.js b/test/test/boot.js index 6df7f23fce..4eb53b92e0 100644 --- a/test/test/boot.js +++ b/test/test/boot.js @@ -332,8 +332,8 @@ function configureJasmineEnvironment() { } // Reset decoding config cache after each test. - afterEach(() => { - shaka.util.StreamUtils.decodingConfigCache = {}; + afterEach(/** @suppress {accessControls} */ () => { + shaka.util.StreamUtils.decodingConfigCache_ = {}; }); // Code in karma-jasmine's adapter will malform test failures when the