hls.js
Version:
JavaScript HLS client using MediaSourceExtension
1,714 lines (1,495 loc) • 799 kB
JavaScript
(function (factory) {
typeof define === 'function' && define.amd ? define(factory) :
factory();
})((function () { 'use strict';
function getDefaultExportFromCjs (x) {
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
}
/**
* Create test stream
* @param {string} url
* @param {string} description
* @param {boolean} [live]
* @param {boolean} [abr]
* @param {string[]} [skip_ua]
* @returns {{url: string, description: string, live: boolean, abr: boolean, skip_ua: string[]}}
*/
var testStreams$1;
var hasRequiredTestStreams;
function requireTestStreams() {
if (hasRequiredTestStreams) return testStreams$1;
hasRequiredTestStreams = 1;
function createTestStream(url, description, live, abr, skip_ua) {
if (live === void 0) {
live = false;
}
if (abr === void 0) {
abr = true;
}
if (skip_ua === void 0) {
skip_ua = [];
}
return {
url: url,
description: description,
live: live,
abr: abr,
skip_ua: skip_ua
};
}
/**
* @param {Object} target
* @param {Object} [config]
* @returns {{url: string, description: string, live: boolean, abr: boolean, skip_ua: string[]}}
*/
function createTestStreamWithConfig(target, config) {
if (typeof target !== 'object') {
throw new Error('target should be object');
}
var testStream = createTestStream(target.url, target.description, target.live, target.abr, target.skip_ua);
testStream.config = config;
return testStream;
}
testStreams$1 = {
bbb: {
url: 'https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8',
description: 'Big Buck Bunny - adaptive qualities',
abr: true
},
fdr: {
url: 'https://cdn.jwplayer.com/manifests/pZxWPRg4.m3u8',
description: 'FDR - CDN packaged, 4s segments, 180p - 1080p',
abr: true
},
bigBuckBunny480p: {
url: 'https://test-streams.mux.dev/x36xhzz/url_6/193039199_mp4_h264_aac_hq_7.m3u8',
description: 'Big Buck Bunny - 480p only',
abr: false
},
arte: {
url: 'https://test-streams.mux.dev/test_001/stream.m3u8',
description: 'ARTE China,ABR',
abr: true
},
deltatreDAI: {
url: 'https://test-streams.mux.dev/dai-discontinuity-deltatre/manifest.m3u8',
description: 'Ad-insertion in event stream',
abr: false
},
issue666: {
url: 'https://playertest.longtailvideo.com/adaptive/issue666/playlists/cisq0gim60007xzvi505emlxx.m3u8',
description: 'Surveillance footage - https://github.com/video-dev/hls.js/issues/666',
abr: false
},
closedCaptions: {
url: 'https://playertest.longtailvideo.com/adaptive/captions/playlist.m3u8',
description: 'CNN special report, with CC',
abr: false
},
customIvBadDts: {
url: 'https://playertest.longtailvideo.com/adaptive/customIV/prog_index.m3u8',
description: 'Custom IV with bad PTS DTS',
abr: false
},
oceansAES: {
url: 'https://playertest.longtailvideo.com/adaptive/oceans_aes/oceans_aes.m3u8',
description: 'AES-128 encrypted, ABR',
abr: true
},
tracksWithAES: {
url: 'https://playertest.longtailvideo.com/adaptive/aes-with-tracks/master.m3u8',
description: 'AES-128 encrypted, TS main with AAC audio track',
abr: false
},
mp3Audio: {
url: 'https://playertest.longtailvideo.com/adaptive/vod-with-mp3/manifest.m3u8',
description: 'MP3 VOD demo',
abr: false
},
mpegAudioOnly: {
url: 'https://pl.streamingvideoprovider.com/mp3-playlist/playlist.m3u8',
description: 'MPEG Audio Only demo',
abr: false,
skip_ua: ['MicrosoftEdge', 'firefox']
},
fmp4: {
url: 'https://storage.googleapis.com/shaka-demo-assets/angel-one-hls/hls.m3u8',
description: 'HLS fMP4 Angel-One multiple audio-tracks',
abr: true
},
fmp4Bitmovin: {
url: 'https://bitdash-a.akamaihd.net/content/MI201109210084_1/m3u8s-fmp4/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.m3u8',
description: 'HLS fMP4 by Bitmovin',
abr: true
},
fmp4BitmovinHevc: {
url: 'https://bitmovin-a.akamaihd.net/content/dataset/multi-codec/hevc/stream_fmp4.m3u8',
description: 'HLS HEVC fMP4 by Bitmovin (Safari and Edge? only as of 2020-08)',
abr: true,
skipFunctionalTests: true
},
offset_pts: {
url: 'https://test-streams.mux.dev/pts_shift/master.m3u8',
description: 'DK Turntable, PTS shifted by 2.3s',
abr: true
},
angelOneShakaWidevine: createTestStreamWithConfig({
url: 'https://storage.googleapis.com/shaka-demo-assets/angel-one-widevine-hls/hls.m3u8',
description: 'Shaka-packager Widevine DRM (EME) HLS-fMP4 - Angel One Demo',
abr: true,
skip_ua: ['firefox', 'safari', {
name: 'chrome',
version: '75.0'
}, {
name: 'chrome',
version: '79.0'
}]
}, {
widevineLicenseUrl: 'https://cwip-shaka-proxy.appspot.com/no_auth',
emeEnabled: true
}),
audioOnlyMultipleLevels: {
url: 'https://s3.amazonaws.com/qa.jwplayer.com/~alex/121628/new_master.m3u8',
description: 'Multiple non-alternate audio levels',
abr: true
},
pdtDuplicate: {
url: 'https://playertest.longtailvideo.com/adaptive/artbeats/manifest.m3u8',
description: 'Duplicate sequential PDT values',
abr: false
},
pdtLargeGap: createTestStreamWithConfig({
url: 'https://playertest.longtailvideo.com/adaptive/boxee/playlist.m3u8',
description: 'PDTs with large gaps following discontinuities',
abr: false
}, {
// gaps are introduced by missing audio samples in the TS segments
// silent audio insertion can only prepend missing back to the last appended time provided there is room
// The discontinuities and starting offset of the timestamps do not allow prepending earlier than the start of the disco
allowedBufferedRangesInSeekTest: 7,
// Ignore "should buffer up to maxBufferLength" result
avBufferOffset: 39
}),
pdtBadValues: {
url: 'https://playertest.longtailvideo.com/adaptive/progdatime/playlist2.m3u8',
description: 'PDTs with bad values',
abr: false
},
pdtOneValue: {
url: 'https://playertest.longtailvideo.com/adaptive/aviion/manifest.m3u8',
description: 'One PDT, no discontinuities',
abr: false
},
noTrackIntersection: createTestStreamWithConfig({
url: 'https://s3.amazonaws.com/qa.jwplayer.com/~alex/123633/new_master.m3u8',
description: 'Audio/video track PTS values do not intersect; 10 second start gap',
abr: false
}, {
avBufferOffset: 10.5
}),
altAudioAndTracks: {
// url: 'https://wowzaec2demo.streamlock.net/vod-multitrack/_definst_/smil:ElephantsDream/elephantsdream2.smil/playlist.m3u',
url: 'https://playertest.longtailvideo.com/adaptive/elephants_dream_v4/index.m3u8',
description: 'Alternate audio tracks, and multiple VTT tracks',
vendor: 'wowza',
abr: true
},
altAudioAudioOnly: createTestStreamWithConfig({
url: 'https://playertest.longtailvideo.com/adaptive/alt-audio-no-video/sintel/playlist.m3u8',
description: 'Audio only with alternate audio track (Sintel)',
abr: false
}, {
// the playlist segment durations are longer than the media. So much so, that when seeking near the end,
// the timeline shifts roughly 10 seconds seconds back, and as a result buffering skips several segments
// to adjust for the currentTime now being places at the very end of the stream.
allowedBufferedRangesInSeekTest: 3
}),
altAudioMultiAudioOnly: {
url: 'https://playertest.longtailvideo.com/adaptive/alt-audio-no-video/angel-one.m3u8',
description: 'Audio only with multiple alternate audio tracks (Angel One)',
abr: false
},
muxedFmp4: {
url: 'https://s3.amazonaws.com/qa.jwplayer.com/hlsjs/muxed-fmp4/hls.m3u8',
description: 'Muxed av fmp4 - appended to "audiovideo" SourceBuffer',
abr: false
},
altAudioWithPdtAndStartGap: {
url: 'https://playertest.longtailvideo.com/adaptive/hls-test-streams/test-audio-pdt/playlist.m3u8',
description: 'PDT before each segment, 1.59s start gap',
// Disable smooth switch on this stream. Test is flakey because of what looks like (auto)play issue. To be expected with this large a gap (for now).
// abr: true,
startSeek: true
},
AppleAdvancedHevcAvcHls: {
url: 'https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_adv_example_hevc/master.m3u8',
description: 'Advanced stream (HEVC/H.264, AC-3/AAC, WebVTT, fMP4 segments)'
},
MuxLowLatencyHls: {
url: 'https://stream.mux.com/v69RSHhFelSm4701snP22dYz2jICy4E4FUyk02rW4gxRM.m3u8',
description: 'Low-Latency HLS sample of Big Buck Bunny loop and a timer. Restarts every 12 hours. (fMP4 segments)',
live: true
},
// AppleLowLatencyHls: {
// url: 'https://ll-hls-test.apple.com/master.m3u8',
// description: 'Apple Low-Latency HLS sample (TS segments)',
// live: true,
// },
// AppleLowLatencyCmafHls: {
// url: 'https://ll-hls-test.apple.com/cmaf/master.m3u8',
// description: 'Apple Low-Latency HLS sample (fMP4 segments)',
// live: true,
// },
groupIds: {
url: 'https://mtoczko.github.io/hls-test-streams/test-group/playlist.m3u8',
description: 'Group-id: subtitle and audio',
abr: true,
skipFunctionalTests: true
},
redundantLevelsWithTrackGroups: {
url: 'https://playertest.longtailvideo.com/adaptive/elephants_dream_v4/redundant.m3u8',
description: 'Redundant levels with subtitle and audio track groups',
abr: true,
skipFunctionalTests: true
},
startDelimiterOverlappingBetweenPESPackets: {
url: 'https://wistia.github.io/hlsjs-test-streams/assets/start-delimiter.m3u8',
description: "A stream with the start delimiter overlapping between PES packets.\n Related to https://github.com/video-dev/hls.js/issues/3834, where Apple Silicon chips throw decoding errors if\n NAL units are not starting right at the beginning of the PES packet when using hardware accelerated decoding.",
abr: false,
skipFunctionalTests: true
},
aes256: {
url: 'https://jvaryhlstests.blob.core.windows.net/hlstestdata/playlist_encrypted.m3u8',
description: 'aes-256 and aes-256-ctr full segment encryption',
abr: false
},
mpegTsHevcHls: {
url: 'https://devoldemar.github.io/streams/hls/bipbop/hevc.m3u8',
description: 'Advanced stream (HEVC Main 10, MPEG-TS segments)',
skipFunctionalTests: true
},
mpegTsBitmovinHevc: {
url: 'https://bitmovin-a.akamaihd.net/content/dataset/multi-codec/hevc/v720p_ts.m3u8',
description: 'HLS M2TS by Bitmovin (HEVC Main, many NALUs overflowing PESes, video only)',
abr: false,
skipFunctionalTests: true
}
};
return testStreams$1;
}
var main = {};
/*
Copyright (c) 2013, Rodrigo González, Sapienlab All Rights Reserved.
Available via MIT LICENSE. See https://github.com/roro89/jsonpack/blob/master/LICENSE.md for details.
*/
var hasRequiredMain;
function requireMain () {
if (hasRequiredMain) return main;
hasRequiredMain = 1;
(function (exports) {
(function(define) {
define([], function() {
var TOKEN_TRUE = -1;
var TOKEN_FALSE = -2;
var TOKEN_NULL = -3;
var TOKEN_EMPTY_STRING = -4;
var TOKEN_UNDEFINED = -5;
var pack = function(json, options) {
// Canonizes the options
options = options || {};
// A shorthand for debugging
var verbose = options.verbose || false;
verbose && console.log('Normalize the JSON Object');
// JSON as Javascript Object (Not string representation)
json = typeof json === 'string' ? this.JSON.parse(json) : json;
verbose && console.log('Creating a empty dictionary');
// The dictionary
var dictionary = {
strings : [],
integers : [],
floats : []
};
verbose && console.log('Creating the AST');
// The AST
var ast = (function recursiveAstBuilder(item) {
verbose && console.log('Calling recursiveAstBuilder with ' + this.JSON.stringify(item));
// The type of the item
var type = typeof item;
// Case 7: The item is null
if (item === null) {
return {
type : 'null',
index : TOKEN_NULL
};
}
//add undefined
if (typeof item === 'undefined') {
return {
type : 'undefined',
index : TOKEN_UNDEFINED
};
}
// Case 1: The item is Array Object
if ( item instanceof Array) {
// Create a new sub-AST of type Array (@)
var ast = ['@'];
// Add each items
for (var i in item) {
if (!item.hasOwnProperty(i)) continue;
ast.push(recursiveAstBuilder(item[i]));
}
// And return
return ast;
}
// Case 2: The item is Object
if (type === 'object') {
// Create a new sub-AST of type Object ($)
var ast = ['$'];
// Add each items
for (var key in item) {
if (!item.hasOwnProperty(key))
continue;
ast.push(recursiveAstBuilder(key));
ast.push(recursiveAstBuilder(item[key]));
}
// And return
return ast;
}
// Case 3: The item empty string
if (item === '') {
return {
type : 'empty',
index : TOKEN_EMPTY_STRING
};
}
// Case 4: The item is String
if (type === 'string') {
// The index of that word in the dictionary
var index = _indexOf.call(dictionary.strings, item);
// If not, add to the dictionary and actualize the index
if (index == -1) {
dictionary.strings.push(_encode(item));
index = dictionary.strings.length - 1;
}
// Return the token
return {
type : 'strings',
index : index
};
}
// Case 5: The item is integer
if (type === 'number' && item % 1 === 0) {
// The index of that number in the dictionary
var index = _indexOf.call(dictionary.integers, item);
// If not, add to the dictionary and actualize the index
if (index == -1) {
dictionary.integers.push(_base10To36(item));
index = dictionary.integers.length - 1;
}
// Return the token
return {
type : 'integers',
index : index
};
}
// Case 6: The item is float
if (type === 'number') {
// The index of that number in the dictionary
var index = _indexOf.call(dictionary.floats, item);
// If not, add to the dictionary and actualize the index
if (index == -1) {
// Float not use base 36
dictionary.floats.push(item);
index = dictionary.floats.length - 1;
}
// Return the token
return {
type : 'floats',
index : index
};
}
// Case 7: The item is boolean
if (type === 'boolean') {
return {
type : 'boolean',
index : item ? TOKEN_TRUE : TOKEN_FALSE
};
}
// Default
throw new Error('Unexpected argument of type ' + typeof (item));
})(json);
// A set of shorthands proxies for the length of the dictionaries
var stringLength = dictionary.strings.length;
var integerLength = dictionary.integers.length;
dictionary.floats.length;
verbose && console.log('Parsing the dictionary');
// Create a raw dictionary
var packed = dictionary.strings.join('|');
packed += '^' + dictionary.integers.join('|');
packed += '^' + dictionary.floats.join('|');
verbose && console.log('Parsing the structure');
// And add the structure
packed += '^' + (function recursiveParser(item) {
verbose && console.log('Calling a recursiveParser with ' + this.JSON.stringify(item));
// If the item is Array, then is a object of
// type [object Object] or [object Array]
if ( item instanceof Array) {
// The packed resulting
var packed = item.shift();
for (var i in item) {
if (!item.hasOwnProperty(i))
continue;
packed += recursiveParser(item[i]) + '|';
}
return (packed[packed.length - 1] === '|' ? packed.slice(0, -1) : packed) + ']';
}
// A shorthand proxies
var type = item.type, index = item.index;
if (type === 'strings') {
// Just return the base 36 of index
return _base10To36(index);
}
if (type === 'integers') {
// Return a base 36 of index plus stringLength offset
return _base10To36(stringLength + index);
}
if (type === 'floats') {
// Return a base 36 of index plus stringLength and integerLength offset
return _base10To36(stringLength + integerLength + index);
}
if (type === 'boolean') {
return item.index;
}
if (type === 'null') {
return TOKEN_NULL;
}
if (type === 'undefined') {
return TOKEN_UNDEFINED;
}
if (type === 'empty') {
return TOKEN_EMPTY_STRING;
}
throw new TypeError('The item is alien!');
})(ast);
verbose && console.log('Ending parser');
// If debug, return a internal representation of dictionary and stuff
if (options.debug)
return {
dictionary : dictionary,
ast : ast,
packed : packed
};
return packed;
};
var unpack = function(packed, options) {
// Canonizes the options
options = options || {};
// A raw buffer
var rawBuffers = packed.split('^');
// Create a dictionary
options.verbose && console.log('Building dictionary');
var dictionary = [];
// Add the strings values
var buffer = rawBuffers[0];
if (buffer !== '') {
buffer = buffer.split('|');
options.verbose && console.log('Parse the strings dictionary');
for (var i=0, n=buffer.length; i<n; i++){
dictionary.push(_decode(buffer[i]));
}
}
// Add the integers values
buffer = rawBuffers[1];
if (buffer !== '') {
buffer = buffer.split('|');
options.verbose && console.log('Parse the integers dictionary');
for (var i=0, n=buffer.length; i<n; i++){
dictionary.push(_base36To10(buffer[i]));
}
}
// Add the floats values
buffer = rawBuffers[2];
if (buffer !== '') {
buffer = buffer.split('|');
options.verbose && console.log('Parse the floats dictionary');
for (var i=0, n=buffer.length; i<n; i++){
dictionary.push(parseFloat(buffer[i]));
}
}
// Free memory
buffer = null;
options.verbose && console.log('Tokenizing the structure');
// Tokenizer the structure
var number36 = '';
var tokens = [];
var len=rawBuffers[3].length;
for (var i = 0; i < len; i++) {
var symbol = rawBuffers[3].charAt(i);
if (symbol === '|' || symbol === '$' || symbol === '@' || symbol === ']') {
if (number36) {
tokens.push(_base36To10(number36));
number36 = '';
}
symbol !== '|' && tokens.push(symbol);
} else {
number36 += symbol;
}
}
// A shorthand proxy for tokens.length
var tokensLength = tokens.length;
// The index of the next token to read
var tokensIndex = 0;
options.verbose && console.log('Starting recursive parser');
return (function recursiveUnpackerParser() {
// Maybe '$' (object) or '@' (array)
var type = tokens[tokensIndex++];
options.verbose && console.log('Reading collection type ' + (type === '$' ? 'object' : 'Array'));
// Parse an array
if (type === '@') {
var node = [];
for (; tokensIndex < tokensLength; tokensIndex++) {
var value = tokens[tokensIndex];
options.verbose && console.log('Read ' + value + ' symbol');
if (value === ']')
return node;
if (value === '@' || value === '$') {
node.push(recursiveUnpackerParser());
} else {
switch(value) {
case TOKEN_TRUE:
node.push(true);
break;
case TOKEN_FALSE:
node.push(false);
break;
case TOKEN_NULL:
node.push(null);
break;
case TOKEN_UNDEFINED:
node.push(undefined);
break;
case TOKEN_EMPTY_STRING:
node.push('');
break;
default:
node.push(dictionary[value]);
}
}
}
options.verbose && console.log('Parsed ' + this.JSON.stringify(node));
return node;
}
// Parse a object
if (type === '$') {
var node = {};
for (; tokensIndex < tokensLength; tokensIndex++) {
var key = tokens[tokensIndex];
if (key === ']')
return node;
if (key === TOKEN_EMPTY_STRING)
key = '';
else
key = dictionary[key];
var value = tokens[++tokensIndex];
if (value === '@' || value === '$') {
node[key] = recursiveUnpackerParser();
} else {
switch(value) {
case TOKEN_TRUE:
node[key] = true;
break;
case TOKEN_FALSE:
node[key] = false;
break;
case TOKEN_NULL:
node[key] = null;
break;
case TOKEN_UNDEFINED:
node[key] = undefined;
break;
case TOKEN_EMPTY_STRING:
node[key] = '';
break;
default:
node[key] = dictionary[value];
}
}
}
options.verbose && console.log('Parsed ' + this.JSON.stringify(node));
return node;
}
throw new TypeError('Bad token ' + type + ' isn\'t a type');
})();
};
var _encode = function(str) {
if ( typeof str !== 'string')
return str;
return str.replace(/[\+ \|\^\%]/g, function(a) {
return ({
' ' : '+',
'+' : '%2B',
'|' : '%7C',
'^' : '%5E',
'%' : '%25'
})[a]
});
};
var _decode = function(str) {
if ( typeof str !== 'string')
return str;
return str.replace(/\+|%2B|%7C|%5E|%25/g, function(a) {
return ({
'+' : ' ',
'%2B' : '+',
'%7C' : '|',
'%5E' : '^',
'%25' : '%'
})[a]
})
};
var _base10To36 = function(number) {
return Number.prototype.toString.call(number, 36).toUpperCase();
};
var _base36To10 = function(number) {
return parseInt(number, 36);
};
var _indexOf = Array.prototype.indexOf ||
function(obj, start) {
for (var i = (start || 0), j = this.length; i < j; i++) {
if (this[i] === obj) {
return i;
}
}
return -1;
};
return {
JSON : JSON,
pack : pack,
unpack : unpack
};
});
})( function(deps, factory) {
var jsonpack = factory();
for (var key in jsonpack)
exports[key] = jsonpack[key];
} );
} (main));
return main;
}
var mainExports = requireMain();
/**
* @this {Promise}
*/
function finallyConstructor(callback) {
var constructor = this.constructor;
return this.then(
function(value) {
// @ts-ignore
return constructor.resolve(callback()).then(function() {
return value;
});
},
function(reason) {
// @ts-ignore
return constructor.resolve(callback()).then(function() {
// @ts-ignore
return constructor.reject(reason);
});
}
);
}
function allSettled(arr) {
var P = this;
return new P(function(resolve, reject) {
if (!(arr && typeof arr.length !== 'undefined')) {
return reject(
new TypeError(
typeof arr +
' ' +
arr +
' is not iterable(cannot read property Symbol(Symbol.iterator))'
)
);
}
var args = Array.prototype.slice.call(arr);
if (args.length === 0) return resolve([]);
var remaining = args.length;
function res(i, val) {
if (val && (typeof val === 'object' || typeof val === 'function')) {
var then = val.then;
if (typeof then === 'function') {
then.call(
val,
function(val) {
res(i, val);
},
function(e) {
args[i] = { status: 'rejected', reason: e };
if (--remaining === 0) {
resolve(args);
}
}
);
return;
}
}
args[i] = { status: 'fulfilled', value: val };
if (--remaining === 0) {
resolve(args);
}
}
for (var i = 0; i < args.length; i++) {
res(i, args[i]);
}
});
}
/**
* @constructor
*/
function AggregateError(errors, message) {
(this.name = 'AggregateError'), (this.errors = errors);
this.message = message || '';
}
AggregateError.prototype = Error.prototype;
function any(arr) {
var P = this;
return new P(function(resolve, reject) {
if (!(arr && typeof arr.length !== 'undefined')) {
return reject(new TypeError('Promise.any accepts an array'));
}
var args = Array.prototype.slice.call(arr);
if (args.length === 0) return reject();
var rejectionReasons = [];
for (var i = 0; i < args.length; i++) {
try {
P.resolve(args[i])
.then(resolve)
.catch(function(error) {
rejectionReasons.push(error);
if (rejectionReasons.length === args.length) {
reject(
new AggregateError(
rejectionReasons,
'All promises were rejected'
)
);
}
});
} catch (ex) {
reject(ex);
}
}
});
}
// Store setTimeout reference so promise-polyfill will be unaffected by
// other code modifying setTimeout (like sinon.useFakeTimers())
var setTimeoutFunc = setTimeout;
function isArray(x) {
return Boolean(x && typeof x.length !== 'undefined');
}
function noop() {}
// Polyfill for Function.prototype.bind
function bind(fn, thisArg) {
return function() {
fn.apply(thisArg, arguments);
};
}
/**
* @constructor
* @param {Function} fn
*/
function Promise$1(fn) {
if (!(this instanceof Promise$1))
throw new TypeError('Promises must be constructed via new');
if (typeof fn !== 'function') throw new TypeError('not a function');
/** @type {!number} */
this._state = 0;
/** @type {!boolean} */
this._handled = false;
/** @type {Promise|undefined} */
this._value = undefined;
/** @type {!Array<!Function>} */
this._deferreds = [];
doResolve(fn, this);
}
function handle(self, deferred) {
while (self._state === 3) {
self = self._value;
}
if (self._state === 0) {
self._deferreds.push(deferred);
return;
}
self._handled = true;
Promise$1._immediateFn(function() {
var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected;
if (cb === null) {
(self._state === 1 ? resolve : reject)(deferred.promise, self._value);
return;
}
var ret;
try {
ret = cb(self._value);
} catch (e) {
reject(deferred.promise, e);
return;
}
resolve(deferred.promise, ret);
});
}
function resolve(self, newValue) {
try {
// Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
if (newValue === self)
throw new TypeError('A promise cannot be resolved with itself.');
if (
newValue &&
(typeof newValue === 'object' || typeof newValue === 'function')
) {
var then = newValue.then;
if (newValue instanceof Promise$1) {
self._state = 3;
self._value = newValue;
finale(self);
return;
} else if (typeof then === 'function') {
doResolve(bind(then, newValue), self);
return;
}
}
self._state = 1;
self._value = newValue;
finale(self);
} catch (e) {
reject(self, e);
}
}
function reject(self, newValue) {
self._state = 2;
self._value = newValue;
finale(self);
}
function finale(self) {
if (self._state === 2 && self._deferreds.length === 0) {
Promise$1._immediateFn(function() {
if (!self._handled) {
Promise$1._unhandledRejectionFn(self._value);
}
});
}
for (var i = 0, len = self._deferreds.length; i < len; i++) {
handle(self, self._deferreds[i]);
}
self._deferreds = null;
}
/**
* @constructor
*/
function Handler(onFulfilled, onRejected, promise) {
this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
this.onRejected = typeof onRejected === 'function' ? onRejected : null;
this.promise = promise;
}
/**
* Take a potentially misbehaving resolver function and make sure
* onFulfilled and onRejected are only called once.
*
* Makes no guarantees about asynchrony.
*/
function doResolve(fn, self) {
var done = false;
try {
fn(
function(value) {
if (done) return;
done = true;
resolve(self, value);
},
function(reason) {
if (done) return;
done = true;
reject(self, reason);
}
);
} catch (ex) {
if (done) return;
done = true;
reject(self, ex);
}
}
Promise$1.prototype['catch'] = function(onRejected) {
return this.then(null, onRejected);
};
Promise$1.prototype.then = function(onFulfilled, onRejected) {
// @ts-ignore
var prom = new this.constructor(noop);
handle(this, new Handler(onFulfilled, onRejected, prom));
return prom;
};
Promise$1.prototype['finally'] = finallyConstructor;
Promise$1.all = function(arr) {
return new Promise$1(function(resolve, reject) {
if (!isArray(arr)) {
return reject(new TypeError('Promise.all accepts an array'));
}
var args = Array.prototype.slice.call(arr);
if (args.length === 0) return resolve([]);
var remaining = args.length;
function res(i, val) {
try {
if (val && (typeof val === 'object' || typeof val === 'function')) {
var then = val.then;
if (typeof then === 'function') {
then.call(
val,
function(val) {
res(i, val);
},
reject
);
return;
}
}
args[i] = val;
if (--remaining === 0) {
resolve(args);
}
} catch (ex) {
reject(ex);
}
}
for (var i = 0; i < args.length; i++) {
res(i, args[i]);
}
});
};
Promise$1.any = any;
Promise$1.allSettled = allSettled;
Promise$1.resolve = function(value) {
if (value && typeof value === 'object' && value.constructor === Promise$1) {
return value;
}
return new Promise$1(function(resolve) {
resolve(value);
});
};
Promise$1.reject = function(value) {
return new Promise$1(function(resolve, reject) {
reject(value);
});
};
Promise$1.race = function(arr) {
return new Promise$1(function(resolve, reject) {
if (!isArray(arr)) {
return reject(new TypeError('Promise.race accepts an array'));
}
for (var i = 0, len = arr.length; i < len; i++) {
Promise$1.resolve(arr[i]).then(resolve, reject);
}
});
};
// Use polyfill for setImmediate for performance gains
Promise$1._immediateFn =
// @ts-ignore
(typeof setImmediate === 'function' &&
function(fn) {
// @ts-ignore
setImmediate(fn);
}) ||
function(fn) {
setTimeoutFunc(fn, 0);
};
Promise$1._unhandledRejectionFn = function _unhandledRejectionFn(err) {
if (typeof console !== 'undefined' && console) {
console.warn('Possible Unhandled Promise Rejection:', err); // eslint-disable-line no-console
}
};
/** @suppress {undefinedVars} */
var globalNS = (function() {
// the only reliable means to get the global object is
// `Function('return this')()`
// However, this causes CSP violations in Chrome apps.
if (typeof self !== 'undefined') {
return self;
}
if (typeof window !== 'undefined') {
return window;
}
if (typeof global !== 'undefined') {
return global;
}
throw new Error('unable to locate global object');
})();
// Expose the polyfill if Promise is undefined or set to a
// non-function value. The latter can be due to a named HTMLElement
// being exposed by browsers for legacy reasons.
// https://github.com/taylorhakes/promise-polyfill/issues/114
if (typeof globalNS['Promise'] !== 'function') {
globalNS['Promise'] = Promise$1;
} else {
if (!globalNS.Promise.prototype['finally']) {
globalNS.Promise.prototype['finally'] = finallyConstructor;
}
if (!globalNS.Promise.allSettled) {
globalNS.Promise.allSettled = allSettled;
}
if (!globalNS.Promise.any) {
globalNS.Promise.any = any;
}
}
function sortObject(obj) {
if (typeof obj !== 'object') {
return obj;
}
var temp = {};
var keys = [];
for (var key in obj) {
keys.push(key);
}
keys.sort();
for (var index in keys) {
temp[keys[index]] = sortObject(obj[keys[index]]);
}
return temp;
}
function copyTextToClipboard(text) {
var textArea = document.createElement('textarea');
textArea.value = text;
document.body.appendChild(textArea);
textArea.select();
try {
var successful = document.execCommand('copy');
var msg = successful ? 'successful' : 'unsuccessful';
console.log('Copying text command was ' + msg);
} catch (err) {
console.log('Oops, unable to copy');
}
document.body.removeChild(textArea);
}
function _defineProperties(e, r) {
for (var t = 0; t < r.length; t++) {
var o = r[t];
o.enumerable = o.enumerable || false, o.configurable = true, "value" in o && (o.writable = true), Object.defineProperty(e, _toPropertyKey(o.key), o);
}
}
function _createClass(e, r, t) {
return r && _defineProperties(e.prototype, r), Object.defineProperty(e, "prototype", {
writable: false
}), e;
}
function _extends() {
return _extends = Object.assign ? Object.assign.bind() : function (n) {
for (var e = 1; e < arguments.length; e++) {
var t = arguments[e];
for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
}
return n;
}, _extends.apply(null, arguments);
}
function _toPrimitive(t, r) {
if ("object" != typeof t || !t) return t;
var e = t[Symbol.toPrimitive];
if (void 0 !== e) {
var i = e.call(t, r);
if ("object" != typeof i) return i;
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return (String )(t);
}
function _toPropertyKey(t) {
var i = _toPrimitive(t, "string");
return "symbol" == typeof i ? i : i + "";
}
var Chart$2 = {exports: {}};
function commonjsRequire(path) {
throw new Error('Could not dynamically require "' + path + '". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.');
}
var moment$1 = {exports: {}};
var moment = moment$1.exports;
var hasRequiredMoment;
function requireMoment () {
if (hasRequiredMoment) return moment$1.exports;
hasRequiredMoment = 1;
(function (module, exports) {
(function (global, factory) {
module.exports = factory() ;
}(moment, (function () {
var hookCallback;
function hooks() {
return hookCallback.apply(null, arguments);
}
// This is done to register the method called with moment()
// without creating circular dependencies.
function setHookCallback(callback) {
hookCallback = callback;
}
function isArray(input) {
return (
input instanceof Array ||
Object.prototype.toString.call(input) === '[object Array]'
);
}
function isObject(input) {
// IE8 will treat undefined and null as object if it wasn't for
// input != null
return (
input != null &&
Object.prototype.toString.call(input) === '[object Object]'
);
}
function hasOwnProp(a, b) {
return Object.prototype.hasOwnProperty.call(a, b);
}
function isObjectEmpty(obj) {
if (Object.getOwnPropertyNames) {
return Object.getOwnPropertyNames(obj).length === 0;
} else {
var k;
for (k in obj) {
if (hasOwnProp(obj, k)) {
return false;
}
}
return true;
}
}
function isUndefined(input) {
return input === void 0;
}
function isNumber(input) {
return (
typeof input === 'number' ||
Object.prototype.toString.call(input) === '[object Number]'
);
}
function isDate(input) {
return (
input instanceof Date ||
Object.prototype.toString.call(input) === '[object Date]'
);
}
function map(arr, fn) {
var res = [],
i,
arrLen = arr.length;
for (i = 0; i < arrLen; ++i) {
res.push(fn(arr[i], i));
}
return res;
}
function extend(a, b) {
for (var i in b) {
if (hasOwnProp(b, i)) {
a[i] = b[i];
}
}
if (hasOwnProp(b, 'toString')) {
a.toString = b.toString;
}
if (hasOwnProp(b, 'valueOf')) {
a.valueOf = b.valueOf;
}
return a;
}
function createUTC(input, format, locale, strict) {
return createLocalOrUTC(input, format, locale, strict, true).utc();
}
function defaultParsingFlags() {
// We need to deep clone this object.
return {
empty: false,
unusedTokens: [],
unusedInput: [],
overflow: -2,
charsLeftOver: 0,
nullInput: false,
invalidEra: null,
invalidMonth: null,
invalidFormat: false,
userInvalidated: false,
iso: false,
parsedDateParts: [],
era: null,
meridiem: null,
rfc2822: false,
weekdayMismatch: false,
};
}
function getParsingFlags(m) {
if (m._pf == null) {
m._pf = defaultParsingFlags();
}
return m._pf;
}
var some;
if (Array.prototype.some) {
some = Array.prototype.some;
} else {
some = function (fun) {
var t = Object(this),
len = t.length >>> 0,
i;
for (i = 0; i < len; i++) {
if (i in t && fun.call(this, t[i], i, t)) {
return true;
}
}
return false;
};
}
function isValid(m) {
if (m._isValid == null) {
var flags = getParsingFlags(m),
parsedParts = some.call(flags.parsedDateParts, function (i) {
return i != null;
}),
isNowValid =
!isNaN(m._d.getTime()) &&
flags.overflow < 0 &&
!flags.empty &&
!flags.invalidEra &&
!flags.invalidMonth &&
!flags.invalidWeekday &&
!flags.weekdayMismatch &&
!flags.nullInput &&
!flags.invalidFormat &&
!flags.userInvalidated &&
(!flags.meridiem || (flags.meridiem && parsedParts));
if (m._strict) {
isNowValid =
isNowValid &&
flags.charsLeftOver === 0 &&
flags.unusedTokens.length === 0 &&
flags.bigHour === undefined;
}
if (Object.isFrozen == null || !Object.isFrozen(m)) {
m._isValid = isNowValid;
} else {
return isNowValid;
}
}
return m._isValid;
}
function createInvalid(flags) {
var m = createUTC(NaN);
if (flags != null) {
extend(getParsingFlags(m), flags);
} else {
getParsingFlags(m).userInvalidated = true;
}
return m;
}
// Plugins that add properties should also add the key here (null value),
// so we can properly clone ourselves.
var momentProperties = (hooks.momentProperties = []),
updateInProgress = false;
function copyConfig(to, from) {
var i,
prop,
val,
momentPropertiesLen = momentProperties.length;
if (!isUndefined(from._isAMomentObject)) {
to._isAMomentObject = from._isAMomentObject;
}
if (!isUndefined(from._i)) {
to._i = from._i;
}
if (!isUndefined(from._f)) {
to._f = from._f;
}
if (!isUndefined(from._l)) {
to._l = from._l;
}
if (!isUndefined(from._strict)) {
to._strict = from._strict;
}
if (!isUndefined(from._tzm)) {
to._tzm = from._tzm;
}
if (!isUndefined(from._isUTC)) {
to._isUTC = from._isUTC;
}
if (!isUndefined(from._offset)) {
to._offset = from._offset;
}
if (!isUndefined(from._pf)) {
to._pf = getParsingFlags(from);
}
if (!isUndefined(from._locale)) {
to._locale = from._locale;
}
if (momentPropertiesLen > 0) {
for (i = 0; i < momentPropertiesLen; i++) {
prop = momentProperties[i];
val = from[prop];
if (!isUndefined(val)) {
to[prop] = val;
}
}
}
return to;
}
// Moment prototype object
function Moment(config) {
copyConfig(this, config);
this._d = new Date(config._d != null ? config._d.getTime() : NaN);
if (!this.isValid()) {
this._d = new Date(NaN);
}
// Prevent infinite loop in case updateOffset creates new moment
// objects.
if (updateInProgress === false) {
updateInProgress = true;
hooks.updateOffset(this);
updateInProgress = false;
}
}
function isMoment(obj) {
return (
obj instanceof Moment || (obj != null && obj._isAMomentObject != null)
);
}
function warn(msg) {
if (
hooks.suppressDeprecationWarnings === false &&
typeof console !== 'undefined' &&
console.warn
) {
console.warn('Deprecation warning: ' + msg);
}
}
function deprecate(msg, fn) {
var firstTime = true;
return extend(function () {
if (hooks.deprecationHandler != null) {
hooks.deprecationHandler(null, msg);
}
if (firstTime) {
var args = [],
arg,
i,
key,
argLen = arguments.length;
for (i = 0; i < argLen; i++) {
arg = '';
if (typeof arguments[i] === 'object') {
arg += '\n[' + i + '] ';
for (key in arguments[0]) {
if (hasOwnProp(arguments[0], key)) {
arg += key + ': ' + arguments[0][key] + ', ';
}
}
arg = arg.slice(0, -2); // Remove trailing comma and space
} else {
arg = arguments[i];
}
args.push(arg);
}
warn(
msg +
'\nArguments: ' +
Array.prototype.slice.call(args).join('') +
'\n' +
new Error().stack
);
firstTime = false;
}
return fn.apply(this, arguments);
}, fn);
}
var deprecations = {};
function deprecateSimple(name, msg) {
if (hooks.deprecationHandler != null) {
hooks.deprecationHandler(name, msg);
}
if (!deprecations[name]) {
warn(msg);
deprecations[name] = true;
}
}
hooks.suppressDeprecationWarnings = false;
hooks.deprecationHandler = null;
function isFunction(input) {
return (
(typeof Function !== 'undefined' && input instanceof Function) ||
Object.prototype.toString.call(input) === '[object Function]'
);
}
function set(config) {
var prop, i;
for (i in config) {
if (hasOwnProp(config, i)) {
prop = config[i];
if (isFunction(prop)) {
this[i] = prop;
} else {
this['_' + i] = prop;
}
}
}
this._config = config;
// Lenient ordinal parsing accepts just a number in addition to
// number + (possibly) stuff coming from _dayOfMonthOrdinalParse.
// TODO: Remove "ordinalParse" fallback in next major release.
this._dayOfMonthOrdinalParseLenient = new RegExp(
(this._dayOfMonthOrdinalParse.source || this._ordinalParse.source) +
'|' +
/\d{1,2}/.source
);
}
function mergeConfigs(parentConfig, childConfig) {
var res = extend({}, parentConfig),
prop;
for (prop in childConfig) {
if (hasOwnProp(childConfig, prop)) {
if (isObject(parentConfig[prop]) && isObject(childConfig[prop])) {
res[prop] = {};
extend(res[prop], parentConfig[prop]);
extend(res[prop], childConfig[prop]);
} else if (childConfig[prop] != null) {
res[prop] = childConfig[prop];
} else {
delete res[prop];
}
}
}
for (prop in parentConfig) {
if (
hasOwnProp(parentConfig, prop) &&
!hasOwnProp(childConfig, prop) &&
isObject(parentConfig[prop])
) {
// make sure changes to properties don't modify parent config
res[prop] = extend({}, res[prop]);
}
}
return res;
}
function Locale(config) {
if (config != null) {
this.set(config);
}
}
var keys;
if (Object.keys) {
keys = Object.keys;
} else {
keys = function (obj) {
var i,
res = [];
for (i in obj) {
if (hasOwnProp(obj, i)) {
res.push(i);
}
}
return res;
};
}
var defaultCalendar = {
sameDay: '[Today at] LT',
nextDay: '[Tomorrow at] LT',
nextWeek: 'dddd [at] LT',
lastDay: '[Yesterday at] LT',
lastWeek: '[Last] dddd [at] LT',
sameElse: 'L',
};