From 3927c0c55250f0c9875d204a7e9ad62e75ed4872 Mon Sep 17 00:00:00 2001 From: Brandon Casey <2381475+brandonocasey@users.noreply.github.com> Date: Mon, 21 Sep 2020 12:37:02 -0400 Subject: [PATCH 001/399] fix: audio groups with the same uri as media do not count (#952) --- scripts/sources.json | 6 ++++++ src/media-groups.js | 21 ++++++++++++++++++++- test/master-playlist-controller.test.js | 8 ++++---- test/playback.test.js | 19 +++++++++++++++++++ 4 files changed, 49 insertions(+), 5 deletions(-) diff --git a/scripts/sources.json b/scripts/sources.json index f9edde78e..329dd12fe 100644 --- a/scripts/sources.json +++ b/scripts/sources.json @@ -297,5 +297,11 @@ "com.widevine.alpha": "https://amssamples.keydelivery.mediaservices.windows.net/Widevine/?KID=1ab45440-532c-4399-94dc-5c5ad9584bac", "com.microsoft.playready": "https://amssamples.keydelivery.mediaservices.windows.net/PlayReady/" } + }, + { + "name": "Big Buck Bunny Audio only, groups have same uri as renditons", + "uri": "https://d2zihajmogu5jn.cloudfront.net/audio-only-dupe-groups/prog_index.m3u8", + "mimetype": "application/x-mpegurl", + "features": [] } ] diff --git a/src/media-groups.js b/src/media-groups.js index 6941c9405..f1e4417b1 100644 --- a/src/media-groups.js +++ b/src/media-groups.js @@ -375,7 +375,7 @@ export const initialize = { sourceType, segmentLoaders: { [type]: segmentLoader }, requestOptions, - master: { mediaGroups }, + master: { mediaGroups, playlists }, mediaTypes: { [type]: { groups, @@ -398,9 +398,28 @@ export const initialize = { // List of playlists that have an AUDIO attribute value matching the current // group ID + const groupPlaylists = playlists.filter(playlist => { + return playlist.attributes[type] === groupId; + }); for (const variantLabel in mediaGroups[type][groupId]) { let properties = mediaGroups[type][groupId][variantLabel]; + + // List of playlists for the current group ID that have a matching uri with + // this alternate audio variant + const matchingPlaylists = groupPlaylists.filter(playlist => { + return playlist.resolvedUri === properties.resolvedUri; + }); + + if (matchingPlaylists.length) { + // If there is a playlist that has the same uri as this audio variant, assume + // that the playlist is audio only. We delete the resolvedUri property here + // to prevent a playlist loader from being created so that we don't have + // both the main and audio segment loaders loading the same audio segments + // from the same playlist. + delete properties.resolvedUri; + } + let playlistLoader; // if vhs-json was provided as the source, and the media playlist was resolved, diff --git a/test/master-playlist-controller.test.js b/test/master-playlist-controller.test.js index 0380805ef..8adcf9f21 100644 --- a/test/master-playlist-controller.test.js +++ b/test/master-playlist-controller.test.js @@ -3620,14 +3620,14 @@ QUnit.test('creates source buffers after second trackinfo if demuxed', function( '#EXTM3U\n' + '#EXT-X-VERSION:4\n' + '#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio",NAME="en",DEFAULT=YES,AUTOSELECT=YES,' + - 'LANGUAGE="en",URI="media.m3u8"\n' + + 'LANGUAGE="en",URI="media-audio.m3u8"\n' + '#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1,AUDIO="audio"\n' + 'media.m3u8\n' ); // video media this.standardXHRResponse(this.requests.shift()); // audio media - this.standardXHRResponse(this.requests.shift()); + this.standardXHRResponse(this.requests.shift(), manifests.media); assert.equal(createSourceBufferCalls.length, 0, 'have not created source buffers yet'); @@ -3903,7 +3903,7 @@ QUnit.test('uses codec info from manifest for source buffer creation even when d '#EXTM3U\n' + '#EXT-X-VERSION:4\n' + '#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio",NAME="en",DEFAULT=YES,AUTOSELECT=YES,' + - 'LANGUAGE="en",URI="media.m3u8"\n' + + 'LANGUAGE="en",URI="media-audio.m3u8"\n' + '#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1,AUDIO="audio",' + 'CODECS="mp4a.40.e, avc1.deadbeef"\n' + 'media.m3u8\n' @@ -3912,7 +3912,7 @@ QUnit.test('uses codec info from manifest for source buffer creation even when d // video media this.standardXHRResponse(this.requests.shift()); // audio media - this.standardXHRResponse(this.requests.shift()); + this.standardXHRResponse(this.requests.shift(), manifests.media); assert.equal(createSourceBufferCalls.length, 0, 'have not created source buffers yet'); diff --git a/test/playback.test.js b/test/playback.test.js index eec92b986..198e792dc 100644 --- a/test/playback.test.js +++ b/test/playback.test.js @@ -218,6 +218,25 @@ QUnit[testFn]('Big Buck Bunny', function(assert) { }); }); +QUnit[testFn]('Big Buck Bunny audio only, groups & renditions same uri', function(assert) { + const done = assert.async(); + + assert.expect(2); + const player = this.player; + + playFor(player, 2, function() { + assert.ok(true, 'played for at least two seconds'); + assert.equal(player.error(), null, 'has no player errors'); + + done(); + }); + + player.src({ + src: 'https://d2zihajmogu5jn.cloudfront.net/audio-only-dupe-groups/prog_index.m3u8', + type: 'application/x-mpegURL' + }); +}); + QUnit[testFn]('Live DASH', function(assert) { const done = assert.async(); From 31d34416fe937736ea9b4598924546bdc4b6306b Mon Sep 17 00:00:00 2001 From: Alex Barstow Date: Tue, 22 Sep 2020 17:38:28 -0400 Subject: [PATCH 002/399] fix: dash manifest not refreshed if only some playlists are updated (#949) --- src/dash-playlist-loader.js | 5 ++-- test/dash-playlist-loader.test.js | 44 +++++++++++++++++++------------ 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/src/dash-playlist-loader.js b/src/dash-playlist-loader.js index a887bab22..8a42e9fa7 100644 --- a/src/dash-playlist-loader.js +++ b/src/dash-playlist-loader.js @@ -61,7 +61,7 @@ export const parseMasterXml = ({ masterXml, srcUrl, clientOffset, sidxMapping }) * playlists merged in */ export const updateMaster = (oldMaster, newMaster) => { - let noChanges; + let noChanges = true; let update = mergeOptions(oldMaster, { // These are top level properties that can be updated duration: newMaster.duration, @@ -74,8 +74,7 @@ export const updateMaster = (oldMaster, newMaster) => { if (playlistUpdate) { update = playlistUpdate; - } else { - noChanges = true; + noChanges = false; } } diff --git a/test/dash-playlist-loader.test.js b/test/dash-playlist-loader.test.js index c19b83244..75245e75c 100644 --- a/test/dash-playlist-loader.test.js +++ b/test/dash-playlist-loader.test.js @@ -80,10 +80,15 @@ QUnit.test('updateMaster: returns falsy when there are no changes', function(ass QUnit.test('updateMaster: updates playlists', function(assert) { const master = { - playlists: { - length: 1, - 0: { uri: '0', id: '0' } + playlists: [{ + uri: '0', + id: '0' }, + { + uri: '1', + id: '1', + segments: [] + }], mediaGroups: { AUDIO: {}, SUBTITLES: {} @@ -92,15 +97,18 @@ QUnit.test('updateMaster: updates playlists', function(assert) { minimumUpdatePeriod: 0 }; + // Only the first playlist is changed const update = { - playlists: { - length: 1, - 0: { - id: '0', - uri: '0', - segments: [] - } + playlists: [{ + id: '0', + uri: '0', + segments: [] }, + { + uri: '1', + id: '1', + segments: [] + }], mediaGroups: { AUDIO: {}, SUBTITLES: {} @@ -112,14 +120,16 @@ QUnit.test('updateMaster: updates playlists', function(assert) { assert.deepEqual( updateMaster(master, update), { - playlists: { - length: 1, - 0: { - id: '0', - uri: '0', - segments: [] - } + playlists: [{ + id: '0', + uri: '0', + segments: [] }, + { + uri: '1', + id: '1', + segments: [] + }], mediaGroups: { AUDIO: {}, SUBTITLES: {} From 22694642fc53815f441560f14e36d74232fca9f3 Mon Sep 17 00:00:00 2001 From: Gary Katsevman Date: Wed, 23 Sep 2020 13:26:18 -0400 Subject: [PATCH 003/399] fix: use playlist NAME when available as its ID (#929) This is particularly used in DASH as the NAME is set from the Representation's ID which is specified to be unique per period and that across periods, the representations with the same ID should be functionally equivalent. This is important because in DASH, across periods, it's possible for Representations to be re-ordered, and we want to make sure that the reference doesn't get messed up when the period updates. It still sets up a reference to the playlist via the old name but if the ordering is changed it'll reference the incorrect playlist as it does now. --- src/dash-playlist-loader.js | 2 +- src/manifest.js | 25 ++++++++++--- test/dash-playlist-loader.test.js | 58 +++++++++++++++++++++++++++++-- test/manifests/dash-swapped.mpd | 24 +++++++++++++ 4 files changed, 101 insertions(+), 8 deletions(-) create mode 100644 test/manifests/dash-swapped.mpd diff --git a/src/dash-playlist-loader.js b/src/dash-playlist-loader.js index 8a42e9fa7..8c54b67b4 100644 --- a/src/dash-playlist-loader.js +++ b/src/dash-playlist-loader.js @@ -43,7 +43,7 @@ export const parseMasterXml = ({ masterXml, srcUrl, clientOffset, sidxMapping }) sidxMapping }); - addPropertiesToMaster(master, srcUrl); + addPropertiesToMaster(master, srcUrl, true); return master; }; diff --git a/src/manifest.js b/src/manifest.js index 3d5423756..29f1ec525 100644 --- a/src/manifest.js +++ b/src/manifest.js @@ -99,18 +99,32 @@ export const setupMediaPlaylist = ({ playlist, uri, id }) => { * * @param {Object} master * The master playlist + * @param {boolean} [useNameForId=false] + * Whether we should use the NAME property for ID. + * Generally only used for DASH and defaults to false. */ -export const setupMediaPlaylists = (master) => { +export const setupMediaPlaylists = (master, useNameForId) => { let i = master.playlists.length; while (i--) { const playlist = master.playlists[i]; + const createdId = createPlaylistID(i, playlist.uri); + let id = createdId; + + // If useNameForId is set, use the NAME attribute for the ID. + // Generally, this will be used for DASH because + // DASH Representations can change order across refreshes which can make referring to them by index not work. + if (useNameForId) { + id = playlist.attributes && playlist.attributes.NAME || id; + } setupMediaPlaylist({ playlist, - id: createPlaylistID(i, playlist.uri) + id }); playlist.resolvedUri = resolveUrl(master.uri, playlist.uri); + // make sure that if a useNameForId is true, the old "createdId" id is also available + master.playlists[createdId] = playlist; master.playlists[playlist.id] = playlist; // URI reference added for backwards compatibility master.playlists[playlist.uri] = playlist; @@ -187,8 +201,11 @@ export const masterForMedia = (media, uri) => { * Master manifest object * @param {string} uri * The source URI + * @param {boolean} [useNameForId=false] + * Whether we should use the NAME property for ID. + * Generally only used for DASH and defaults to false. */ -export const addPropertiesToMaster = (master, uri) => { +export const addPropertiesToMaster = (master, uri, useNameForId = false) => { master.uri = uri; for (let i = 0; i < master.playlists.length; i++) { @@ -221,6 +238,6 @@ export const addPropertiesToMaster = (master, uri) => { master.playlists[phonyUri] = properties.playlists[0]; }); - setupMediaPlaylists(master); + setupMediaPlaylists(master, useNameForId); resolveMediaGroupUris(master); }; diff --git a/test/dash-playlist-loader.test.js b/test/dash-playlist-loader.test.js index 75245e75c..aac25ea5b 100644 --- a/test/dash-playlist-loader.test.js +++ b/test/dash-playlist-loader.test.js @@ -1305,7 +1305,12 @@ QUnit.test('parseMasterXml: setup phony playlists and resolves uris', function(a assert.strictEqual(masterPlaylist.uri, loader.srcUrl, 'master playlist uri set correctly'); assert.strictEqual(masterPlaylist.playlists[0].uri, 'placeholder-uri-0'); - assert.strictEqual(masterPlaylist.playlists[0].id, '0-placeholder-uri-0'); + assert.strictEqual(masterPlaylist.playlists[0].id, '1080p'); + assert.strictEqual( + masterPlaylist.playlists['1080p'], + masterPlaylist.playlists['0-placeholder-uri-0'], + 'available via old and new ids' + ); assert.deepEqual( masterPlaylist.playlists['0-placeholder-uri-0'], masterPlaylist.playlists[0], @@ -1631,6 +1636,43 @@ QUnit.test('refreshXml_: updates media playlist reference if master changed', fu ); }); +QUnit.test('refreshXml_: keep reference to same playlist by id across mpd updates', function(assert) { + const loader = new DashPlaylistLoader('dash.mpd', this.fakeVhs); + + loader.load(); + this.standardXHRResponse(this.requests.shift()); + + const oldMaster = loader.master; + const oldMedia = loader.media(); + + loader.refreshXml_(); + + assert.strictEqual(this.requests.length, 1, 'manifest is being requested'); + + this.requests.shift().respond(200, null, testDataManifests['dash-swapped']); + + const newMaster = loader.master; + const newMedia = loader.media(); + + assert.notEqual(newMaster, oldMaster, 'master changed'); + assert.notEqual(newMedia, oldMedia, 'media changed'); + assert.equal( + newMedia, + newMaster.playlists[newMedia.id], + 'media from updated master' + ); + + // given that the only thing that changed in the new manifest is + // the mediaPresentationDuration and order of representations + // the old media and the new media should be equivalent. + // Comparing the attributes is an easy way to check. + assert.deepEqual( + newMedia.attributes, + oldMedia.attributes, + 'old media and new media references by same id' + ); +}); + QUnit.test('sidxRequestFinished_: updates master with sidx information', function(assert) { const loader = new DashPlaylistLoader('dash.mpd', this.fakeVhs); const fakePlaylist = { @@ -2268,9 +2310,14 @@ QUnit.test( 'setup phony uri for media playlist' ); assert.equal( - loader.master.playlists[0].id, '0-placeholder-uri-0', + loader.master.playlists[0].id, '1080p', 'setup phony id for media playlist' ); + assert.strictEqual( + loader.master.playlists['1080p'], + loader.master.playlists['0-placeholder-uri-0'], + 'reference by NAME and old id' + ); assert.strictEqual( loader.master.playlists['0-placeholder-uri-0'], loader.master.playlists[0], 'set reference by uri for easy access' @@ -2280,9 +2327,14 @@ QUnit.test( 'setup phony uri for media playlist' ); assert.equal( - loader.master.playlists[1].id, '1-placeholder-uri-1', + loader.master.playlists[1].id, '720p', 'setup phony id for media playlist' ); + assert.strictEqual( + loader.master.playlists['720p'], + loader.master.playlists['1-placeholder-uri-1'], + 'reference by NAME and old id' + ); assert.strictEqual( loader.master.playlists['1-placeholder-uri-1'], loader.master.playlists[1], 'set reference by uri for easy access' diff --git a/test/manifests/dash-swapped.mpd b/test/manifests/dash-swapped.mpd new file mode 100644 index 000000000..f6ee7fa3b --- /dev/null +++ b/test/manifests/dash-swapped.mpd @@ -0,0 +1,24 @@ + + + + main/ + + video/ + + 720/ + + + + 1080/ + + + + + audio/ + + 720/ + + + + + From 043ccc602446a636789f416f548b3401f619cc48 Mon Sep 17 00:00:00 2001 From: Brandon Casey <2381475+brandonocasey@users.noreply.github.com> Date: Wed, 23 Sep 2020 13:28:20 -0400 Subject: [PATCH 004/399] fix: report the correct buffered regardless of playlist change (#950) This also adds debug logging for checkBuffer_ so that we can determine troubleshoot issues such as this in the future. --- src/segment-loader.js | 66 ++++++++++++++++++++++++------------- test/segment-loader.test.js | 49 +++++++++++++++++++++++++++ 2 files changed, 93 insertions(+), 22 deletions(-) diff --git a/src/segment-loader.js b/src/segment-loader.js index be2d33c1e..ddd68bbbd 100644 --- a/src/segment-loader.js +++ b/src/segment-loader.js @@ -632,12 +632,12 @@ export default class SegmentLoader extends videojs.EventTarget { * TimeRange object representing the current buffered ranges */ buffered_() { - if (!this.sourceUpdater_ || !this.startingMedia_) { + if (!this.sourceUpdater_ || !this.mediaConfig_) { return videojs.createTimeRanges(); } if (this.loaderType_ === 'main') { - const { hasAudio, hasVideo, isMuxed } = this.startingMedia_; + const { hasAudio, hasVideo, isMuxed } = this.mediaConfig_; if (hasVideo && hasAudio && !this.audioDisabled_ && !isMuxed) { return this.sourceUpdater_.buffered(); @@ -1089,12 +1089,6 @@ export default class SegmentLoader extends videojs.EventTarget { return; } - if (segmentInfo.mediaIndex === this.playlist_.segments.length - 1 && - this.mediaSource_.readyState === 'ended' && - !this.seeking_()) { - return; - } - segmentInfo.timestampOffset = timestampOffsetForSegment({ segmentTimeline: segmentInfo.timeline, currentTimeline: this.currentTimeline_, @@ -1150,9 +1144,8 @@ export default class SegmentLoader extends videojs.EventTarget { * @param {Object} syncPoint - a segment info object that describes the * @return {Object} a segment request object that describes the segment to load */ - checkBuffer_(buffered, playlist, mediaIndex, hasPlayed, currentTime, syncPoint) { + checkBuffer_(buffered, playlist, currentMediaIndex, hasPlayed, currentTime, syncPoint) { let lastBufferedEnd = 0; - let startOfSegment; if (buffered.length) { lastBufferedEnd = buffered.end(buffered.length - 1); @@ -1176,31 +1169,33 @@ export default class SegmentLoader extends videojs.EventTarget { return null; } + let nextMediaIndex = null; + let startOfSegment; + let isSyncRequest = false; + // When the syncPoint is null, there is no way of determining a good // conservative segment index to fetch from // The best thing to do here is to get the kind of sync-point data by // making a request if (syncPoint === null) { - mediaIndex = this.getSyncSegmentCandidate_(playlist); - return this.generateSegmentInfo_(playlist, mediaIndex, null, true); - } - + nextMediaIndex = this.getSyncSegmentCandidate_(playlist); + isSyncRequest = true; + } else if (currentMediaIndex !== null) { // Under normal playback conditions fetching is a simple walk forward - if (mediaIndex !== null) { - const segment = playlist.segments[mediaIndex]; + const segment = playlist.segments[currentMediaIndex]; if (segment && segment.end) { startOfSegment = segment.end; } else { startOfSegment = lastBufferedEnd; } - return this.generateSegmentInfo_(playlist, mediaIndex + 1, startOfSegment, false); - } + + nextMediaIndex = currentMediaIndex + 1; // There is a sync-point but the lack of a mediaIndex indicates that // we need to make a good conservative guess about which segment to // fetch - if (this.fetchAtBuffer_) { + } else if (this.fetchAtBuffer_) { // Find the segment containing the end of the buffer const mediaSourceInfo = Playlist.getMediaInfoForTime( playlist, @@ -1209,7 +1204,7 @@ export default class SegmentLoader extends videojs.EventTarget { syncPoint.time ); - mediaIndex = mediaSourceInfo.mediaIndex; + nextMediaIndex = mediaSourceInfo.mediaIndex; startOfSegment = mediaSourceInfo.startTime; } else { // Find the segment containing currentTime @@ -1220,11 +1215,35 @@ export default class SegmentLoader extends videojs.EventTarget { syncPoint.time ); - mediaIndex = mediaSourceInfo.mediaIndex; + nextMediaIndex = mediaSourceInfo.mediaIndex; startOfSegment = mediaSourceInfo.startTime; } - return this.generateSegmentInfo_(playlist, mediaIndex, startOfSegment, false); + const segmentInfo = this.generateSegmentInfo_(playlist, nextMediaIndex, startOfSegment, isSyncRequest); + + if (!segmentInfo) { + return; + } + + // if this is the last segment in the playlist + // we are not seeking and end of stream has already been called + // do not re-request + if (this.mediaSource_ && this.playlist_ && segmentInfo.mediaIndex === this.playlist_.segments.length - 1 && + this.mediaSource_.readyState === 'ended' && + !this.seeking_()) { + return; + } + + this.logger_(`checkBuffer_ returning ${segmentInfo.uri}`, { + segmentInfo, + playlist, + currentMediaIndex, + nextMediaIndex, + startOfSegment, + isSyncRequest + }); + + return segmentInfo; } /** @@ -1458,6 +1477,9 @@ export default class SegmentLoader extends videojs.EventTarget { video: true }; + // TODO: rename these variables to + // startingMediaInfo_ and currentMediaInfo_ + this.mediaConfig_ = trackInfo; this.startingMedia_ = trackInfo; this.logger_('trackinfo update', trackInfo); this.trigger('trackinfo'); diff --git a/test/segment-loader.test.js b/test/segment-loader.test.js index adf0ba622..533273c1b 100644 --- a/test/segment-loader.test.js +++ b/test/segment-loader.test.js @@ -3237,6 +3237,55 @@ QUnit.module('SegmentLoader', function(hooks) { ); }); }); + + QUnit.test('can get buffered between playlists', function(assert) { + return setupMediaSource(loader.mediaSource_, loader.sourceUpdater_).then(() => { + const playlist = playlistWithDuration(40); + + loader.playlist(playlist); + loader.load(); + this.clock.tick(1); + + // need to load content to have starting media + standardXHRResponse(this.requests.shift(), muxedSegment()); + return new Promise((resolve, reject) => { + loader.one('appended', resolve); + loader.one('error', reject); + }); + }).then(() => { + // mock the buffered values (easiest solution to test that segment-loader is + // calling the correct functions) + loader.sourceUpdater_.audioBuffered = + () => videojs.createTimeRanges([[2, 3], [5, 7]]); + loader.sourceUpdater_.videoBuffered = + () => videojs.createTimeRanges([[2, 6]]); + loader.sourceUpdater_.buffered = + () => videojs.createTimeRanges([[2, 3], [5, 6]]); + + timeRangesEqual( + loader.buffered_(), + videojs.createTimeRanges([[2, 3], [5, 6]]), + 'buffered reports intersection of audio and video buffers' + ); + const playlist2 = playlistWithDuration(40, {uri: 'playlist2.m3u8'}); + + loader.playlist(playlist2); + + timeRangesEqual( + loader.buffered_(), + videojs.createTimeRanges([[2, 3], [5, 6]]), + 'buffered reports intersection of audio and video buffers' + ); + + loader.load(); + + timeRangesEqual( + loader.buffered_(), + videojs.createTimeRanges([[2, 3], [5, 6]]), + 'buffered reports intersection of audio and video buffers' + ); + }); + }); }); }); From d0ef2983f1f9c799800eeba329446caa4d6d0336 Mon Sep 17 00:00:00 2001 From: Brandon Casey <2381475+brandonocasey@users.noreply.github.com> Date: Wed, 23 Sep 2020 13:31:30 -0400 Subject: [PATCH 005/399] fix: detect demuxed video underflow gaps (#948) --- src/playback-watcher.js | 50 ++++++++++++++++----- test/playback-watcher.test.js | 84 ++++++++++++++++++++++++++++++++--- test/test-helpers.js | 15 ++++++- 3 files changed, 130 insertions(+), 19 deletions(-) diff --git a/src/playback-watcher.js b/src/playback-watcher.js index 87a618a81..66d96f8e8 100644 --- a/src/playback-watcher.js +++ b/src/playback-watcher.js @@ -443,10 +443,15 @@ export default class PlaybackWatcher { return true; } + const sourceUpdater = this.tech_.vhs.masterPlaylistController_.sourceUpdater_; const buffered = this.tech_.buffered(); - const nextRange = Ranges.findNextRange(buffered, currentTime); + const videoUnderflow = this.videoUnderflow_({ + audioBuffered: sourceUpdater.audioBuffered(), + videoBuffered: sourceUpdater.videoBuffered(), + currentTime + }); - if (this.videoUnderflow_(nextRange, buffered, currentTime)) { + if (videoUnderflow) { // Even though the video underflowed and was stuck in a gap, the audio overplayed // the gap, leading currentTime into a buffered range. Seeking to currentTime // allows the video to catch up to the audio position without losing any audio @@ -459,6 +464,7 @@ export default class PlaybackWatcher { this.tech_.trigger({type: 'usage', name: 'hls-video-underflow'}); return true; } + const nextRange = Ranges.findNextRange(buffered, currentTime); // check for gap if (nextRange.length > 0) { @@ -512,18 +518,42 @@ export default class PlaybackWatcher { return false; } - videoUnderflow_(nextRange, buffered, currentTime) { - if (nextRange.length === 0) { + videoUnderflow_({videoBuffered, audioBuffered, currentTime}) { + // audio only content will not have video underflow :) + if (!videoBuffered) { + return; + } + let gap; + + // find a gap in demuxed content. + if (videoBuffered.length && audioBuffered.length) { + // in Chrome audio will continue to play for ~3s when we run out of video + // so we have to check that the video buffer did have some buffer in the + // past. + const lastVideoRange = Ranges.findRange(videoBuffered, currentTime - 3); + const videoRange = Ranges.findRange(videoBuffered, currentTime); + const audioRange = Ranges.findRange(audioBuffered, currentTime); + + if (audioRange.length && !videoRange.length && lastVideoRange.length) { + gap = {start: lastVideoRange.end(0), end: audioRange.end(0)}; + } + + // find a gap in muxed content. + } else { + const nextRange = Ranges.findNextRange(videoBuffered, currentTime); + // Even if there is no available next range, there is still a possibility we are // stuck in a gap due to video underflow. - const gap = this.gapFromVideoUnderflow_(buffered, currentTime); + if (!nextRange.length) { + gap = this.gapFromVideoUnderflow_(videoBuffered, currentTime); + } + } - if (gap) { - this.logger_(`Encountered a gap in video from ${gap.start} to ${gap.end}. ` + - `Seeking to current time ${currentTime}`); + if (gap) { + this.logger_(`Encountered a gap in video from ${gap.start} to ${gap.end}. ` + + `Seeking to current time ${currentTime}`); - return true; - } + return true; } return false; diff --git a/test/playback-watcher.test.js b/test/playback-watcher.test.js index 43a9a2852..64efa739c 100644 --- a/test/playback-watcher.test.js +++ b/test/playback-watcher.test.js @@ -151,7 +151,7 @@ QUnit.test('skips over gap in chrome without waiting event', function(assert) { assert.equal(hlsGapSkipEvents, 1, 'there is one skipped gap'); }); -QUnit.test('skips over gap in Chrome due to video underflow', function(assert) { +QUnit.test('skips over gap in Chrome due to muxed video underflow', function(assert) { let vhsVideoUnderflowEvents = 0; let hlsVideoUnderflowEvents = 0; @@ -166,10 +166,61 @@ QUnit.test('skips over gap in Chrome due to video underflow', function(assert) { } }); - this.player.tech_.buffered = () => { + // set an arbitrary source + this.player.src({ + src: 'master.m3u8', + type: 'application/vnd.apple.mpegurl' + }); + + // start playback normally + this.player.tech_.triggerReady(); + this.clock.tick(1); + standardXHRResponse(this.requests.shift()); + openMediaSource(this.player, this.clock); + this.player.tech_.trigger('play'); + this.player.tech_.trigger('playing'); + this.clock.tick(1); + + assert.equal(vhsVideoUnderflowEvents, 0, 'no video underflow event got triggered'); + assert.equal(hlsVideoUnderflowEvents, 0, 'no video underflow event got triggered'); + + const mpc = this.player.tech_.vhs.masterPlaylistController_; + + mpc.sourceUpdater_.videoBuffered = () => { return videojs.createTimeRanges([[0, 10], [10.1, 20]]); }; + this.player.currentTime(13); + + const seeks = []; + + this.player.tech_.setCurrentTime = (time) => { + seeks.push(time); + }; + + this.player.tech_.trigger('waiting'); + + assert.equal(seeks.length, 1, 'one seek'); + assert.equal(seeks[0], 13, 'player seeked to current time'); + assert.equal(vhsVideoUnderflowEvents, 1, 'triggered a video underflow event'); + assert.equal(hlsVideoUnderflowEvents, 1, 'triggered a video underflow event'); +}); + +QUnit.test('skips over gap in Chrome due to demuxed video underflow', function(assert) { + let vhsVideoUnderflowEvents = 0; + let hlsVideoUnderflowEvents = 0; + + this.player.autoplay(true); + + this.player.tech_.on('usage', (event) => { + if (event.name === 'vhs-video-underflow') { + vhsVideoUnderflowEvents++; + } + if (event.name === 'hls-video-underflow') { + hlsVideoUnderflowEvents++; + } + }); + // set an arbitrary source this.player.src({ src: 'master.m3u8', @@ -188,7 +239,17 @@ QUnit.test('skips over gap in Chrome due to video underflow', function(assert) { assert.equal(vhsVideoUnderflowEvents, 0, 'no video underflow event got triggered'); assert.equal(hlsVideoUnderflowEvents, 0, 'no video underflow event got triggered'); - this.player.currentTime(13); + const mpc = this.player.tech_.vhs.masterPlaylistController_; + + mpc.sourceUpdater_.videoBuffered = () => { + return videojs.createTimeRanges([[0, 15]]); + }; + + mpc.sourceUpdater_.audioBuffered = () => { + return videojs.createTimeRanges([[0, 20]]); + }; + + this.player.currentTime(18); const seeks = []; @@ -199,7 +260,7 @@ QUnit.test('skips over gap in Chrome due to video underflow', function(assert) { this.player.tech_.trigger('waiting'); assert.equal(seeks.length, 1, 'one seek'); - assert.equal(seeks[0], 13, 'player seeked to current time'); + assert.equal(seeks[0], 18, 'player seeked to current time'); assert.equal(vhsVideoUnderflowEvents, 1, 'triggered a video underflow event'); assert.equal(hlsVideoUnderflowEvents, 1, 'triggered a video underflow event'); }); @@ -429,7 +490,7 @@ QUnit.test('fires notifications when activated', function(assert) { this.player.tech_.currentTime = function() { return currentTime; }; - this.player.tech_.buffered = function() { + this.player.tech_.vhs.masterPlaylistController_.sourceUpdater_.videoBuffered = function() { return { length: buffered.length, start(i) { @@ -570,7 +631,16 @@ QUnit.test('corrects seek outside of seekable', function(assert) { currentTime: () => currentTime, // mocked out paused: () => false, - buffered: () => videojs.createTimeRanges() + buffered: () => videojs.createTimeRanges(), + trigger: () => {}, + vhs: { + masterPlaylistController_: { + sourceUpdater_: { + videoBuffered: () => {}, + audioBuffered: () => {} + } + } + } }; // waiting @@ -1078,7 +1148,7 @@ QUnit.module('PlaybackWatcher isolated functions', { } }); -QUnit.test('skips gap from video underflow', function(assert) { +QUnit.test('skips gap from muxed video underflow', function(assert) { assert.equal( this.playbackWatcher.gapFromVideoUnderflow_(videojs.createTimeRanges(), 0), null, diff --git a/test/test-helpers.js b/test/test-helpers.js index c562956b3..b352662dc 100644 --- a/test/test-helpers.js +++ b/test/test-helpers.js @@ -183,13 +183,24 @@ export const useFakeEnvironment = function(assert) { if (this.log && this.log[level] && this.log[level].restore) { if (assert) { const calls = (this.log[level].args || []).map((args) => { - return args.join(', '); + return args.reduce((acc, val) => { + if (acc) { + acc += ', '; + } + + acc += val; + + if (val.stack) { + acc += '\n' + val.stack; + } + return acc; + }, ''); }).join('\n '); assert.equal( this.log[level].callCount, 0, - 'no unexpected logs at level "' + level + '":\n ' + calls + 'no unexpected logs at level "' + level + '":\n' + calls ); } this.log[level].restore(); From ce4d6fdf9fdba2bc0f5ec0b417cb4890d7c52a84 Mon Sep 17 00:00:00 2001 From: Brandon Casey <2381475+brandonocasey@users.noreply.github.com> Date: Wed, 23 Sep 2020 15:17:31 -0400 Subject: [PATCH 006/399] fix: Throw a player error when trying to play DRM content without eme (#938) --- src/videojs-http-streaming.js | 13 ++++++++----- test/videojs-http-streaming.test.js | 27 +++++++++++++++++++++++++-- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/videojs-http-streaming.js b/src/videojs-http-streaming.js index 348b2c1b3..115193b55 100644 --- a/src/videojs-http-streaming.js +++ b/src/videojs-http-streaming.js @@ -136,7 +136,7 @@ const emeKeySystems = (keySystemOptions, videoPlaylist, audioPlaylist) => { audio: audioPlaylist && audioPlaylist.attributes && audioPlaylist.attributes.CODECS }; - if (!codecs.audio && codecs.video.split(',').length > 1) { + if (!codecs.audio && codecs.video && codecs.video.split(',').length > 1) { codecs.video.split(',').forEach(function(codec) { codec = codec.trim(); @@ -243,10 +243,6 @@ const setupEmeOptions = ({ audioMedia, mainPlaylists }) => { - if (!player.eme) { - return; - } - const sourceOptions = emeKeySystems(sourceKeySystems, media, audioMedia); if (!sourceOptions) { @@ -255,6 +251,13 @@ const setupEmeOptions = ({ player.currentSource().keySystems = sourceOptions; + // eme handles the rest of the setup, so if it is missing + // do nothing. + if (sourceOptions && !player.eme) { + videojs.log.warn('DRM encrypted source cannot be decrypted without a DRM plugin'); + return; + } + // works around https://bugs.chromium.org/p/chromium/issues/detail?id=895449 // in non-IE11 browsers. In IE11 this is too early to initialize media keys if (videojs.browser.IE_VERSION === 11 || !player.eme.initializeMediaKeys) { diff --git a/test/videojs-http-streaming.test.js b/test/videojs-http-streaming.test.js index dd6e64cd5..75c17a3b5 100644 --- a/test/videojs-http-streaming.test.js +++ b/test/videojs-http-streaming.test.js @@ -5765,9 +5765,9 @@ QUnit.module('setupEmeOptions', { } }); -QUnit.test('no error if no eme', function(assert) { +QUnit.test('no error if no eme and no key systems', function(assert) { const player = {}; - const sourceKeySystems = {}; + const sourceKeySystems = null; const media = {}; const audioMedia = {}; const mainPlaylists = []; @@ -5777,6 +5777,29 @@ QUnit.test('no error if no eme', function(assert) { assert.ok(true, 'no exception'); }); +QUnit.test('log error if no eme and we have key systems', function(assert) { + const sourceKeySystems = {}; + const media = {}; + const audioMedia = {}; + const mainPlaylists = []; + const src = {}; + const player = {currentSource: () => src}; + + let logWarn; + const origWarn = videojs.log.warn; + + videojs.log.warn = (line) => { + logWarn = line; + }; + + setupEmeOptions({ player, sourceKeySystems, media, audioMedia, mainPlaylists }); + + assert.equal(logWarn, 'DRM encrypted source cannot be decrypted without a DRM plugin', 'logs expected error'); + assert.ok(src.hasOwnProperty('keySystems'), 'source key systems was set'); + + videojs.log.warn = origWarn; +}); + QUnit.test('no initialize calls if no source key systems', function(assert) { let numInitializeCalls = 0; const player = { eme: { initializeMediaKeys: () => numInitializeCalls++ } }; From 7eb112dcc2366fe9abd619b2eee3c54e7350cddc Mon Sep 17 00:00:00 2001 From: Brandon Casey <2381475+brandonocasey@users.noreply.github.com> Date: Wed, 23 Sep 2020 15:18:58 -0400 Subject: [PATCH 007/399] fix: use TIME_FUDGE_FACTOR rather than rounding by decimal digits (#881) Currently, we ran into an issue with roundSignificantDigit because it is rounding integer whole numbers when it seems like it was only made to round floats. This can cause us to download multiple duplicate segments on slow connections. Instead, only round by TIME_FUDGE_FACTOR here. This will prevent us from having to do any rounding at all. --- src/playlist.js | 31 ++------------- test/playlist.test.js | 92 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+), 28 deletions(-) diff --git a/src/playlist.js b/src/playlist.js index 892b1aa6a..59a236157 100644 --- a/src/playlist.js +++ b/src/playlist.js @@ -5,6 +5,7 @@ */ import videojs from 'video.js'; import window from 'global/window'; +import {TIME_FUDGE_FACTOR} from './ranges.js'; const {createTimeRange} = videojs; @@ -329,32 +330,6 @@ export const seekable = function(playlist, expired, liveEdgePadding) { return createTimeRange(seekableStart, seekableEnd); }; -const isWholeNumber = function(num) { - return (num - Math.floor(num)) === 0; -}; - -const roundSignificantDigit = function(increment, num) { - // If we have a whole number, just add 1 to it - if (isWholeNumber(num)) { - return num + (increment * 0.1); - } - - const numDecimalDigits = num.toString().split('.')[1].length; - - for (let i = 1; i <= numDecimalDigits; i++) { - const scale = Math.pow(10, i); - const temp = num * scale; - - if (isWholeNumber(temp) || - i === numDecimalDigits) { - return (temp + increment) / scale; - } - } -}; - -const ceilLeastSignificantDigit = roundSignificantDigit.bind(null, 1); -const floorLeastSignificantDigit = roundSignificantDigit.bind(null, -1); - /** * Determine the index and estimated starting time of the segment that * contains a specified playback position in a media playlist. @@ -384,7 +359,7 @@ export const getMediaInfoForTime = function( if (startIndex > 0) { for (i = startIndex - 1; i >= 0; i--) { segment = playlist.segments[i]; - time += floorLeastSignificantDigit(segment.duration); + time += (segment.duration + TIME_FUDGE_FACTOR); if (time > 0) { return { mediaIndex: i, @@ -421,7 +396,7 @@ export const getMediaInfoForTime = function( // until we find a segment that contains `time` and return it for (i = startIndex; i < numSegments; i++) { segment = playlist.segments[i]; - time -= ceilLeastSignificantDigit(segment.duration); + time -= segment.duration + TIME_FUDGE_FACTOR; if (time < 0) { return { mediaIndex: i, diff --git a/test/playlist.test.js b/test/playlist.test.js index c2dda324c..c4e9a6de4 100644 --- a/test/playlist.test.js +++ b/test/playlist.test.js @@ -1226,6 +1226,98 @@ QUnit.test( } ); +QUnit.test('rounding down works', function(assert) { + const loader = new PlaylistLoader('media.m3u8', this.fakeVhs); + + loader.load(); + + this.requests.shift().respond( + 200, null, + '#EXTM3U\n' + + '#EXT-X-MEDIA-SEQUENCE:0\n' + + '#EXTINF:2,\n' + + '0.ts\n' + + '#EXTINF:2,\n' + + '1.ts\n' + + '#EXTINF:2,\n' + + '2.ts\n' + + '#EXTINF:2,\n' + + '3.ts\n' + + '#EXTINF:2,\n' + + '4.ts\n' + + '#EXTINF:2,\n' + + '5.ts\n' + + '#EXT-X-ENDLIST\n' + ); + + const media = loader.media(); + const fn = Playlist.getMediaInfoForTime; + + // 1 segment away + assert.equal(fn(media, 2.1, 0, 0).mediaIndex, 1, '1 away 2 is correct'); + assert.equal(fn(media, 4.1, 1, 2).mediaIndex, 2, '1 away 3 is correct '); + assert.equal(fn(media, 6.1, 2, 4).mediaIndex, 3, '1 away 4 is correct'); + assert.equal(fn(media, 8.1, 3, 6).mediaIndex, 4, '1 away 5 is correct'); + assert.equal(fn(media, 10.1, 4, 8).mediaIndex, 5, '1 away 6 is correct'); + + // 2 segment away + assert.equal(fn(media, 4.1, 0, 0).mediaIndex, 2, '2 away 3 is correct '); + assert.equal(fn(media, 6.1, 1, 2).mediaIndex, 3, '2 away 4 is correct'); + assert.equal(fn(media, 8.1, 2, 4).mediaIndex, 4, '2 away 5 is correct'); + assert.equal(fn(media, 10.1, 3, 6).mediaIndex, 5, '2 away 6 is correct'); + + // 3 segments away + assert.equal(fn(media, 6.1, 0, 0).mediaIndex, 3, '3 away 4 is correct'); + assert.equal(fn(media, 8.1, 1, 2).mediaIndex, 4, '3 away 5 is correct'); + assert.equal(fn(media, 10.1, 2, 4).mediaIndex, 5, '3 away 6 is correct'); +}); + +QUnit.test('rounding up works', function(assert) { + const loader = new PlaylistLoader('media.m3u8', this.fakeVhs); + + loader.load(); + + this.requests.shift().respond( + 200, null, + '#EXTM3U\n' + + '#EXT-X-MEDIA-SEQUENCE:0\n' + + '#EXTINF:2,\n' + + '0.ts\n' + + '#EXTINF:2,\n' + + '1.ts\n' + + '#EXTINF:2,\n' + + '2.ts\n' + + '#EXTINF:2,\n' + + '3.ts\n' + + '#EXTINF:2,\n' + + '4.ts\n' + + '#EXTINF:2,\n' + + '5.ts\n' + + '#EXT-X-ENDLIST\n' + ); + + const media = loader.media(); + const fn = Playlist.getMediaInfoForTime; + + // 1 segment away + assert.equal(fn(media, 0, 1, 2).mediaIndex, 0, '1 away 1 is correct'); + assert.equal(fn(media, 2.1, 2, 4).mediaIndex, 1, '1 away 2 is correct'); + assert.equal(fn(media, 4.1, 3, 6).mediaIndex, 2, '1 away 3 is correct'); + assert.equal(fn(media, 6.1, 4, 8).mediaIndex, 3, '1 away 4 is correct'); + assert.equal(fn(media, 8.1, 5, 10).mediaIndex, 4, '1 away 5 is correct'); + + // 2 segment away + assert.equal(fn(media, 0, 2, 4).mediaIndex, 0, '2 away 1 is correct'); + assert.equal(fn(media, 2.1, 3, 6).mediaIndex, 1, '2 away 2 is correct'); + assert.equal(fn(media, 4.1, 4, 8).mediaIndex, 2, '2 away 3 is correct'); + assert.equal(fn(media, 6.1, 5, 10).mediaIndex, 3, '2 away 4 is correct'); + + // 3 segments away + assert.equal(fn(media, 0, 3, 6).mediaIndex, 0, '3 away 1 is correct'); + assert.equal(fn(media, 2.1, 4, 8).mediaIndex, 1, '3 away 2 is correct'); + assert.equal(fn(media, 4.1, 5, 10).mediaIndex, 2, '3 away 3 is correct'); +}); + QUnit.test( 'returns the lower index when calculating for a segment boundary', function(assert) { From 8801d1c268814cf64cc8acd989b42bb1a044fd58 Mon Sep 17 00:00:00 2001 From: Brandon Casey <2381475+brandonocasey@users.noreply.github.com> Date: Wed, 23 Sep 2020 15:27:54 -0400 Subject: [PATCH 008/399] chore: mediaConfig_ -> staringMediaInfo_, startingMedia_ -> currentMediaInfo_ (#953) --- src/master-playlist-controller.js | 10 +++---- src/segment-loader.js | 35 ++++++++++++------------- test/master-playlist-controller.test.js | 22 ++++++++-------- test/segment-loader.test.js | 4 +-- test/videojs-http-streaming.test.js | 20 +++++++------- 5 files changed, 45 insertions(+), 46 deletions(-) diff --git a/src/master-playlist-controller.js b/src/master-playlist-controller.js index 281f0ea64..7df977405 100644 --- a/src/master-playlist-controller.js +++ b/src/master-playlist-controller.js @@ -808,8 +808,8 @@ export class MasterPlaylistController extends videojs.EventTarget { if (this.mediaTypes_.AUDIO.activePlaylistLoader) { // if the audio playlist loader exists, then alternate audio is active - if (!this.mainSegmentLoader_.startingMedia_ || - this.mainSegmentLoader_.startingMedia_.hasVideo) { + if (!this.mainSegmentLoader_.currentMediaInfo_ || + this.mainSegmentLoader_.currentMediaInfo_.hasVideo) { // if we do not know if the main segment loader contains video yet or if we // definitively know the main segment loader contains video, then we need to wait // for both main and audio segment loaders to call endOfStream @@ -1346,7 +1346,7 @@ export class MasterPlaylistController extends videojs.EventTarget { const usingAudioLoader = !!this.mediaTypes_.AUDIO.activePlaylistLoader; // one or both loaders has not loaded sufficently to get codecs - if (!this.mainSegmentLoader_.startingMedia_ || (usingAudioLoader && !this.audioSegmentLoader_.startingMedia_)) { + if (!this.mainSegmentLoader_.currentMediaInfo_ || (usingAudioLoader && !this.audioSegmentLoader_.currentMediaInfo_)) { return false; } @@ -1355,8 +1355,8 @@ export class MasterPlaylistController extends videojs.EventTarget { getCodecsOrExclude_() { const media = { - main: this.mainSegmentLoader_.startingMedia_ || {}, - audio: this.audioSegmentLoader_.startingMedia_ || {} + main: this.mainSegmentLoader_.currentMediaInfo_ || {}, + audio: this.audioSegmentLoader_.currentMediaInfo_ || {} }; // set "main" media equal to video diff --git a/src/segment-loader.js b/src/segment-loader.js index ddd68bbbd..aadfe68de 100644 --- a/src/segment-loader.js +++ b/src/segment-loader.js @@ -345,7 +345,8 @@ export default class SegmentLoader extends videojs.EventTarget { this.mediaSource_ = settings.mediaSource; this.vhs_ = settings.vhs; this.loaderType_ = settings.loaderType; - this.startingMedia_ = void 0; + this.currentMediaInfo_ = void 0; + this.startingMediaInfo_ = void 0; this.segmentMetadataTrack_ = settings.segmentMetadataTrack; this.goalBufferLength_ = settings.goalBufferLength; this.sourceType_ = settings.sourceType; @@ -632,12 +633,12 @@ export default class SegmentLoader extends videojs.EventTarget { * TimeRange object representing the current buffered ranges */ buffered_() { - if (!this.sourceUpdater_ || !this.mediaConfig_) { + if (!this.sourceUpdater_ || !this.startingMediaInfo_) { return videojs.createTimeRanges(); } if (this.loaderType_ === 'main') { - const { hasAudio, hasVideo, isMuxed } = this.mediaConfig_; + const { hasAudio, hasVideo, isMuxed } = this.startingMediaInfo_; if (hasVideo && hasAudio && !this.audioDisabled_ && !isMuxed) { return this.sourceUpdater_.buffered(); @@ -839,7 +840,7 @@ export default class SegmentLoader extends videojs.EventTarget { // out before we start adding more data this.resyncLoader(); } - this.startingMedia_ = void 0; + this.currentMediaInfo_ = void 0; this.trigger('playlistupdate'); // the rest of this function depends on `oldPlaylist` being defined @@ -978,7 +979,7 @@ export default class SegmentLoader extends videojs.EventTarget { end = this.duration_(); } - if (!this.sourceUpdater_ || !this.startingMedia_) { + if (!this.sourceUpdater_ || !this.currentMediaInfo_) { // nothing to remove if we haven't processed any media return; } @@ -997,7 +998,7 @@ export default class SegmentLoader extends videojs.EventTarget { this.sourceUpdater_.removeAudio(start, end, removeFinished); } - if (this.loaderType_ === 'main' && this.startingMedia_ && this.startingMedia_.hasVideo) { + if (this.loaderType_ === 'main' && this.currentMediaInfo_ && this.currentMediaInfo_.hasVideo) { this.gopBuffer_ = removeGopBuffer(this.gopBuffer_, start, end, this.timeMapping_); removesRemaining++; this.sourceUpdater_.removeVideo(start, end, removeFinished); @@ -1471,16 +1472,14 @@ export default class SegmentLoader extends videojs.EventTarget { // When we have track info, determine what media types this loader is dealing with. // Guard against cases where we're not getting track info at all until we are // certain that all streams will provide it. - if (!shallowEqual(this.startingMedia_, trackInfo)) { + if (!shallowEqual(this.currentMediaInfo_, trackInfo)) { this.appendInitSegment_ = { audio: true, video: true }; - // TODO: rename these variables to - // startingMediaInfo_ and currentMediaInfo_ - this.mediaConfig_ = trackInfo; - this.startingMedia_ = trackInfo; + this.startingMediaInfo_ = trackInfo; + this.currentMediaInfo_ = trackInfo; this.logger_('trackinfo update', trackInfo); this.trigger('trackinfo'); } @@ -1678,7 +1677,7 @@ export default class SegmentLoader extends videojs.EventTarget { // created together (before appending). Source buffer creation uses the presence of // audio and video data to determine whether to create audio/video source buffers, and // uses processed (transmuxed or parsed) media to determine the types required. - if (!this.startingMedia_) { + if (!this.currentMediaInfo_) { return true; } @@ -1728,7 +1727,7 @@ export default class SegmentLoader extends videojs.EventTarget { } if (!this.handlePartialData_) { - const {hasAudio, hasVideo, isMuxed} = this.startingMedia_; + const {hasAudio, hasVideo, isMuxed} = this.currentMediaInfo_; if (hasVideo && !segmentInfo.videoTimingInfo) { return false; @@ -1809,7 +1808,7 @@ export default class SegmentLoader extends videojs.EventTarget { segmentInfo[timingInfoPropertyForMedia(result.type)].start; } else { const useVideoTimingInfo = - this.loaderType_ === 'main' && this.startingMedia_.hasVideo; + this.loaderType_ === 'main' && this.currentMediaInfo_.hasVideo; let firstVideoFrameTimeForData; if (useVideoTimingInfo) { @@ -2372,7 +2371,7 @@ export default class SegmentLoader extends videojs.EventTarget { } waitForAppendsToComplete_(segmentInfo) { - if (!this.startingMedia_) { + if (!this.currentMediaInfo_) { this.error({ message: 'No starting media returned, likely due to an unsupported media format.', blacklistDuration: Infinity @@ -2383,7 +2382,7 @@ export default class SegmentLoader extends videojs.EventTarget { // Although transmuxing is done, appends may not yet be finished. Throw a marker // on each queue this loader is responsible for to ensure that the appends are // complete. - const {hasAudio, hasVideo, isMuxed} = this.startingMedia_; + const {hasAudio, hasVideo, isMuxed} = this.currentMediaInfo_; const waitForVideo = this.loaderType_ === 'main' && hasVideo; // TODO: does this break partial support for muxed content? const waitForAudio = !this.audioDisabled_ && hasAudio && !isMuxed; @@ -2452,7 +2451,7 @@ export default class SegmentLoader extends videojs.EventTarget { checkForIllegalMediaSwitch(trackInfo) { const illegalMediaSwitchError = - illegalMediaSwitch(this.loaderType_, this.startingMedia_, trackInfo); + illegalMediaSwitch(this.loaderType_, this.currentMediaInfo_, trackInfo); if (illegalMediaSwitchError) { this.error({ @@ -2508,7 +2507,7 @@ export default class SegmentLoader extends videojs.EventTarget { updateTimingInfoEnd_(segmentInfo) { segmentInfo.timingInfo = segmentInfo.timingInfo || {}; const useVideoTimingInfo = - this.loaderType_ === 'main' && this.startingMedia_.hasVideo; + this.loaderType_ === 'main' && this.currentMediaInfo_.hasVideo; const prioritizedTimingInfo = useVideoTimingInfo && segmentInfo.videoTimingInfo ? segmentInfo.videoTimingInfo : segmentInfo.audioTimingInfo; diff --git a/test/master-playlist-controller.test.js b/test/master-playlist-controller.test.js index 8adcf9f21..7834f8b7a 100644 --- a/test/master-playlist-controller.test.js +++ b/test/master-playlist-controller.test.js @@ -534,7 +534,7 @@ QUnit.test('resets everything for a fast quality change', function(assert) { origRemove.call(segmentLoader, start, end); }; - segmentLoader.startingMedia_ = { hasVideo: true }; + segmentLoader.currentMediaInfo_ = { hasVideo: true }; segmentLoader.audioDisabled_ = true; segmentLoader.sourceUpdater_.removeVideo = function(start, end) { @@ -1044,8 +1044,8 @@ QUnit.test('waits for both main and audio loaders to finish before calling endOf MPC.mainSegmentLoader_.on('ended', () => videoEnded++); MPC.audioSegmentLoader_.on('ended', () => audioEnded++); - MPC.mainSegmentLoader_.startingMedia_ = { hasVideo: true }; - MPC.audioSegmentLoader_.startingMedia_ = { hasAudio: true }; + MPC.mainSegmentLoader_.currentMediaInfo_ = { hasVideo: true }; + MPC.audioSegmentLoader_.currentMediaInfo_ = { hasAudio: true }; // master this.standardXHRResponse(this.requests.shift(), manifests.demuxed); @@ -2835,7 +2835,7 @@ QUnit.test('parses codec from audio only fmp4 init segment', function(assert) { }, 'parsed audio codec' ); - assert.deepEqual(loader.startingMedia_, { + assert.deepEqual(loader.currentMediaInfo_, { audioCodec: 'mp4a.40.2', hasAudio: true, hasVideo: false, @@ -2896,7 +2896,7 @@ QUnit.test('parses codec from video only fmp4 init segment', function(assert) { }, 'parsed video codec' ); - assert.deepEqual(loader.startingMedia_, { + assert.deepEqual(loader.currentMediaInfo_, { hasAudio: false, hasVideo: true, isFmp4: true, @@ -2957,7 +2957,7 @@ QUnit.test('parses codec from muxed fmp4 init segment', function(assert) { }, 'parsed video codec' ); - assert.deepEqual(loader.startingMedia_, { + assert.deepEqual(loader.currentMediaInfo_, { hasAudio: true, hasVideo: true, videoCodec: 'avc1.42c00d', @@ -4577,11 +4577,11 @@ QUnit.module('MasterPlaylistController codecs', { } = options; if (mainStartingMedia) { - this.mpc.mainSegmentLoader_.startingMedia_ = mainStartingMedia; + this.mpc.mainSegmentLoader_.currentMediaInfo_ = mainStartingMedia; } if (audioStartingMedia) { - this.mpc.audioSegmentLoader_.startingMedia_ = audioStartingMedia; + this.mpc.audioSegmentLoader_.currentMediaInfo_ = audioStartingMedia; } this.master = {mediaGroups: {AUDIO: {}}, playlists: []}; @@ -5165,7 +5165,7 @@ QUnit.test('main & audio loader only trackinfo works as expected', function(asse assert.equal(createBuffers, 0, 'createSourceBuffers not called'); assert.equal(switchBuffers, 0, 'addOrChangeSourceBuffers not called'); - this.mpc.audioSegmentLoader_.startingMedia_ = { + this.mpc.audioSegmentLoader_.currentMediaInfo_ = { hasVideo: false, hasAudio: true, audioCodec: 'mp4a.40.2' @@ -5179,7 +5179,7 @@ QUnit.test('main & audio loader only trackinfo works as expected', function(asse this.mpc.sourceUpdater_.ready = () => true; this.mpc.sourceUpdater_.canChangeType = () => true; - this.mpc.mainSegmentLoader_.startingMedia_ = { + this.mpc.mainSegmentLoader_.currentMediaInfo_ = { videoCodec: 'avc1.4c400e', hasVideo: true, hasAudio: false @@ -5195,7 +5195,7 @@ QUnit.test('main & audio loader only trackinfo works as expected', function(asse assert.equal(createBuffers, 1, 'createBuffers not called'); assert.equal(switchBuffers, 1, 'addOrChangeSourceBuffers called'); - this.mpc.audioSegmentLoader_.startingMedia_ = { + this.mpc.audioSegmentLoader_.currentMediaInfo_ = { hasVideo: false, hasAudio: true, audioCodec: 'mp4a.40.5' diff --git a/test/segment-loader.test.js b/test/segment-loader.test.js index 533273c1b..083c65e2e 100644 --- a/test/segment-loader.test.js +++ b/test/segment-loader.test.js @@ -3366,8 +3366,8 @@ QUnit.module('SegmentLoader: FMP4', function(hooks) { endTime: 2, text: 'test' }); - // set startingMedia_ - loader.startingMedia_ = {hasVideo: true, hasAudio: true}; + // set currentMediaInfo_ + loader.currentMediaInfo_ = {hasVideo: true, hasAudio: true}; loader.remove(0, 2); assert.equal(this.inbandTextTracks.CC1.cues.length, 0, 'all cues have been removed'); diff --git a/test/videojs-http-streaming.test.js b/test/videojs-http-streaming.test.js index 75c17a3b5..2383380a3 100644 --- a/test/videojs-http-streaming.test.js +++ b/test/videojs-http-streaming.test.js @@ -1652,7 +1652,7 @@ QUnit.test('does not blacklist compatible H.264 codec strings', function(assert) const master = this.player.tech_.vhs.playlists.master; const loader = this.player.tech_.vhs.masterPlaylistController_.mainSegmentLoader_; - loader.startingMedia_ = {hasVideo: true, hasAudio: true}; + loader.currentMediaInfo_ = {hasVideo: true, hasAudio: true}; loader.trigger('trackinfo'); assert.strictEqual( @@ -1697,7 +1697,7 @@ QUnit.test('does not blacklist compatible AAC codec strings', function(assert) { const loader = this.player.tech_.vhs.masterPlaylistController_.mainSegmentLoader_; const master = this.player.tech_.vhs.playlists.master; - loader.startingMedia_ = {hasVideo: true, hasAudio: true}; + loader.currentMediaInfo_ = {hasVideo: true, hasAudio: true}; loader.trigger('trackinfo'); assert.strictEqual( @@ -1758,7 +1758,7 @@ QUnit.test('blacklists incompatible playlists by codec, without codec switching' mpc.sourceUpdater_.canChangeType = () => false; - loader.startingMedia_ = {hasVideo: true, hasAudio: true}; + loader.currentMediaInfo_ = {hasVideo: true, hasAudio: true}; loader.trigger('trackinfo'); const playlists = master.playlists; @@ -1818,7 +1818,7 @@ QUnit.test('does not blacklist incompatible codecs with codec switching', functi mpc.sourceUpdater_.canChangeType = () => true; - loader.startingMedia_ = {hasVideo: true, hasAudio: true}; + loader.currentMediaInfo_ = {hasVideo: true, hasAudio: true}; loader.trigger('trackinfo'); const playlists = master.playlists; @@ -1882,17 +1882,17 @@ QUnit.test('blacklists fmp4 playlists by browser support', function(assert) { playlistLoader.media = () => playlists[0]; loader.mainStartingMedia_ = playlists[0]; - loader.startingMedia_ = {hasVideo: true, hasAudio: true, isFmp4: true}; + loader.currentMediaInfo_ = {hasVideo: true, hasAudio: true, isFmp4: true}; loader.trigger('trackinfo'); playlistLoader.media = () => playlists[1]; loader.mainStartingMedia_ = playlists[1]; - loader.startingMedia_ = {hasVideo: true, hasAudio: true, isFmp4: true}; + loader.currentMediaInfo_ = {hasVideo: true, hasAudio: true, isFmp4: true}; loader.trigger('trackinfo'); playlistLoader.media = () => playlists[2]; loader.mainStartingMedia_ = playlists[2]; - loader.startingMedia_ = {hasVideo: true, hasAudio: true, isFmp4: true}; + loader.currentMediaInfo_ = {hasVideo: true, hasAudio: true, isFmp4: true}; loader.trigger('trackinfo'); assert.strictEqual(playlists.length, 3, 'three playlists total'); @@ -1950,17 +1950,17 @@ QUnit.test('blacklists ts playlists by muxer support', function(assert) { playlistLoader.media = () => playlists[0]; loader.mainStartingMedia_ = playlists[0]; - loader.startingMedia_ = {hasVideo: true, hasAudio: true}; + loader.currentMediaInfo_ = {hasVideo: true, hasAudio: true}; loader.trigger('trackinfo'); playlistLoader.media = () => playlists[1]; loader.mainStartingMedia_ = playlists[1]; - loader.startingMedia_ = {hasVideo: true, hasAudio: true}; + loader.currentMediaInfo_ = {hasVideo: true, hasAudio: true}; loader.trigger('trackinfo'); playlistLoader.media = () => playlists[2]; loader.mainStartingMedia_ = playlists[2]; - loader.startingMedia_ = {hasVideo: true, hasAudio: true}; + loader.currentMediaInfo_ = {hasVideo: true, hasAudio: true}; loader.trigger('trackinfo'); assert.strictEqual(playlists.length, 3, 'three playlists total'); From 8648e76de9d4117fcf54c47c9670881b1dc279cc Mon Sep 17 00:00:00 2001 From: Alex Barstow Date: Wed, 23 Sep 2020 16:48:13 -0400 Subject: [PATCH 009/399] feat: Update minimumUpdatePeriod handling (#942) This is part of a set of upcoming changes to add support for live DASH playback. Specifically, this PR differentiates the handling of 2 cases which were formerly conflated: - The MPD@minimumUpdatePeriod attribute has a value of 0, indicating that the MPD has no validity after the moment it was retrieved. - The MPD@minimumUpdatePeriod attribute is absent, indicating the MPD has infinite validity and will never be updated --- package-lock.json | 6 +- package.json | 2 +- src/dash-playlist-loader.js | 48 +++++++------- test/dash-playlist-loader.test.js | 107 ++++++++++++++++++++++++++---- 4 files changed, 122 insertions(+), 41 deletions(-) diff --git a/package-lock.json b/package-lock.json index d8eb1a241..a652d5d5c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6823,9 +6823,9 @@ "dev": true }, "mpd-parser": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/mpd-parser/-/mpd-parser-0.11.0.tgz", - "integrity": "sha512-z9DIs++G+dRopPT5ROQgNdnDbby+j/9dkGoCC20Hd/3swyR8YxTxM8jOtl3zO9cnhjoikVFJuMbH+V8SE0/f5Q==", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/mpd-parser/-/mpd-parser-0.12.0.tgz", + "integrity": "sha512-Ov5Oz9bw5X/G8V/6PlO+rHuqKywYYjQ6USyv8fqFMs413HkrzlpDjgUKSBD7C+/J19ID5mWtxzrpMf4Yp++iZg==", "requires": { "@babel/runtime": "^7.5.5", "@videojs/vhs-utils": "^1.1.0", diff --git a/package.json b/package.json index cf78faaa5..a2dae5696 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "aes-decrypter": "3.0.2", "global": "^4.3.2", "m3u8-parser": "4.4.3", - "mpd-parser": "0.11.0", + "mpd-parser": "0.12.0", "mux.js": "5.6.6", "video.js": "^6 || ^7" }, diff --git a/src/dash-playlist-loader.js b/src/dash-playlist-loader.js index 8c54b67b4..92a6d571f 100644 --- a/src/dash-playlist-loader.js +++ b/src/dash-playlist-loader.js @@ -93,6 +93,10 @@ export const updateMaster = (oldMaster, newMaster) => { } }); + if (newMaster.minimumUpdatePeriod !== oldMaster.minimumUpdatePeriod) { + noChanges = false; + } + if (noChanges) { return null; } @@ -645,6 +649,22 @@ export default class DashPlaylistLoader extends EventTarget { } } + updateMinimumUpdatePeriodTimeout_() { + // Clear existing timeout + window.clearTimeout(this.minimumUpdatePeriodTimeout_); + + const minimumUpdatePeriod = this.master && this.master.minimumUpdatePeriod; + + if (minimumUpdatePeriod >= 0) { + this.minimumUpdatePeriodTimeout_ = window.setTimeout(() => { + this.trigger('minimumUpdatePeriod'); + // We use the target duration here because a minimumUpdatePeriod value of 0 + // indicates that the current MPD has no future validity, so a new one will + // need to be acquired when new media segments are to be made available + }, minimumUpdatePeriod || this.media().targetDuration * 1000); + } + } + /** * Handler for after client/server clock synchronization has happened. Sets up * xml refresh timer if specificed by the manifest. @@ -656,17 +676,7 @@ export default class DashPlaylistLoader extends EventTarget { this.media(this.master.playlists[0]); } - // TODO: minimumUpdatePeriod can have a value of 0. Currently the manifest will not - // be refreshed when this is the case. The inter-op guide says that when the - // minimumUpdatePeriod is 0, the manifest should outline all currently available - // segments, but future segments may require an update. I think a good solution - // would be to update the manifest at the same rate that the media playlists - // are "refreshed", i.e. every targetDuration. - if (this.master && this.master.minimumUpdatePeriod) { - this.minimumUpdatePeriodTimeout_ = window.setTimeout(() => { - this.trigger('minimumUpdatePeriod'); - }, this.master.minimumUpdatePeriod); - } + this.updateMinimumUpdatePeriodTimeout_(); } /** @@ -763,13 +773,7 @@ export default class DashPlaylistLoader extends EventTarget { // update loader's sidxMapping with parsed sidx box this.sidxMapping_[sidxKey].sidx = sidx; - // Clear & reset timeout with new minimumUpdatePeriod - window.clearTimeout(this.minimumUpdatePeriodTimeout_); - if (this.master.minimumUpdatePeriod) { - this.minimumUpdatePeriodTimeout_ = window.setTimeout(() => { - this.trigger('minimumUpdatePeriod'); - }, this.master.minimumUpdatePeriod); - } + this.updateMinimumUpdatePeriodTimeout_(); // TODO: do we need to reload the current playlist? this.refreshMedia_(this.media().id); @@ -786,13 +790,7 @@ export default class DashPlaylistLoader extends EventTarget { } } - // Clear & reset timeout with new minimumUpdatePeriod - window.clearTimeout(this.minimumUpdatePeriodTimeout_); - if (this.master.minimumUpdatePeriod) { - this.minimumUpdatePeriodTimeout_ = window.setTimeout(() => { - this.trigger('minimumUpdatePeriod'); - }, this.master.minimumUpdatePeriod); - } + this.updateMinimumUpdatePeriodTimeout_(); }); } diff --git a/test/dash-playlist-loader.test.js b/test/dash-playlist-loader.test.js index aac25ea5b..06e2d50f7 100644 --- a/test/dash-playlist-loader.test.js +++ b/test/dash-playlist-loader.test.js @@ -330,6 +330,62 @@ QUnit.test('updateMaster: updates playlists and mediaGroups', function(assert) { ); }); +QUnit.test('updateMaster: updates minimumUpdatePeriod', function(assert) { + const master = { + playlists: { + length: 1, + 0: { + uri: '0', + id: '0', + segments: [] + } + }, + mediaGroups: { + AUDIO: {}, + SUBTITLES: {} + }, + duration: 0, + minimumUpdatePeriod: 0 + }; + + const update = { + playlists: { + length: 1, + 0: { + uri: '0', + id: '0', + segments: [] + } + }, + mediaGroups: { + AUDIO: {}, + SUBTITLES: {} + }, + duration: 0, + minimumUpdatePeriod: 2 + }; + + assert.deepEqual( + updateMaster(master, update), + { + playlists: { + length: 1, + 0: { + uri: '0', + id: '0', + segments: [] + } + }, + mediaGroups: { + AUDIO: {}, + SUBTITLES: {} + }, + duration: 0, + minimumUpdatePeriod: 2 + } + ); +}); + QUnit.test('generateSidxKey: generates correct key', function(assert) { const sidxInfo = { byterange: { @@ -2386,7 +2442,7 @@ QUnit.test('refreshes the xml if there is a minimumUpdatePeriod', function(asser assert.equal(minimumUpdatePeriods, 1, 'refreshed manifest'); }); -QUnit.test('stop xml refresh if minimumUpdatePeriod changes from `mUP > 0` to `mUP == 0`', function(assert) { +QUnit.test('stop xml refresh if minimumUpdatePeriod is removed', function(assert) { const loader = new DashPlaylistLoader('dash-live.mpd', this.fakeVhs); let minimumUpdatePeriods = 0; @@ -2399,25 +2455,52 @@ QUnit.test('stop xml refresh if minimumUpdatePeriod changes from `mUP > 0` to `m this.standardXHRResponse(this.requests.shift()); assert.equal(minimumUpdatePeriods, 0, 'no refreshes immediately after response'); - // First Refresh Tick + // First Refresh Tick: MPD loaded this.clock.tick(4 * 1000); - this.standardXHRResponse(this.requests[0], loader.masterXml_); assert.equal(this.requests.length, 1, 'refreshed manifest'); assert.equal(this.requests[0].uri, 'dash-live.mpd', 'refreshed manifest'); assert.equal(minimumUpdatePeriods, 1, 'total minimumUpdatePeriods'); - // Second Refresh Tick: MinimumUpdatePeriod Removed - this.clock.tick(4 * 1000); - this.standardXHRResponse(this.requests[1], loader.masterXml_.replace('minimumUpdatePeriod="PT4S"', '')); + this.standardXHRResponse(this.requests[0], loader.masterXml_.replace('minimumUpdatePeriod="PT4S"', '')); + + // Second Refresh Tick: MUP removed this.clock.tick(4 * 1000); - this.standardXHRResponse(this.requests[2]); - assert.equal(this.requests.length, 3, 'final manifest refresh'); - assert.equal(minimumUpdatePeriods, 3, 'final minimumUpdatePeriods'); + assert.equal(this.requests.length, 1, 'no more manifest refreshes'); + assert.equal(minimumUpdatePeriods, 1, 'no more minimumUpdatePeriods'); +}); - // Third Refresh Tick: No Additional Requests Expected +QUnit.test('continue xml refresh every targetDuration if minimumUpdatePeriod is 0', function(assert) { + const loader = new DashPlaylistLoader('dash-live.mpd', this.fakeVhs); + let minimumUpdatePeriods = 0; + + loader.on('minimumUpdatePeriod', () => minimumUpdatePeriods++); + + loader.load(); + + // Start Request + assert.equal(minimumUpdatePeriods, 0, 'no refreshes to start'); + this.standardXHRResponse(this.requests.shift()); + assert.equal(minimumUpdatePeriods, 0, 'no refreshes immediately after response'); + + // First Refresh Tick this.clock.tick(4 * 1000); - assert.equal(this.requests.length, 3, 'final manifest refresh'); - assert.equal(minimumUpdatePeriods, 3, 'final minimumUpdatePeriods'); + assert.equal(this.requests.length, 1, 'refreshed manifest'); + assert.equal(this.requests[0].uri, 'dash-live.mpd', 'refreshed manifest'); + assert.equal(minimumUpdatePeriods, 1, 'total minimumUpdatePeriods'); + + this.standardXHRResponse(this.requests[0], loader.masterXml_.replace('minimumUpdatePeriod="PT4S"', 'minimumUpdatePeriod="PT0S"')); + + // Second Refresh Tick: MinimumUpdatePeriod set to 0 + // The manifest should refresh after one target duration, in this case 2 seconds. At this point + // it should not have occurred. + this.clock.tick(1 * 1000); + assert.equal(this.requests.length, 1, 'no 3rd manifest refresh yet'); + assert.equal(minimumUpdatePeriods, 1, 'no 3rd minimumUpdatePeriod yet'); + + // Now the refresh should happen + this.clock.tick(1 * 1000); + assert.equal(this.requests.length, 2, '3rd manifest refresh after targetDuration'); + assert.equal(minimumUpdatePeriods, 2, '3rd minimumUpdatePeriod after targetDuration'); }); QUnit.test('media playlists "refresh" by re-parsing master xml', function(assert) { From 3a0682fe4d74e7af0249ba8182bc28f1a1ac5bf0 Mon Sep 17 00:00:00 2001 From: Alex Barstow Date: Thu, 24 Sep 2020 16:50:05 -0400 Subject: [PATCH 010/399] fix: MPD not refreshed if minimumUpdatePeriod is 0 (#954) This fixes a bug caused by an oversight in #942. If the MPD@minimumUpdatePeriod is 0 in the first dynamic MPD we load, we should use the media's target duration as the MPD refresh interval, however we need to wait until a playlist has been selected before we can know DashPlaylistLoader.media().targetDuration, otherwise we get a TypeError. --- src/dash-playlist-loader.js | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/src/dash-playlist-loader.js b/src/dash-playlist-loader.js index 92a6d571f..6fea8c125 100644 --- a/src/dash-playlist-loader.js +++ b/src/dash-playlist-loader.js @@ -653,15 +653,31 @@ export default class DashPlaylistLoader extends EventTarget { // Clear existing timeout window.clearTimeout(this.minimumUpdatePeriodTimeout_); - const minimumUpdatePeriod = this.master && this.master.minimumUpdatePeriod; - - if (minimumUpdatePeriod >= 0) { + const createMUPTimeout = (mup) => { this.minimumUpdatePeriodTimeout_ = window.setTimeout(() => { this.trigger('minimumUpdatePeriod'); - // We use the target duration here because a minimumUpdatePeriod value of 0 - // indicates that the current MPD has no future validity, so a new one will - // need to be acquired when new media segments are to be made available - }, minimumUpdatePeriod || this.media().targetDuration * 1000); + }, mup); + }; + + const minimumUpdatePeriod = this.master && this.master.minimumUpdatePeriod; + + if (minimumUpdatePeriod > 0) { + createMUPTimeout(minimumUpdatePeriod); + + // If the minimumUpdatePeriod has a value of 0, that indicates that the current + // MPD has no future validity, so a new one will need to be acquired when new + // media segments are to be made available. Thus, we use the target duration + // in this case + } else if (minimumUpdatePeriod === 0) { + // If we haven't yet selected a playlist, wait until then so we know the + // target duration + if (!this.media()) { + this.one('loadedplaylist', () => { + createMUPTimeout(this.media().targetDuration * 1000); + }); + } else { + createMUPTimeout(this.media().targetDuration * 1000); + } } } From fe8376bc3fc5c8f3e8058d2a53fa0fc5db8a26d7 Mon Sep 17 00:00:00 2001 From: Gary Katsevman Date: Fri, 25 Sep 2020 13:25:51 -0400 Subject: [PATCH 011/399] revert: fix: use playlist NAME when available as its ID (#929) (#957) This reverts commit 22694642fc53815f441560f14e36d74232fca9f3. In testing, we noticed that the Angel One DASH video is broken, so we need to revert this change and fix it later. --- src/dash-playlist-loader.js | 2 +- src/manifest.js | 25 +++---------- test/dash-playlist-loader.test.js | 58 ++----------------------------- test/manifests/dash-swapped.mpd | 24 ------------- 4 files changed, 8 insertions(+), 101 deletions(-) delete mode 100644 test/manifests/dash-swapped.mpd diff --git a/src/dash-playlist-loader.js b/src/dash-playlist-loader.js index 6fea8c125..39550cb7a 100644 --- a/src/dash-playlist-loader.js +++ b/src/dash-playlist-loader.js @@ -43,7 +43,7 @@ export const parseMasterXml = ({ masterXml, srcUrl, clientOffset, sidxMapping }) sidxMapping }); - addPropertiesToMaster(master, srcUrl, true); + addPropertiesToMaster(master, srcUrl); return master; }; diff --git a/src/manifest.js b/src/manifest.js index 29f1ec525..3d5423756 100644 --- a/src/manifest.js +++ b/src/manifest.js @@ -99,32 +99,18 @@ export const setupMediaPlaylist = ({ playlist, uri, id }) => { * * @param {Object} master * The master playlist - * @param {boolean} [useNameForId=false] - * Whether we should use the NAME property for ID. - * Generally only used for DASH and defaults to false. */ -export const setupMediaPlaylists = (master, useNameForId) => { +export const setupMediaPlaylists = (master) => { let i = master.playlists.length; while (i--) { const playlist = master.playlists[i]; - const createdId = createPlaylistID(i, playlist.uri); - let id = createdId; - - // If useNameForId is set, use the NAME attribute for the ID. - // Generally, this will be used for DASH because - // DASH Representations can change order across refreshes which can make referring to them by index not work. - if (useNameForId) { - id = playlist.attributes && playlist.attributes.NAME || id; - } setupMediaPlaylist({ playlist, - id + id: createPlaylistID(i, playlist.uri) }); playlist.resolvedUri = resolveUrl(master.uri, playlist.uri); - // make sure that if a useNameForId is true, the old "createdId" id is also available - master.playlists[createdId] = playlist; master.playlists[playlist.id] = playlist; // URI reference added for backwards compatibility master.playlists[playlist.uri] = playlist; @@ -201,11 +187,8 @@ export const masterForMedia = (media, uri) => { * Master manifest object * @param {string} uri * The source URI - * @param {boolean} [useNameForId=false] - * Whether we should use the NAME property for ID. - * Generally only used for DASH and defaults to false. */ -export const addPropertiesToMaster = (master, uri, useNameForId = false) => { +export const addPropertiesToMaster = (master, uri) => { master.uri = uri; for (let i = 0; i < master.playlists.length; i++) { @@ -238,6 +221,6 @@ export const addPropertiesToMaster = (master, uri, useNameForId = false) => { master.playlists[phonyUri] = properties.playlists[0]; }); - setupMediaPlaylists(master, useNameForId); + setupMediaPlaylists(master); resolveMediaGroupUris(master); }; diff --git a/test/dash-playlist-loader.test.js b/test/dash-playlist-loader.test.js index 06e2d50f7..bf53eae5a 100644 --- a/test/dash-playlist-loader.test.js +++ b/test/dash-playlist-loader.test.js @@ -1361,12 +1361,7 @@ QUnit.test('parseMasterXml: setup phony playlists and resolves uris', function(a assert.strictEqual(masterPlaylist.uri, loader.srcUrl, 'master playlist uri set correctly'); assert.strictEqual(masterPlaylist.playlists[0].uri, 'placeholder-uri-0'); - assert.strictEqual(masterPlaylist.playlists[0].id, '1080p'); - assert.strictEqual( - masterPlaylist.playlists['1080p'], - masterPlaylist.playlists['0-placeholder-uri-0'], - 'available via old and new ids' - ); + assert.strictEqual(masterPlaylist.playlists[0].id, '0-placeholder-uri-0'); assert.deepEqual( masterPlaylist.playlists['0-placeholder-uri-0'], masterPlaylist.playlists[0], @@ -1692,43 +1687,6 @@ QUnit.test('refreshXml_: updates media playlist reference if master changed', fu ); }); -QUnit.test('refreshXml_: keep reference to same playlist by id across mpd updates', function(assert) { - const loader = new DashPlaylistLoader('dash.mpd', this.fakeVhs); - - loader.load(); - this.standardXHRResponse(this.requests.shift()); - - const oldMaster = loader.master; - const oldMedia = loader.media(); - - loader.refreshXml_(); - - assert.strictEqual(this.requests.length, 1, 'manifest is being requested'); - - this.requests.shift().respond(200, null, testDataManifests['dash-swapped']); - - const newMaster = loader.master; - const newMedia = loader.media(); - - assert.notEqual(newMaster, oldMaster, 'master changed'); - assert.notEqual(newMedia, oldMedia, 'media changed'); - assert.equal( - newMedia, - newMaster.playlists[newMedia.id], - 'media from updated master' - ); - - // given that the only thing that changed in the new manifest is - // the mediaPresentationDuration and order of representations - // the old media and the new media should be equivalent. - // Comparing the attributes is an easy way to check. - assert.deepEqual( - newMedia.attributes, - oldMedia.attributes, - 'old media and new media references by same id' - ); -}); - QUnit.test('sidxRequestFinished_: updates master with sidx information', function(assert) { const loader = new DashPlaylistLoader('dash.mpd', this.fakeVhs); const fakePlaylist = { @@ -2366,14 +2324,9 @@ QUnit.test( 'setup phony uri for media playlist' ); assert.equal( - loader.master.playlists[0].id, '1080p', + loader.master.playlists[0].id, '0-placeholder-uri-0', 'setup phony id for media playlist' ); - assert.strictEqual( - loader.master.playlists['1080p'], - loader.master.playlists['0-placeholder-uri-0'], - 'reference by NAME and old id' - ); assert.strictEqual( loader.master.playlists['0-placeholder-uri-0'], loader.master.playlists[0], 'set reference by uri for easy access' @@ -2383,14 +2336,9 @@ QUnit.test( 'setup phony uri for media playlist' ); assert.equal( - loader.master.playlists[1].id, '720p', + loader.master.playlists[1].id, '1-placeholder-uri-1', 'setup phony id for media playlist' ); - assert.strictEqual( - loader.master.playlists['720p'], - loader.master.playlists['1-placeholder-uri-1'], - 'reference by NAME and old id' - ); assert.strictEqual( loader.master.playlists['1-placeholder-uri-1'], loader.master.playlists[1], 'set reference by uri for easy access' diff --git a/test/manifests/dash-swapped.mpd b/test/manifests/dash-swapped.mpd deleted file mode 100644 index f6ee7fa3b..000000000 --- a/test/manifests/dash-swapped.mpd +++ /dev/null @@ -1,24 +0,0 @@ - - - - main/ - - video/ - - 720/ - - - - 1080/ - - - - - audio/ - - 720/ - - - - - From 56a0970fb6861197ea9ba9986c52e4fe790cfad5 Mon Sep 17 00:00:00 2001 From: Brandon Casey <2381475+brandonocasey@users.noreply.github.com> Date: Fri, 25 Sep 2020 13:26:44 -0400 Subject: [PATCH 012/399] chore: mark angel one dash subs as broken (#956) --- scripts/sources.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/sources.json b/scripts/sources.json index 329dd12fe..6b711fc28 100644 --- a/scripts/sources.json +++ b/scripts/sources.json @@ -108,7 +108,7 @@ "features": [] }, { - "name": "Angel One - fmp4, webm, subs, alternate audio tracks", + "name": "Angel One - fmp4, webm, subs (TODO: subs are broken), alternate audio tracks", "uri": "https://storage.googleapis.com/shaka-demo-assets/angel-one/dash.mpd", "mimetype": "application/dash+xml", "features": [] From d1dcd7b2b8fa8f102e3b73dc3dce02ee95cb8865 Mon Sep 17 00:00:00 2001 From: Brandon Casey <2381475+brandonocasey@users.noreply.github.com> Date: Fri, 25 Sep 2020 13:46:52 -0400 Subject: [PATCH 013/399] fix: noop vtt segment loader handle data (#959) We should noop handleData in vtt segment loader so that any captions which we don't support the type of, such as stpp.ttml.im1t from tears of steal widevine unified streaming do not attempt to append to sourceBuffers and cause a player append error. --- src/vtt-segment-loader.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vtt-segment-loader.js b/src/vtt-segment-loader.js index 389c28a61..933b7805c 100644 --- a/src/vtt-segment-loader.js +++ b/src/vtt-segment-loader.js @@ -375,6 +375,10 @@ export default class VTTSegmentLoader extends SegmentLoader { this.handleAppendsDone_(); } + handleData_() { + // noop as we shouldn't be getting video/audio data captions + // that we do not support here. + } updateTimingInfoEnd_() { // noop } From 89ead2ca012eeb497b024ebea8414e267381312b Mon Sep 17 00:00:00 2001 From: Gary Katsevman Date: Fri, 25 Sep 2020 14:50:29 -0400 Subject: [PATCH 014/399] 2.2.0 --- CHANGELOG.md | 33 +++++++++++++++++++++++++++++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e91c0e98..28649cff3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,36 @@ + +# [2.2.0](https://github.com/videojs/http-streaming/compare/v2.1.0...v2.2.0) (2020-09-25) + +### Features + +* default handleManfiestRedirect to true ([#927](https://github.com/videojs/http-streaming/issues/927)) ([556321f](https://github.com/videojs/http-streaming/commit/556321f)) +* support MPD.Location ([#926](https://github.com/videojs/http-streaming/issues/926)) ([c4a43d7](https://github.com/videojs/http-streaming/commit/c4a43d7)) +* Update minimumUpdatePeriod handling ([#942](https://github.com/videojs/http-streaming/issues/942)) ([8648e76](https://github.com/videojs/http-streaming/commit/8648e76)) + +### Bug Fixes + +* audio groups with the same uri as media do not count ([#952](https://github.com/videojs/http-streaming/issues/952)) ([3927c0c](https://github.com/videojs/http-streaming/commit/3927c0c)) +* dash manifest not refreshed if only some playlists are updated ([#949](https://github.com/videojs/http-streaming/issues/949)) ([31d3441](https://github.com/videojs/http-streaming/commit/31d3441)) +* detect demuxed video underflow gaps ([#948](https://github.com/videojs/http-streaming/issues/948)) ([d0ef298](https://github.com/videojs/http-streaming/commit/d0ef298)) +* MPD not refreshed if minimumUpdatePeriod is 0 ([#954](https://github.com/videojs/http-streaming/issues/954)) ([3a0682f](https://github.com/videojs/http-streaming/commit/3a0682f)), closes [#942](https://github.com/videojs/http-streaming/issues/942) +* noop vtt segment loader handle data ([#959](https://github.com/videojs/http-streaming/issues/959)) ([d1dcd7b](https://github.com/videojs/http-streaming/commit/d1dcd7b)) +* report the correct buffered regardless of playlist change ([#950](https://github.com/videojs/http-streaming/issues/950)) ([043ccc6](https://github.com/videojs/http-streaming/commit/043ccc6)) +* Throw a player error when trying to play DRM content without eme ([#938](https://github.com/videojs/http-streaming/issues/938)) ([ce4d6fd](https://github.com/videojs/http-streaming/commit/ce4d6fd)) +* use playlist NAME when available as its ID ([#929](https://github.com/videojs/http-streaming/issues/929)) ([2269464](https://github.com/videojs/http-streaming/commit/2269464)) +* use TIME_FUDGE_FACTOR rather than rounding by decimal digits ([#881](https://github.com/videojs/http-streaming/issues/881)) ([7eb112d](https://github.com/videojs/http-streaming/commit/7eb112d)) + +### Chores + +* **package:** remove engine check in pkcs7 ([#947](https://github.com/videojs/http-streaming/issues/947)) ([89392fa](https://github.com/videojs/http-streaming/commit/89392fa)) +* mark angel one dash subs as broken ([#956](https://github.com/videojs/http-streaming/issues/956)) ([56a0970](https://github.com/videojs/http-streaming/commit/56a0970)) +* mediaConfig_ -> staringMediaInfo_, startingMedia_ -> currentMediaInfo_ ([#953](https://github.com/videojs/http-streaming/issues/953)) ([8801d1c](https://github.com/videojs/http-streaming/commit/8801d1c)) +* playlist selector logging ([#921](https://github.com/videojs/http-streaming/issues/921)) ([ccdbaef](https://github.com/videojs/http-streaming/commit/ccdbaef)) +* update m3u8-parser to v4.4.3 ([#928](https://github.com/videojs/http-streaming/issues/928)) ([af5b4ee](https://github.com/videojs/http-streaming/commit/af5b4ee)) + +### Reverts + +* fix: use playlist NAME when available as its ID ([#929](https://github.com/videojs/http-streaming/issues/929)) ([#957](https://github.com/videojs/http-streaming/issues/957)) ([fe8376b](https://github.com/videojs/http-streaming/commit/fe8376b)) + # [2.1.0](https://github.com/videojs/http-streaming/compare/v2.0.0...v2.1.0) (2020-07-28) diff --git a/package-lock.json b/package-lock.json index a652d5d5c..7531fdfce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@videojs/http-streaming", - "version": "2.1.0", + "version": "2.2.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index a2dae5696..8417457f7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@videojs/http-streaming", - "version": "2.1.0", + "version": "2.2.0", "description": "Play back HLS and DASH with Video.js, even where it's not natively supported", "main": "dist/videojs-http-streaming.cjs.js", "module": "dist/videojs-http-streaming.es.js", From a05d0328238c30d9cd564d0ba7a64b09082c8749 Mon Sep 17 00:00:00 2001 From: Gary Katsevman Date: Wed, 30 Sep 2020 19:01:13 -0400 Subject: [PATCH 015/399] feat: add experimental buffer based ABR (#886) This adds a new option `experimentalBufferBasedABR` which turns it on. It uses a moving average playlist selector along with forward buffer checks that gate up and down switching. Right now it is turned off, and we are likely to fiddle with the implementation of this so it should not be relied on right now. We hope to eventually ship what this turns into as the new default ABR for VHS. Co-authored-by: brandonocasey --- index.html | 4 + scripts/index-demo-page.js | 24 +-- src/config.js | 8 +- src/master-playlist-controller.js | 130 ++++++++++--- src/segment-loader.js | 45 ++--- src/videojs-http-streaming.js | 19 +- test/configuration.test.js | 6 +- test/loader-common.js | 4 +- test/master-playlist-controller.test.js | 244 +++++++++++++++++++++++- 9 files changed, 412 insertions(+), 72 deletions(-) diff --git a/index.html b/index.html index 6ce5957fa..13e6f5f05 100644 --- a/index.html +++ b/index.html @@ -73,6 +73,10 @@

Options

Handle Partial (reloads player) +

Load a URL

diff --git a/scripts/index-demo-page.js b/scripts/index-demo-page.js index 7500d5707..85324c485 100644 --- a/scripts/index-demo-page.js +++ b/scripts/index-demo-page.js @@ -216,7 +216,7 @@ representationsEl.selectedIndex = selectedIndex; }; - ['debug', 'autoplay', 'muted', 'minified', 'liveui', 'partial', 'url', 'type', 'keysystems'].forEach(function(name) { + ['debug', 'autoplay', 'muted', 'minified', 'liveui', 'partial', 'url', 'type', 'keysystems', 'buffer-water'].forEach(function(name) { stateEls[name] = document.getElementById(name); }); @@ -251,13 +251,15 @@ stateEls.partial.addEventListener('change', function(event) { saveState(); - window.videojs.options = window.videojs.options || {}; - window.videojs.options.vhs = window.videojs.options.vhs || {}; - window.videojs.options.vhs.handlePartialData = event.target.checked; + // reload the player and scripts + stateEls.minified.dispatchEvent(newEvent('change')); + }); - if (window.player) { - window.player.src(window.player.currentSource()); - } + stateEls['buffer-water'].addEventListener('change', function(event) { + saveState(); + + // reload the player and scripts + stateEls.minified.dispatchEvent(newEvent('change')); }); stateEls.liveui.addEventListener('change', function(event) { @@ -296,8 +298,6 @@ videoEl.className = 'vjs-default-skin'; fixture.appendChild(videoEl); - stateEls.partial.dispatchEvent(newEvent('change')); - player = window.player = window.videojs(videoEl, { plugins: { httpSourceSelector: { @@ -307,7 +307,9 @@ liveui: stateEls.liveui.checked, html5: { vhs: { - overrideNative: true + overrideNative: true, + handlePartialData: getInputValue(stateEls.partial), + experimentalBufferBasedABR: getInputValue(stateEls['buffer-water']) } } }); @@ -329,7 +331,7 @@ sources.dispatchEvent(newEvent('change')); } player.on('loadedmetadata', function() { - if (player.vhs) { + if (player.tech_.vhs) { window.vhs = player.tech_.vhs; window.mpc = player.tech_.vhs.masterPlaylistController_; window.mpc.masterPlaylistLoader_.on('mediachange', regenerateRepresentations); diff --git a/src/config.js b/src/config.js index 056aac550..6ccb0adc3 100644 --- a/src/config.js +++ b/src/config.js @@ -11,5 +11,11 @@ export default { // How much of the buffer must be filled before we consider upswitching BUFFER_LOW_WATER_LINE: 0, MAX_BUFFER_LOW_WATER_LINE: 30, - BUFFER_LOW_WATER_LINE_RATE: 1 + + // TODO: Remove this when useBufferWaterLines is removed + EXPERIMENTAL_MAX_BUFFER_LOW_WATER_LINE: 16, + + BUFFER_LOW_WATER_LINE_RATE: 1, + // If the buffer is greater than the high water line, we won't switch down + BUFFER_HIGH_WATER_LINE: 30 }; diff --git a/src/master-playlist-controller.js b/src/master-playlist-controller.js index 7df977405..60c445201 100644 --- a/src/master-playlist-controller.js +++ b/src/master-playlist-controller.js @@ -49,7 +49,9 @@ const shouldSwitchToMedia = function({ nextPlaylist, forwardBuffer, bufferLowWaterLine, + bufferHighWaterLine, duration, + experimentalBufferBasedABR, log }) { // we have no other playlist to switch to @@ -58,31 +60,61 @@ const shouldSwitchToMedia = function({ return false; } + const sharedLogLine = `allowing switch ${currentPlaylist && currentPlaylist.id || 'null'} -> ${nextPlaylist.id}`; + // If the playlist is live, then we want to not take low water line into account. // This is because in LIVE, the player plays 3 segments from the end of the // playlist, and if `BUFFER_LOW_WATER_LINE` is greater than the duration availble // in those segments, a viewer will never experience a rendition upswitch. - if (!currentPlaylist.endList) { + if (!currentPlaylist || !currentPlaylist.endList) { + log(`${sharedLogLine} as current playlist ` + (!currentPlaylist ? 'is not set' : 'is live')); return true; } + // no need to switch playlist is the same + if (nextPlaylist.id === currentPlaylist.id) { + return false; + } + + const maxBufferLowWaterLine = experimentalBufferBasedABR ? + Config.EXPERIMENTAL_MAX_BUFFER_LOW_WATER_LINE : Config.MAX_BUFFER_LOW_WATER_LINE; + // For the same reason as LIVE, we ignore the low water line when the VOD // duration is below the max potential low water line - if (duration < Config.MAX_BUFFER_LOW_WATER_LINE) { + if (duration < maxBufferLowWaterLine) { + log(`${sharedLogLine} as duration < max low water line (${duration} < ${maxBufferLowWaterLine})`); return true; } - // we want to switch down to lower resolutions quickly to continue playback, but - if (nextPlaylist.attributes.BANDWIDTH < currentPlaylist.attributes.BANDWIDTH) { + const nextBandwidth = nextPlaylist.attributes.BANDWIDTH; + const currBandwidth = currentPlaylist.attributes.BANDWIDTH; + + // when switching down, if our buffer is lower than the high water line, + // we can switch down + if (nextBandwidth < currBandwidth && (!experimentalBufferBasedABR || forwardBuffer < bufferHighWaterLine)) { + let logLine = `${sharedLogLine} as next bandwidth < current bandwidth (${nextBandwidth} < ${currBandwidth})`; + + if (experimentalBufferBasedABR) { + logLine += ` and forwardBuffer < bufferHighWaterLine (${forwardBuffer} < ${bufferHighWaterLine})`; + } + log(logLine); return true; } - // ensure we have some buffer before we switch up to prevent us running out of - // buffer while loading a higher rendition. - if (forwardBuffer >= bufferLowWaterLine) { + // and if our buffer is higher than the low water line, + // we can switch up + if ((!experimentalBufferBasedABR || nextBandwidth > currBandwidth) && forwardBuffer >= bufferLowWaterLine) { + let logLine = `${sharedLogLine} as forwardBuffer >= bufferLowWaterLine (${forwardBuffer} >= ${bufferLowWaterLine})`; + + if (experimentalBufferBasedABR) { + logLine += ` and next bandwidth > current bandwidth (${nextBandwidth} > ${currBandwidth})`; + } + log(logLine); return true; } + log(`not ${sharedLogLine} as no switching criteria met`); + return false; }; @@ -111,7 +143,8 @@ export class MasterPlaylistController extends videojs.EventTarget { enableLowInitialPlaylist, sourceType, cacheEncryptionKeys, - handlePartialData + handlePartialData, + experimentalBufferBasedABR } = options; if (!src) { @@ -120,6 +153,7 @@ export class MasterPlaylistController extends videojs.EventTarget { Vhs = externVhs; + this.experimentalBufferBasedABR = Boolean(experimentalBufferBasedABR); this.withCredentials = withCredentials; this.tech_ = tech; this.vhs_ = tech.vhs; @@ -318,7 +352,12 @@ export class MasterPlaylistController extends videojs.EventTarget { selectedMedia = this.selectPlaylist(); } + if (!selectedMedia || !this.shouldSwitchToMedia_(selectedMedia)) { + return; + } + this.initialMedia_ = selectedMedia; + this.masterPlaylistLoader_.media(this.initialMedia_); // Under the standard case where a source URL is provided, loadedplaylist will @@ -478,6 +517,27 @@ export class MasterPlaylistController extends videojs.EventTarget { this.tech_.trigger({type: 'usage', name: 'hls-playlist-cue-tags'}); } } + + shouldSwitchToMedia_(nextPlaylist) { + const currentPlaylist = this.masterPlaylistLoader_.media(); + const buffered = this.tech_.buffered(); + const forwardBuffer = buffered.length ? + buffered.end(buffered.length - 1) - this.tech_.currentTime() : 0; + + const bufferLowWaterLine = this.bufferLowWaterLine(); + const bufferHighWaterLine = this.bufferHighWaterLine(); + + return shouldSwitchToMedia({ + currentPlaylist, + nextPlaylist, + forwardBuffer, + bufferLowWaterLine, + bufferHighWaterLine, + duration: this.duration(), + experimentalBufferBasedABR: this.experimentalBufferBasedABR, + log: this.logger_ + }); + } /** * Register event handlers on the segment loaders. A helper function * for construction time. @@ -487,27 +547,23 @@ export class MasterPlaylistController extends videojs.EventTarget { setupSegmentLoaderListeners_() { this.mainSegmentLoader_.on('bandwidthupdate', () => { const nextPlaylist = this.selectPlaylist(); - const currentPlaylist = this.masterPlaylistLoader_.media(); - const buffered = this.tech_.buffered(); - const forwardBuffer = buffered.length ? - buffered.end(buffered.length - 1) - this.tech_.currentTime() : 0; - - const bufferLowWaterLine = this.bufferLowWaterLine(); - - if (shouldSwitchToMedia({ - currentPlaylist, - nextPlaylist, - forwardBuffer, - bufferLowWaterLine, - duration: this.duration(), - log: this.logger_ - })) { + + if (this.shouldSwitchToMedia_(nextPlaylist)) { this.masterPlaylistLoader_.media(nextPlaylist); } this.tech_.trigger('bandwidthupdate'); }); + this.mainSegmentLoader_.on('progress', () => { + if (this.experimentalBufferBasedABR) { + const nextPlaylist = this.selectPlaylist(); + + if (this.shouldSwitchToMedia_(nextPlaylist)) { + this.masterPlaylistLoader_.media(nextPlaylist); + } + } + this.trigger('progress'); }); @@ -542,7 +598,26 @@ export class MasterPlaylistController extends videojs.EventTarget { this.onEndOfStream(); }); - this.mainSegmentLoader_.on('earlyabort', () => { + this.mainSegmentLoader_.on('earlyabort', (event) => { + if (this.experimentalBufferBasedABR) { + const currentPlaylist = this.masterPlaylistLoader_.media(); + + // temporarily exclude the current playlist so that we can + // determine the next playlist that would be selected + // if this playlist were to be excluded. + currentPlaylist.excludeUntil = Infinity; + + const nextPlaylist = this.selectPlaylist(); + + // un-exclude the current playlist for now + currentPlaylist.excludeUntil = null; + + // if we shouldn't switch to the next playlist, do nothing + if (!this.shouldSwitchToMedia_(nextPlaylist)) { + this.logger_(`earlyabort triggered, but we will not be switching from ${currentPlaylist.id} -> ${nextPlaylist.id}.`); + return; + } + } this.blacklistCurrentPlaylist({ message: 'Aborted early because there isn\'t enough bandwidth to complete the ' + 'request without rebuffering.' @@ -1633,8 +1708,13 @@ export class MasterPlaylistController extends videojs.EventTarget { const initial = Config.BUFFER_LOW_WATER_LINE; const rate = Config.BUFFER_LOW_WATER_LINE_RATE; const max = Math.max(initial, Config.MAX_BUFFER_LOW_WATER_LINE); + const newMax = Math.max(initial, Config.EXPERIMENTAL_MAX_BUFFER_LOW_WATER_LINE); - return Math.min(initial + currentTime * rate, max); + return Math.min(initial + currentTime * rate, this.experimentalBufferBasedABR ? newMax : max); + } + + bufferHighWaterLine() { + return Config.BUFFER_HIGH_WATER_LINE; } } diff --git a/src/segment-loader.js b/src/segment-loader.js index aadfe68de..53aa3edca 100644 --- a/src/segment-loader.js +++ b/src/segment-loader.js @@ -1343,10 +1343,9 @@ export default class SegmentLoader extends videojs.EventTarget { * * @param {Object} stats * Object containing stats about the request timing and size - * @return {boolean} True if the request was aborted, false otherwise * @private */ - abortRequestEarly_(stats) { + earlyAbortWhenNeeded_(stats) { if (this.vhs_.tech_.paused() || // Don't abort if the current playlist is on the lowestEnabledRendition // TODO: Replace using timeout with a boolean indicating whether this playlist is @@ -1354,14 +1353,14 @@ export default class SegmentLoader extends videojs.EventTarget { !this.xhrOptions_.timeout || // Don't abort if we have no bandwidth information to estimate segment sizes !(this.playlist_.attributes.BANDWIDTH)) { - return false; + return; } // Wait at least 1 second since the first byte of data has been received before // using the calculated bandwidth from the progress event to allow the bitrate // to stabilize if (Date.now() - (stats.firstBytesReceivedAt || Date.now()) < 1000) { - return false; + return; } const currentTime = this.currentTime_(); @@ -1388,7 +1387,7 @@ export default class SegmentLoader extends videojs.EventTarget { // Only consider aborting early if the estimated time to finish the download // is larger than the estimated time until the player runs out of forward buffer if (requestTimeRemaining <= timeUntilRebuffer) { - return false; + return; } const switchCandidate = minRebufferMaxBandwidthSelector({ @@ -1422,7 +1421,7 @@ export default class SegmentLoader extends videojs.EventTarget { if (!switchCandidate.playlist || switchCandidate.playlist.uri === this.playlist_.uri || timeSavedBySwitching < minimumTimeSaving) { - return false; + return; } // set the bandwidth to that of the desired playlist being sure to scale by @@ -1430,9 +1429,7 @@ export default class SegmentLoader extends videojs.EventTarget { // don't trigger a bandwidthupdate as the bandwidth is artifial this.bandwidth = switchCandidate.playlist.attributes.BANDWIDTH * Config.BANDWIDTH_VARIANCE + 1; - this.abort(); this.trigger('earlyabort'); - return true; } handleAbort_() { @@ -1449,8 +1446,9 @@ export default class SegmentLoader extends videojs.EventTarget { * @private */ handleProgress_(event, simpleSegment) { - if (this.checkForAbort_(simpleSegment.requestId) || - this.abortRequestEarly_(simpleSegment.stats)) { + this.earlyAbortWhenNeeded_(simpleSegment.stats); + + if (this.checkForAbort_(simpleSegment.requestId)) { return; } @@ -1458,8 +1456,9 @@ export default class SegmentLoader extends videojs.EventTarget { } handleTrackInfo_(simpleSegment, trackInfo) { - if (this.checkForAbort_(simpleSegment.requestId) || - this.abortRequestEarly_(simpleSegment.stats)) { + this.earlyAbortWhenNeeded_(simpleSegment.stats); + + if (this.checkForAbort_(simpleSegment.requestId)) { return; } @@ -1486,8 +1485,7 @@ export default class SegmentLoader extends videojs.EventTarget { // trackinfo may cause an abort if the trackinfo // causes a codec change to an unsupported codec. - if (this.checkForAbort_(simpleSegment.requestId) || - this.abortRequestEarly_(simpleSegment.stats)) { + if (this.checkForAbort_(simpleSegment.requestId)) { return; } @@ -1502,8 +1500,8 @@ export default class SegmentLoader extends videojs.EventTarget { } handleTimingInfo_(simpleSegment, mediaType, timeType, time) { - if (this.checkForAbort_(simpleSegment.requestId) || - this.abortRequestEarly_(simpleSegment.stats)) { + this.earlyAbortWhenNeeded_(simpleSegment.stats); + if (this.checkForAbort_(simpleSegment.requestId)) { return; } @@ -1522,8 +1520,9 @@ export default class SegmentLoader extends videojs.EventTarget { } handleCaptions_(simpleSegment, captionData) { - if (this.checkForAbort_(simpleSegment.requestId) || - this.abortRequestEarly_(simpleSegment.stats)) { + this.earlyAbortWhenNeeded_(simpleSegment.stats); + + if (this.checkForAbort_(simpleSegment.requestId)) { return; } @@ -1595,8 +1594,9 @@ export default class SegmentLoader extends videojs.EventTarget { } handleId3_(simpleSegment, id3Frames, dispatchType) { - if (this.checkForAbort_(simpleSegment.requestId) || - this.abortRequestEarly_(simpleSegment.stats)) { + this.earlyAbortWhenNeeded_(simpleSegment.stats); + + if (this.checkForAbort_(simpleSegment.requestId)) { return; } @@ -1755,8 +1755,9 @@ export default class SegmentLoader extends videojs.EventTarget { } handleData_(simpleSegment, result) { - if (this.checkForAbort_(simpleSegment.requestId) || - this.abortRequestEarly_(simpleSegment.stats)) { + this.earlyAbortWhenNeeded_(simpleSegment.stats); + + if (this.checkForAbort_(simpleSegment.requestId)) { return; } diff --git a/src/videojs-http-streaming.js b/src/videojs-http-streaming.js index 115193b55..7890c2c8a 100644 --- a/src/videojs-http-streaming.js +++ b/src/videojs-http-streaming.js @@ -26,6 +26,7 @@ import reloadSourceOnError from './reload-source-on-error'; import { lastBandwidthSelector, lowestBitrateCompatibleVariantSelector, + movingAverageBandwidthSelector, comparePlaylistBandwidth, comparePlaylistResolution } from './playlist-selectors.js'; @@ -43,6 +44,8 @@ const Vhs = { STANDARD_PLAYLIST_SELECTOR: lastBandwidthSelector, INITIAL_PLAYLIST_SELECTOR: lowestBitrateCompatibleVariantSelector, + lastBandwidthSelector, + movingAverageBandwidthSelector, comparePlaylistBandwidth, comparePlaylistResolution, @@ -57,6 +60,7 @@ const Vhs = { 'GOAL_BUFFER_LENGTH_RATE', 'BUFFER_LOW_WATER_LINE', 'MAX_BUFFER_LOW_WATER_LINE', + 'EXPERIMENTAL_MAX_BUFFER_LOW_WATER_LINE', 'BUFFER_LOW_WATER_LINE_RATE', 'BANDWIDTH_VARIANCE' ].forEach((prop) => { @@ -589,7 +593,10 @@ class VhsHandler extends Component { 'customTagMappers', 'handleManifestRedirects', 'cacheEncryptionKeys', - 'handlePartialData' + 'handlePartialData', + 'playlistSelector', + 'initialPlaylistSelector', + 'experimentalBufferBasedABR' ].forEach((option) => { if (typeof this.source_[option] !== 'undefined') { this.options_[option] = this.source_[option]; @@ -615,6 +622,7 @@ class VhsHandler extends Component { this.options_.tech = this.tech_; this.options_.externVhs = Vhs; this.options_.sourceType = simpleTypeFromSourceType(type); + // Whenever we seek internally, we should update the tech this.options_.seekTo = (time) => { this.tech_.setCurrentTime(time); @@ -640,11 +648,14 @@ class VhsHandler extends Component { player.error(error); }); + const defaultSelector = this.options_.experimentalBufferBasedABR ? + Vhs.movingAverageBandwidthSelector(0.55) : Vhs.STANDARD_PLAYLIST_SELECTOR; + // `this` in selectPlaylist should be the VhsHandler for backwards // compatibility with < v2 - this.masterPlaylistController_.selectPlaylist = - this.selectPlaylist ? - this.selectPlaylist.bind(this) : Vhs.STANDARD_PLAYLIST_SELECTOR.bind(this); + this.masterPlaylistController_.selectPlaylist = this.selectPlaylist ? + this.selectPlaylist.bind(this) : + defaultSelector.bind(this); this.masterPlaylistController_.selectInitialPlaylist = Vhs.INITIAL_PLAYLIST_SELECTOR.bind(this); diff --git a/test/configuration.test.js b/test/configuration.test.js index fee2b10ca..7087e9516 100644 --- a/test/configuration.test.js +++ b/test/configuration.test.js @@ -265,15 +265,17 @@ QUnit.test('MAX_BUFFER_LOW_WATER_LINE set warning', function(assert) { }); QUnit.test('MAX_BUFFER_LOW_WATER_LINE set warning and invalid', function(assert) { + const defaultValue = Config.MAX_BUFFER_LOW_WATER_LINE; + Vhs.MAX_BUFFER_LOW_WATER_LINE = 'nope'; assert.equal(this.env.log.warn.calls, 2, 'logged two warnings'); - assert.equal(Config.MAX_BUFFER_LOW_WATER_LINE, 30, 'default'); + assert.equal(Config.MAX_BUFFER_LOW_WATER_LINE, defaultValue, 'default'); Vhs.MAX_BUFFER_LOW_WATER_LINE = -1; assert.equal(this.env.log.warn.calls, 2, 'logged two warnings'); - assert.equal(Config.MAX_BUFFER_LOW_WATER_LINE, 30, 'default'); + assert.equal(Config.MAX_BUFFER_LOW_WATER_LINE, defaultValue, 'default'); }); QUnit.test('BUFFER_LOW_WATER_LINE_RATE get warning', function(assert) { diff --git a/test/loader-common.js b/test/loader-common.js index 60c56760c..44cfed738 100644 --- a/test/loader-common.js +++ b/test/loader-common.js @@ -340,7 +340,7 @@ export const LoaderCommonFactory = ({ }); QUnit.test( - 'aborts request at progress events if bandwidth is too low', + 'triggers earlyabort at progress events if bandwidth is too low', function(assert) { const playlist1 = playlistWithDuration(10, { uri: 'playlist1.m3u8' }); const playlist2 = playlistWithDuration(10, { uri: 'playlist2.m3u8' }); @@ -425,7 +425,7 @@ export const LoaderCommonFactory = ({ }); assert.equal(bandwidthupdates, 0, 'bandwidth not updated'); - assert.ok(this.requests[0].aborted, 'request aborted'); + assert.ok(!this.requests[0].aborted, 'request not aborted'); assert.equal(earlyAborts, 1, 'earlyabort event triggered'); } ); diff --git a/test/master-playlist-controller.test.js b/test/master-playlist-controller.test.js index 7834f8b7a..954cd04c0 100644 --- a/test/master-playlist-controller.test.js +++ b/test/master-playlist-controller.test.js @@ -67,7 +67,7 @@ const sharedHooks = { videojs.Vhs.supportsNativeHls = false; this.oldBrowser = videojs.browser; videojs.browser = videojs.mergeOptions({}, videojs.browser); - this.player = createPlayer(); + this.player = createPlayer(videojs.mergeOptions({}, this.playerOptions)); this.player.src({ src: 'manifest/master.m3u8', type: 'application/vnd.apple.mpegurl' @@ -1643,12 +1643,14 @@ QUnit.test( let currentTime = 0; let endList = true; let duration = 100; + let id = 0; this.masterPlaylistController.tech_.currentTime = () => currentTime; this.masterPlaylistController.tech_.buffered = () => videojs.createTimeRanges(buffered); this.masterPlaylistController.duration = () => duration; this.masterPlaylistController.selectPlaylist = () => { return { + id: id++, attributes: { BANDWIDTH: nextPlaylistBandwidth }, @@ -1658,6 +1660,7 @@ QUnit.test( this.masterPlaylistController.masterPlaylistLoader_.media = (media) => { if (!media) { return { + id: id++, attributes: { BANDWIDTH: currentPlaylistBandwidth }, @@ -2069,11 +2072,9 @@ QUnit.test('does not get stuck in a loop due to inconsistent network/caching', f bandwidth: 88000 }); }).then(() => { - // Media may be changed, but it should be changed to the same media. In the future, this - // can safely not be changed. bandwidthWithinTolerance(segmentLoader.bandwidth, 88000, 'bandwidth is correct'); - assert.equal(mediaChanges.length, 3, 'changed media'); - assert.equal(mediaChanges[2].uri, 'media.m3u8', 'media remains unchanged'); + assert.equal(mediaChanges.length, 2, 'did not change media'); + assert.equal(mediaChanges[1].uri, 'media.m3u8', 'media remains unchanged'); segmentRequest = this.requests[0]; assert.equal( @@ -5510,3 +5511,236 @@ QUnit.test('filter subtitle works', function(assert) { assert.deepEqual(this.calls, this.expected, 'calls as expected'); }); + +QUnit.module('MasterPlaylistController experimentalBufferBasedABR', { + beforeEach(assert) { + this.playerOptions = { + html5: { + vhs: { + experimentalBufferBasedABR: true + } + } + }; + sharedHooks.beforeEach.call(this, assert); + this.mpc = this.masterPlaylistController; + + }, + afterEach(assert) { + sharedHooks.afterEach.call(this, assert); + } +}); + +QUnit.test('Determines if playlist should be aborted on earlyabort', function(assert) { + this.masterPlaylistController.mediaSource.trigger('sourceopen'); + // master + this.standardXHRResponse(this.requests.shift()); + // media + this.standardXHRResponse(this.requests.shift()); + + const mediaChanges = []; + const playlistLoader = this.masterPlaylistController.masterPlaylistLoader_; + const currentMedia = playlistLoader.media(); + const origMedia = playlistLoader.media.bind(playlistLoader); + const origWarn = videojs.log.warn; + const warnings = []; + + this.masterPlaylistController.masterPlaylistLoader_.media = (media) => { + if (media) { + mediaChanges.push(media); + } + return origMedia(media); + }; + + videojs.log.warn = (text) => warnings.push(text); + + assert.notOk(currentMedia.excludeUntil > 0, 'playlist not blacklisted'); + assert.equal(mediaChanges.length, 0, 'no media change'); + + this.masterPlaylistController.shouldSwitchToMedia_ = () => false; + this.masterPlaylistController.mainSegmentLoader_.trigger('earlyabort'); + + assert.notOk(currentMedia.excludeUntil > 0, 'no exclusions if we should not switch'); + assert.equal(mediaChanges.length, 0, 'no media change if we should not switch'); + + this.masterPlaylistController.shouldSwitchToMedia_ = () => true; + this.masterPlaylistController.mainSegmentLoader_.trigger('earlyabort'); + assert.equal(mediaChanges.length, 1, 'one media change'); + assert.equal(warnings.length, 1, 'one warning logged'); + assert.equal( + warnings[0], + `Problem encountered with playlist ${currentMedia.id}. ` + + 'Aborted early because there isn\'t enough bandwidth to complete the ' + + `request without rebuffering. Switching to playlist ${mediaChanges[0].id}.`, + 'warning message is correct' + ); + + videojs.log.warn = origWarn; +}); + +QUnit.test('Determines if playlist should change on bandwidthupdate/progress from segment loader', function(assert) { + let calls = 0; + + this.masterPlaylistController.selectPlaylist = () => { + calls++; + return this.masterPlaylistController.masterPlaylistLoader_.master.playlists[0]; + }; + this.masterPlaylistController.mediaSource.trigger('sourceopen'); + + // master + this.standardXHRResponse(this.requests.shift()); + // media + this.standardXHRResponse(this.requests.shift()); + + // progress for a segment download + this.masterPlaylistController.mainSegmentLoader_.trigger('progress'); + assert.strictEqual(calls, 2, 'selects after segment progress'); + + // "downloaded" a segment + this.masterPlaylistController.mainSegmentLoader_.trigger('bandwidthupdate'); + assert.strictEqual(calls, 3, 'selects after segment download'); + + // verify stats + assert.equal(this.player.tech_.vhs.stats.bandwidth, 4194304, 'default bandwidth'); +}); + +QUnit.module('MasterPlaylistController shouldSwitchToMedia', sharedHooks); + +QUnit.test('true if a no current playlist', function(assert) { + const mpc = this.masterPlaylistController; + + mpc.masterPlaylistLoader_.media = () => null; + const nextPlaylist = {id: 'foo', endList: true}; + + assert.ok(mpc.shouldSwitchToMedia_(nextPlaylist), 'should switch without currentPlaylist'); +}); + +QUnit.test('true if current playlist is live', function(assert) { + const mpc = this.masterPlaylistController; + + mpc.masterPlaylistLoader_.media = () => ({endList: false, id: 'bar'}); + const nextPlaylist = {id: 'foo', endList: true}; + + assert.ok(mpc.shouldSwitchToMedia_(nextPlaylist), 'should switch with live currentPlaylist'); +}); + +QUnit.test('true if duration < 30', function(assert) { + const mpc = this.masterPlaylistController; + const nextPlaylist = {id: 'foo', endList: true}; + + mpc.duration = () => 20; + mpc.masterPlaylistLoader_.media = () => ({endList: true, id: 'bar'}); + + assert.ok(mpc.shouldSwitchToMedia_(nextPlaylist), 'should switch'); +}); + +QUnit.test('true duration < 16 with experimentalBufferBasedABR', function(assert) { + const mpc = this.masterPlaylistController; + const nextPlaylist = {id: 'foo', endList: true}; + + mpc.experimentalBufferBasedABR = true; + + mpc.duration = () => 15; + mpc.masterPlaylistLoader_.media = () => ({endList: true, id: 'bar'}); + + assert.ok(mpc.shouldSwitchToMedia_(nextPlaylist), 'should switch'); +}); + +QUnit.test('true if bandwidth decreases', function(assert) { + const mpc = this.masterPlaylistController; + const nextPlaylist = {id: 'foo', endList: true, attributes: {BANDWIDTH: 1}}; + + mpc.duration = () => 40; + mpc.masterPlaylistLoader_.media = () => ({endList: true, id: 'bar', attributes: {BANDWIDTH: 2}}); + + assert.ok(mpc.shouldSwitchToMedia_(nextPlaylist), 'should switch'); +}); + +QUnit.test('true if bandwidth decreases, experimentalBufferBasedABR, and forwardBuffer < bufferHighWaterLine', function(assert) { + const mpc = this.masterPlaylistController; + const nextPlaylist = {id: 'foo', endList: true, attributes: {BANDWIDTH: 1}}; + + // 0 forward buffer + mpc.tech_.buffered = () => videojs.createTimeRange(); + mpc.tech_.currentTime = () => 0; + mpc.experimentalBufferBasedABR = true; + mpc.duration = () => 40; + mpc.masterPlaylistLoader_.media = () => ({endList: true, id: 'bar', attributes: {BANDWIDTH: 2}}); + + assert.ok(mpc.shouldSwitchToMedia_(nextPlaylist), 'should switch'); +}); + +QUnit.test('true if forwardBuffer >= bufferLowWaterLine', function(assert) { + const mpc = this.masterPlaylistController; + const nextPlaylist = {id: 'foo', endList: true, attributes: {BANDWIDTH: 2}}; + + // zero forward buffer and zero buffer low water line + mpc.tech_.buffered = () => videojs.createTimeRange(); + mpc.tech_.currentTime = () => 0; + mpc.duration = () => 40; + mpc.masterPlaylistLoader_.media = () => ({endList: true, id: 'bar', attributes: {BANDWIDTH: 2}}); + + assert.ok(mpc.shouldSwitchToMedia_(nextPlaylist), 'should switch'); +}); + +QUnit.test('true if forwardBuffer >= bufferLowWaterLine, experimentalBufferBasedABR, and bandwidth increase', function(assert) { + const mpc = this.masterPlaylistController; + const nextPlaylist = {id: 'foo', endList: true, attributes: {BANDWIDTH: 3}}; + + // zero forward buffer and zero buffer low water line + mpc.tech_.buffered = () => videojs.createTimeRange(); + mpc.tech_.currentTime = () => 0; + mpc.experimentalBufferBasedABR = true; + mpc.duration = () => 40; + mpc.masterPlaylistLoader_.media = () => ({endList: true, id: 'bar', attributes: {BANDWIDTH: 2}}); + + assert.ok(mpc.shouldSwitchToMedia_(nextPlaylist), 'should switch'); +}); + +QUnit.test('false if nextPlaylist bandwidth lower, experimentalBufferBasedABR, and forwardBuffer > bufferHighWaterLine', function(assert) { + const mpc = this.masterPlaylistController; + const nextPlaylist = {id: 'foo', endList: true, attributes: {BANDWIDTH: 1}}; + + // 31s forwardBuffer + mpc.tech_.buffered = () => videojs.createTimeRange(0, 31); + mpc.tech_.currentTime = () => 0; + mpc.experimentalBufferBasedABR = true; + mpc.duration = () => 40; + mpc.masterPlaylistLoader_.media = () => ({endList: true, id: 'bar', attributes: {BANDWIDTH: 2}}); + + assert.notOk(mpc.shouldSwitchToMedia_(nextPlaylist), 'should not switch'); +}); + +QUnit.test('false if nextPlaylist bandwidth same, experimentalBufferBasedABR, and forwardBuffer >= bufferLowWaterLine', function(assert) { + const mpc = this.masterPlaylistController; + const nextPlaylist = {id: 'foo', endList: true, attributes: {BANDWIDTH: 2}}; + + // 31s forwardBuffer + mpc.tech_.buffered = () => videojs.createTimeRange(); + mpc.tech_.currentTime = () => 0; + mpc.experimentalBufferBasedABR = true; + mpc.duration = () => 40; + mpc.masterPlaylistLoader_.media = () => ({endList: true, id: 'bar', attributes: {BANDWIDTH: 2}}); + + assert.notOk(mpc.shouldSwitchToMedia_(nextPlaylist), 'should not switch'); +}); + +QUnit.test('false if nextPlaylist is currentPlaylist', function(assert) { + const mpc = this.masterPlaylistController; + const nextPlaylist = {id: 'foo', endList: true}; + + mpc.masterPlaylistLoader_.media = () => nextPlaylist; + + assert.notOk(mpc.shouldSwitchToMedia_(nextPlaylist), 'should not switch'); +}); + +QUnit.test('false without nextPlaylist', function(assert) { + const mpc = this.masterPlaylistController; + + mpc.masterPlaylistLoader_.media = () => ({endList: true, id: 'bar'}); + + assert.notOk(mpc.shouldSwitchToMedia_(null), 'should not switch'); + + assert.equal(this.env.log.warn.callCount, 1, 'logged a warning'); + + this.env.log.warn.callCount = 0; +}); From 0c7b2cbb035f852bfae1c4cb96cb6a46158b358f Mon Sep 17 00:00:00 2001 From: Brandon Casey <2381475+brandonocasey@users.noreply.github.com> Date: Fri, 2 Oct 2020 13:35:54 -0400 Subject: [PATCH 016/399] fix: check tech error before pause loaders (#969) A failed poster image may trigger an error event from the tech. This shouldn't cause us to pause our loaders, though. Instead, we should verify that there's an actual error object on the tech before proceeding with pausing the loaders. --- src/videojs-http-streaming.js | 4 +++- test/master-playlist-controller.test.js | 4 ++++ test/videojs-http-streaming.test.js | 30 +++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/videojs-http-streaming.js b/src/videojs-http-streaming.js index 7890c2c8a..06df9c393 100644 --- a/src/videojs-http-streaming.js +++ b/src/videojs-http-streaming.js @@ -526,7 +526,9 @@ class VhsHandler extends Component { }); this.on(this.tech_, 'error', function() { - if (this.masterPlaylistController_) { + // verify that the error was real and we are loaded + // enough to have mpc loaded. + if (this.tech_.error() && this.masterPlaylistController_) { this.masterPlaylistController_.pauseLoading(); } }); diff --git a/test/master-playlist-controller.test.js b/test/master-playlist-controller.test.js index 954cd04c0..0d264cb2a 100644 --- a/test/master-playlist-controller.test.js +++ b/test/master-playlist-controller.test.js @@ -3228,9 +3228,13 @@ QUnit.test('pauses subtitle segment loader on tech errors', function(assert) { masterPlaylistController.subtitleSegmentLoader_.pause = () => pauseCount++; + this.player.tech_.error = () => 'foo'; this.player.tech_.trigger('error'); assert.equal(pauseCount, 1, 'paused subtitle segment loader'); + + assert.equal(this.env.log.error.calls, 1, '1 media error logged'); + this.env.log.error.reset(); }); QUnit.test('disposes subtitle loaders on dispose', function(assert) { diff --git a/test/videojs-http-streaming.test.js b/test/videojs-http-streaming.test.js index 2383380a3..664225400 100644 --- a/test/videojs-http-streaming.test.js +++ b/test/videojs-http-streaming.test.js @@ -304,6 +304,36 @@ QUnit.test('the VhsHandler instance is referenced by player.vhs', function(asser assert.equal(this.env.log.warn.calls, 1, 'warning logged'); }); +QUnit.test('tech error may pause loading', function(assert) { + this.player.src({ + src: 'manifest/playlist.m3u8', + type: 'application/vnd.apple.mpegurl' + }); + this.clock.tick(1); + + const vhs = this.player.tech_.vhs; + const mpc = vhs.masterPlaylistController_; + let pauseCalled = false; + + mpc.pauseLoading = () => { + pauseCalled = true; + }; + + this.player.tech_.error = () => null; + this.player.tech_.trigger('error'); + + assert.notOk(pauseCalled, 'no video el error attribute, no pause loading'); + + this.player.tech_.error = () => 'foo'; + this.player.tech_.trigger('error'); + + assert.ok(pauseCalled, 'video el error and trigger pauses loading'); + + assert.equal(this.env.log.error.calls, 1, '1 media error logged'); + this.env.log.error.reset(); + +}); + QUnit.test('a deprecation notice is shown when using player.dash', function(assert) { this.player.src({ src: 'manifest/playlist.m3u8', From 329d50a7c63a3ae570a73e472e2278068d14ec5f Mon Sep 17 00:00:00 2001 From: Brandon Casey <2381475+brandonocasey@users.noreply.github.com> Date: Tue, 6 Oct 2020 16:43:33 -0400 Subject: [PATCH 017/399] fix: appendsdone abort and handle multiple id3 sections. (#971) appendsdone may cause an abort in segmentloaders which can then cause pendingSegment to be null after we just null checked it. Instead we should check if we have a pendingSegment then trigger appends done and see if an abort happens. We also want to make sure that if audio contains multiple id3 sections, we support playing back to it as we did in previos versions of VHS. --- package-lock.json | 12 ++++++------ package.json | 4 ++-- src/segment-loader.js | 7 +++++-- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7531fdfce..d047c16a9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1181,9 +1181,9 @@ } }, "@videojs/vhs-utils": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@videojs/vhs-utils/-/vhs-utils-2.2.0.tgz", - "integrity": "sha512-Mtq+doRlbNvis9TyI5kfOg+Vg8aHGXkSXiuNwnkcimqyaP3wO/s/iEVKPcmRUySKivjaWktjdEFVXYfaP+/HTg==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@videojs/vhs-utils/-/vhs-utils-2.2.1.tgz", + "integrity": "sha512-9Qbwx3LAdkG1jh2HKfninjXDxVZCeaoPcmct/bUcDRmLej68Z9XhLe5d2a9fy1qB+UuQwWg7YySASesWavYNjQ==", "requires": { "@babel/runtime": "^7.5.5", "global": "^4.3.2", @@ -6858,9 +6858,9 @@ "dev": true }, "mux.js": { - "version": "5.6.6", - "resolved": "https://registry.npmjs.org/mux.js/-/mux.js-5.6.6.tgz", - "integrity": "sha512-q5VIpqb28UVs5dKsOQkpHrPxqInMjiZ/f/4qW4gEBKlm2xeBasRjRJIokixFWj+r6PWfVSEygvPffXnG7aK99g==" + "version": "5.6.7", + "resolved": "https://registry.npmjs.org/mux.js/-/mux.js-5.6.7.tgz", + "integrity": "sha512-YSr6B8MUgE4S18MptbY2XM+JKGbw9JDkgs7YkuE/T2fpDKjOhZfb/nD6vmsVxvLYOExWNaQn1UGBp6PGsnTtew==" }, "nanomatch": { "version": "1.2.13", diff --git a/package.json b/package.json index 8417457f7..8a2adc230 100644 --- a/package.json +++ b/package.json @@ -57,12 +57,12 @@ ], "dependencies": { "@babel/runtime": "^7.5.5", - "@videojs/vhs-utils": "^2.2.0", + "@videojs/vhs-utils": "^2.2.1", "aes-decrypter": "3.0.2", "global": "^4.3.2", "m3u8-parser": "4.4.3", "mpd-parser": "0.12.0", - "mux.js": "5.6.6", + "mux.js": "5.6.7", "video.js": "^6 || ^7" }, "devDependencies": { diff --git a/src/segment-loader.js b/src/segment-loader.js index 53aa3edca..056a817d9 100644 --- a/src/segment-loader.js +++ b/src/segment-loader.js @@ -2530,6 +2530,11 @@ export default class SegmentLoader extends videojs.EventTarget { * @private */ handleAppendsDone_() { + // appendsdone can cause an abort + if (this.pendingSegment_) { + this.trigger('appendsdone'); + } + if (!this.pendingSegment_) { this.state = 'READY'; // TODO should this move into this.checkForAbort to speed up requests post abort in @@ -2540,8 +2545,6 @@ export default class SegmentLoader extends videojs.EventTarget { return; } - this.trigger('appendsdone'); - const segmentInfo = this.pendingSegment_; // Now that the end of the segment has been reached, we can set the end time. It's From 326ce1c37d2bb42a0da58a6447953ad471f5e669 Mon Sep 17 00:00:00 2001 From: Brandon Casey <2381475+brandonocasey@users.noreply.github.com> Date: Wed, 14 Oct 2020 15:57:30 -0400 Subject: [PATCH 018/399] fix: inline json version (#967) --- package-lock.json | 41 +++++++++++++++++++++++++++++++++++ package.json | 1 + scripts/rollup.config.js | 18 +++++++++++++++ src/videojs-http-streaming.js | 7 +++++- 4 files changed, 66 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index d047c16a9..737be7c66 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1009,6 +1009,47 @@ "integrity": "sha512-Jq0JfThRZvmuDn0Sx3TTi0uf2ZhIDnx08l9af4741gCMghyT26zxR/DNPoPJCGDc1QFLohYdCWsMn21XFDt46Q==", "dev": true }, + "@rollup/plugin-replace": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.3.3.tgz", + "integrity": "sha512-XPmVXZ7IlaoWaJLkSCDaa0Y6uVo5XQYHhiMFzOd5qSv5rE+t/UJToPIOE56flKIxBFQI27ONsxb7dqHnwSsjKQ==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^3.0.8", + "magic-string": "^0.25.5" + } + }, + "@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "dev": true, + "requires": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + }, + "dependencies": { + "@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true + }, + "estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", + "dev": true + }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true + } + } + }, "@samverschueren/stream-to-observable": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz", diff --git a/package.json b/package.json index 8a2adc230..80ecfea88 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ }, "devDependencies": { "@gkatsev/rollup-plugin-bundle-worker": "^1.0.2", + "@rollup/plugin-replace": "^2.3.3", "@videojs/generator-helpers": "~1.2.0", "d3": "^3.4.8", "es5-shim": "^4.5.13", diff --git a/scripts/rollup.config.js b/scripts/rollup.config.js index 242e4f91d..55100c486 100644 --- a/scripts/rollup.config.js +++ b/scripts/rollup.config.js @@ -2,6 +2,12 @@ const generate = require('videojs-generate-rollup-config'); const worker = require('@gkatsev/rollup-plugin-bundle-worker'); const {terser} = require('rollup-plugin-terser'); const createTestData = require('./create-test-data.js'); +const vhs = require('../package.json'); +const mux = require('mux.js/package.json'); +const mpd = require('mpd-parser/package.json'); +const m3u8 = require('m3u8-parser/package.json'); +const aes = require('aes-decrypter/package.json'); +const replace = require('@rollup/plugin-replace'); // see https://github.com/videojs/videojs-generate-rollup-config // for options @@ -28,6 +34,10 @@ const options = { defaults.module.splice(2, 0, 'worker'); defaults.browser.splice(2, 0, 'worker'); defaults.test.splice(3, 0, 'worker'); + + defaults.module.unshift('replace'); + defaults.browser.unshift('replace'); + defaults.test.unshift('replace'); defaults.test.splice(0, 0, 'createTestData'); // istanbul is only in the list for regular builds and not watch @@ -45,6 +55,14 @@ const options = { compress: {passes: 2}, include: [/^.+\.min\.js$/] }), + replace: replace({ + "import {version as vhsVersion} from '../package.json';": `const vhsVersion = '${vhs.version}';`, + "import {version as muxVersion} from 'mux.js/package.json';": `const muxVersion = '${mux.version}';`, + "import {version as mpdVersion} from 'mpd-parser/package.json';": `const mpdVersion = '${mpd.version}';`, + "import {version as m3u8Version} from 'm3u8-parser/package.json';": `const m3u8Version = '${m3u8.version}';`, + "import {version as aesVersion} from 'aes-decrypter/package.json';": `const aesVersion = '${aes.version}';`, + 'delimiters': ['', ''] + }), createTestData: createTestData() }); }, diff --git a/src/videojs-http-streaming.js b/src/videojs-http-streaming.js index 06df9c393..ef403bd2e 100644 --- a/src/videojs-http-streaming.js +++ b/src/videojs-http-streaming.js @@ -30,12 +30,17 @@ import { comparePlaylistBandwidth, comparePlaylistResolution } from './playlist-selectors.js'; +import {isAudioCodec, isVideoCodec, browserSupportsCodec} from '@videojs/vhs-utils/dist/codecs.js'; + +// IMPORTANT: +// keep these at the bottom they are replaced at build time +// because webpack and rollup without plugins do not support json +// and we do not want to break our users import {version as vhsVersion} from '../package.json'; import {version as muxVersion} from 'mux.js/package.json'; import {version as mpdVersion} from 'mpd-parser/package.json'; import {version as m3u8Version} from 'm3u8-parser/package.json'; import {version as aesVersion} from 'aes-decrypter/package.json'; -import {isAudioCodec, isVideoCodec, browserSupportsCodec} from '@videojs/vhs-utils/dist/codecs.js'; const Vhs = { PlaylistLoader, From 200c87bcdbe5ca76a3841389b6d2ff2490f7cf66 Mon Sep 17 00:00:00 2001 From: Gary Katsevman Date: Fri, 30 Oct 2020 18:58:28 -0400 Subject: [PATCH 019/399] fix(experimentalBufferBasedABR): call selectPlaylist and change media on an interval (#978) This is a followup to #886. There, I noticed that if we get sustained bad network we will time out because we will an opportunity for earlyabort. At first, I tried working around by delaying earlyabort in that case (#966) but as I was getting that ready I kept finding edge cases that we needed to account for. Specifically, the issue is that we only run our ABR algorithm on progress and bandwidthchange events from the segment loader. This means that if the download stalls, we stop run our algorithm and will eventually stall playback. Instead, we should remove earlyabort altogether (f897dde) and set up an interval (currently 250ms) to re-run our ABR algorithm. This means that if the network becomes bad for a sustained period, we will drop down once the buffer allows us but if the network recovers, we will switch up appropriately as well. Also, the interval is stopped while we're paused. Fixes #964. --- src/master-playlist-controller.js | 94 ++++++++++++++++--------- test/master-playlist-controller.test.js | 56 ++------------- 2 files changed, 69 insertions(+), 81 deletions(-) diff --git a/src/master-playlist-controller.js b/src/master-playlist-controller.js index 60c445201..9486ce127 100644 --- a/src/master-playlist-controller.js +++ b/src/master-playlist-controller.js @@ -258,6 +258,12 @@ export class MasterPlaylistController extends videojs.EventTarget { this.setupSegmentLoaderListeners_(); + if (this.experimentalBufferBasedABR) { + this.startABRTimer_(); + this.tech_.on('pause', () => this.stopABRTimer_()); + this.tech_.on('play', () => this.startABRTimer_()); + } + // Create SegmentLoader stat-getters // mediaRequests_ // mediaRequestsAborted_ @@ -275,6 +281,45 @@ export class MasterPlaylistController extends videojs.EventTarget { this.masterPlaylistLoader_.load(); } + /** + * Run selectPlaylist and switch to the new playlist if we should + * + * @private + * + */ + checkABR_() { + const nextPlaylist = this.selectPlaylist(); + + if (this.shouldSwitchToMedia_(nextPlaylist)) { + this.masterPlaylistLoader_.media(nextPlaylist); + } + } + + /** + * Start a timer that periodically calls checkABR_ + * + * @private + */ + startABRTimer_() { + this.stopABRTimer_(); + this.abrTimer_ = window.setInterval(() => this.checkABR_(), 250); + } + + /** + * Stop the timer that periodically calls checkABR_ + * + * @private + */ + stopABRTimer_() { + // if we're scrubbing, we don't need to pause. + // This getter will be added to Video.js in version 7.11. + if (this.tech_.scrubbing && this.tech_.scrubbing()) { + return; + } + window.clearInterval(this.abrTimer_); + this.abrTimer_ = null; + } + /** * Register event handlers on the master playlist loader. A helper * function for construction time. @@ -545,27 +590,21 @@ export class MasterPlaylistController extends videojs.EventTarget { * @private */ setupSegmentLoaderListeners_() { - this.mainSegmentLoader_.on('bandwidthupdate', () => { - const nextPlaylist = this.selectPlaylist(); - - if (this.shouldSwitchToMedia_(nextPlaylist)) { - this.masterPlaylistLoader_.media(nextPlaylist); - } - - this.tech_.trigger('bandwidthupdate'); - }); - - this.mainSegmentLoader_.on('progress', () => { - if (this.experimentalBufferBasedABR) { + if (!this.experimentalBufferBasedABR) { + this.mainSegmentLoader_.on('bandwidthupdate', () => { const nextPlaylist = this.selectPlaylist(); if (this.shouldSwitchToMedia_(nextPlaylist)) { this.masterPlaylistLoader_.media(nextPlaylist); } - } - this.trigger('progress'); - }); + this.tech_.trigger('bandwidthupdate'); + }); + + this.mainSegmentLoader_.on('progress', () => { + this.trigger('progress'); + }); + } this.mainSegmentLoader_.on('error', () => { this.blacklistCurrentPlaylist(this.mainSegmentLoader_.error()); @@ -599,25 +638,11 @@ export class MasterPlaylistController extends videojs.EventTarget { }); this.mainSegmentLoader_.on('earlyabort', (event) => { + // never try to early abort with the new ABR algorithm if (this.experimentalBufferBasedABR) { - const currentPlaylist = this.masterPlaylistLoader_.media(); - - // temporarily exclude the current playlist so that we can - // determine the next playlist that would be selected - // if this playlist were to be excluded. - currentPlaylist.excludeUntil = Infinity; - - const nextPlaylist = this.selectPlaylist(); - - // un-exclude the current playlist for now - currentPlaylist.excludeUntil = null; - - // if we shouldn't switch to the next playlist, do nothing - if (!this.shouldSwitchToMedia_(nextPlaylist)) { - this.logger_(`earlyabort triggered, but we will not be switching from ${currentPlaylist.id} -> ${nextPlaylist.id}.`); - return; - } + return; } + this.blacklistCurrentPlaylist({ message: 'Aborted early because there isn\'t enough bandwidth to complete the ' + 'request without rebuffering.' @@ -899,6 +924,7 @@ export class MasterPlaylistController extends videojs.EventTarget { return; } + this.stopABRTimer_(); this.sourceUpdater_.endOfStream(); } @@ -1066,6 +1092,7 @@ export class MasterPlaylistController extends videojs.EventTarget { */ pauseLoading() { this.delegateLoaders_('all', ['abort', 'pause']); + this.stopABRTimer_(); } /** @@ -1386,6 +1413,9 @@ export class MasterPlaylistController extends videojs.EventTarget { this.subtitleSegmentLoader_.dispose(); this.sourceUpdater_.dispose(); this.timelineChangeController_.dispose(); + + this.stopABRTimer_(); + if (this.updateDuration_) { this.mediaSource.removeEventListener('sourceopen', this.updateDuration_); } diff --git a/test/master-playlist-controller.test.js b/test/master-playlist-controller.test.js index 0d264cb2a..919c80e22 100644 --- a/test/master-playlist-controller.test.js +++ b/test/master-playlist-controller.test.js @@ -5534,53 +5534,6 @@ QUnit.module('MasterPlaylistController experimentalBufferBasedABR', { } }); -QUnit.test('Determines if playlist should be aborted on earlyabort', function(assert) { - this.masterPlaylistController.mediaSource.trigger('sourceopen'); - // master - this.standardXHRResponse(this.requests.shift()); - // media - this.standardXHRResponse(this.requests.shift()); - - const mediaChanges = []; - const playlistLoader = this.masterPlaylistController.masterPlaylistLoader_; - const currentMedia = playlistLoader.media(); - const origMedia = playlistLoader.media.bind(playlistLoader); - const origWarn = videojs.log.warn; - const warnings = []; - - this.masterPlaylistController.masterPlaylistLoader_.media = (media) => { - if (media) { - mediaChanges.push(media); - } - return origMedia(media); - }; - - videojs.log.warn = (text) => warnings.push(text); - - assert.notOk(currentMedia.excludeUntil > 0, 'playlist not blacklisted'); - assert.equal(mediaChanges.length, 0, 'no media change'); - - this.masterPlaylistController.shouldSwitchToMedia_ = () => false; - this.masterPlaylistController.mainSegmentLoader_.trigger('earlyabort'); - - assert.notOk(currentMedia.excludeUntil > 0, 'no exclusions if we should not switch'); - assert.equal(mediaChanges.length, 0, 'no media change if we should not switch'); - - this.masterPlaylistController.shouldSwitchToMedia_ = () => true; - this.masterPlaylistController.mainSegmentLoader_.trigger('earlyabort'); - assert.equal(mediaChanges.length, 1, 'one media change'); - assert.equal(warnings.length, 1, 'one warning logged'); - assert.equal( - warnings[0], - `Problem encountered with playlist ${currentMedia.id}. ` + - 'Aborted early because there isn\'t enough bandwidth to complete the ' + - `request without rebuffering. Switching to playlist ${mediaChanges[0].id}.`, - 'warning message is correct' - ); - - videojs.log.warn = origWarn; -}); - QUnit.test('Determines if playlist should change on bandwidthupdate/progress from segment loader', function(assert) { let calls = 0; @@ -5597,11 +5550,16 @@ QUnit.test('Determines if playlist should change on bandwidthupdate/progress fro // progress for a segment download this.masterPlaylistController.mainSegmentLoader_.trigger('progress'); - assert.strictEqual(calls, 2, 'selects after segment progress'); + assert.strictEqual(calls, 1, 'does not select after segment progress'); // "downloaded" a segment this.masterPlaylistController.mainSegmentLoader_.trigger('bandwidthupdate'); - assert.strictEqual(calls, 3, 'selects after segment download'); + assert.strictEqual(calls, 1, 'does not select after segment download'); + + this.clock.tick(250); + assert.strictEqual(calls, 2, 'selects after clock tick'); + this.clock.tick(1000); + assert.strictEqual(calls, 6, 'selects after clock tick, 1000 is 4x250'); // verify stats assert.equal(this.player.tech_.vhs.stats.bandwidth, 4194304, 'default bandwidth'); From 645e979bed0c212a7478b5592fc8d0a3fed0a2da Mon Sep 17 00:00:00 2001 From: Brandon Casey <2381475+brandonocasey@users.noreply.github.com> Date: Fri, 30 Oct 2020 18:59:08 -0400 Subject: [PATCH 020/399] fix: only prevent audio group creation if no other playlists are using it (#981) --- scripts/sources.json | 6 ++++++ src/media-groups.js | 20 ++++++++++---------- test/media-groups.test.js | 37 +++++++++++++++++++++++++++++++++++++ test/playback.test.js | 19 +++++++++++++++++++ 4 files changed, 72 insertions(+), 10 deletions(-) diff --git a/scripts/sources.json b/scripts/sources.json index 6b711fc28..ae6c041d1 100644 --- a/scripts/sources.json +++ b/scripts/sources.json @@ -303,5 +303,11 @@ "uri": "https://d2zihajmogu5jn.cloudfront.net/audio-only-dupe-groups/prog_index.m3u8", "mimetype": "application/x-mpegurl", "features": [] + }, + { + "name": "Big Buck Bunny Demuxed av, audio only rendition same as group", + "uri": "https://d2zihajmogu5jn.cloudfront.net/demuxed-ts-with-audio-only-rendition/master.m3u8", + "mimetype": "application/x-mpegurl", + "features": [] } ] diff --git a/src/media-groups.js b/src/media-groups.js index f1e4417b1..3064337de 100644 --- a/src/media-groups.js +++ b/src/media-groups.js @@ -405,18 +405,18 @@ export const initialize = { for (const variantLabel in mediaGroups[type][groupId]) { let properties = mediaGroups[type][groupId][variantLabel]; - // List of playlists for the current group ID that have a matching uri with - // this alternate audio variant - const matchingPlaylists = groupPlaylists.filter(playlist => { - return playlist.resolvedUri === properties.resolvedUri; + // List of playlists for the current group ID that do not have a matching uri + // with this alternate audio variant + const unmatchingPlaylists = groupPlaylists.filter(playlist => { + return playlist.resolvedUri !== properties.resolvedUri; }); - if (matchingPlaylists.length) { - // If there is a playlist that has the same uri as this audio variant, assume - // that the playlist is audio only. We delete the resolvedUri property here - // to prevent a playlist loader from being created so that we don't have - // both the main and audio segment loaders loading the same audio segments - // from the same playlist. + // If there are no playlists using this audio group other than ones + // that match it's uri, then the playlist is audio only. We delete the resolvedUri + // property here to prevent a playlist loader from being created so that we don't have + // both the main and audio segment loaders loading the same audio segments + // from the same playlist. + if (!unmatchingPlaylists.length && groupPlaylists.length) { delete properties.resolvedUri; } diff --git a/test/media-groups.test.js b/test/media-groups.test.js index ee3b5222a..910f41d29 100644 --- a/test/media-groups.test.js +++ b/test/media-groups.test.js @@ -1012,6 +1012,43 @@ QUnit.test('initialize audio correctly uses HLS source type', function(assert) { ); }); +QUnit.test('no audio loader for audio only with duplicated audio groups', function(assert) { + this.master.mediaGroups.AUDIO.aud1 = { + en: { default: true, language: 'en', resolvedUri: 'en.m3u8' } + }; + + this.settings.sourceType = 'hls'; + + this.settings.master.playlists = [ + {resolvedUri: 'en.m3u8', attributes: {AUDIO: 'aud1'}} + ]; + MediaGroups.initialize.AUDIO('AUDIO', this.settings); + + assert.notOk( + this.mediaTypes.AUDIO.groups.aud1[0].playlistLoader, + 'no loader as audio group is the same as main renditions' + ); +}); + +QUnit.test('audio loader created with audio group duplicated as audio only rendition', function(assert) { + this.master.mediaGroups.AUDIO.aud1 = { + en: { default: true, language: 'en', resolvedUri: 'en.m3u8' } + }; + + this.settings.sourceType = 'hls'; + + this.settings.master.playlists = [ + {resolvedUri: 'video/en.m3u8', attributes: {AUDIO: 'aud1'}}, + {resolvedUri: 'en.m3u8', attributes: {AUDIO: 'aud1'}} + ]; + MediaGroups.initialize.AUDIO('AUDIO', this.settings); + + assert.ok( + this.mediaTypes.AUDIO.groups.aud1[0].playlistLoader, + 'audio loader created' + ); +}); + QUnit.test('initialize audio correctly uses DASH source type', function(assert) { // allow async methods to resolve before next test const done = assert.async(); diff --git a/test/playback.test.js b/test/playback.test.js index 198e792dc..8a19ab526 100644 --- a/test/playback.test.js +++ b/test/playback.test.js @@ -237,6 +237,25 @@ QUnit[testFn]('Big Buck Bunny audio only, groups & renditions same uri', functio }); }); +QUnit[testFn]('Big Buck Bunny Demuxed av, audio only rendition same as group', function(assert) { + const done = assert.async(); + + assert.expect(2); + const player = this.player; + + playFor(player, 25, function() { + assert.ok(true, 'played for at least 25 seconds'); + assert.equal(player.error(), null, 'has no player errors'); + + done(); + }); + + player.src({ + src: 'https://d2zihajmogu5jn.cloudfront.net/demuxed-ts-with-audio-only-rendition/master.m3u8', + type: 'application/x-mpegURL' + }); +}); + QUnit[testFn]('Live DASH', function(assert) { const done = assert.async(); From ca7655e0f8ef12f708367e0bedbde3d38e900659 Mon Sep 17 00:00:00 2001 From: Gary Katsevman Date: Fri, 30 Oct 2020 19:00:04 -0400 Subject: [PATCH 021/399] fix(playback-watcher): ignore subtitles (#980) It's possible that a subtitle track will have segments without any text in them depending on how the subtitles and captions were created. Therefor, we should ignore it in the playback-watcher where we're checking for excessive downloads. --- src/playback-watcher.js | 9 ---- test/playback-watcher.test.js | 88 +++++++++++++++++------------------ 2 files changed, 44 insertions(+), 53 deletions(-) diff --git a/src/playback-watcher.js b/src/playback-watcher.js index 66d96f8e8..6ebb7ed55 100644 --- a/src/playback-watcher.js +++ b/src/playback-watcher.js @@ -11,7 +11,6 @@ import window from 'global/window'; import * as Ranges from './ranges'; import logger from './util/logger'; -import videojs from 'video.js'; // Set of events that reset the playback-watcher time check logic and clear the timeout const timerCancelEvents = [ @@ -220,14 +219,6 @@ export default class PlaybackWatcher { this.tech_.trigger({type: 'usage', name: `vhs-${type}-download-exclusion`}); if (type === 'subtitle') { - // TODO: Is there anything else that we can do here? - // removing the track and disabling could have accesiblity implications. - const track = loader.track(); - const label = track.label || track.language || 'Unknown'; - - videojs.log.warn(`Text track "${label}" is not working correctly. It will be disabled and excluded.`); - track.mode = 'disabled'; - this.tech_.textTracks().removeTrack(track); return; } diff --git a/test/playback-watcher.test.js b/test/playback-watcher.test.js index 64efa739c..3612838e7 100644 --- a/test/playback-watcher.test.js +++ b/test/playback-watcher.test.js @@ -933,64 +933,64 @@ QUnit.module('PlaybackWatcher download detection', { }); loaderTypes.forEach(function(type) { - QUnit.test(`detects ${type} appends without buffer changes and excludes`, function(assert) { - this.setup(); - const loader = this.mpc[`${type}SegmentLoader_`]; - const track = {label: 'foobar', mode: 'showing'}; + if (type !== 'subtitle') { + QUnit.test(`detects ${type} appends without buffer changes and excludes`, function(assert) { + this.setup(); + const loader = this.mpc[`${type}SegmentLoader_`]; + const track = {label: 'foobar', mode: 'showing'}; - if (type === 'subtitle') { - loader.track = () => track; - sinon.stub(this.player.tech_.textTracks(), 'removeTrack'); - } + if (type === 'subtitle') { + loader.track = () => track; + sinon.stub(this.player.tech_.textTracks(), 'removeTrack'); + } - this.setBuffered(videojs.createTimeRanges([[0, 30]])); + this.setBuffered(videojs.createTimeRanges([[0, 30]])); - for (let i = 0; i <= EXCLUDE_APPEND_COUNT; i++) { - loader.trigger('appendsdone'); - if (i === EXCLUDE_APPEND_COUNT) { - assert.equal(this.playbackWatcher[`${type}StalledDownloads_`], 0, `append #${i} resets stalled downloads to 0`); - } else { - assert.equal(this.playbackWatcher[`${type}StalledDownloads_`], i, `append #${i + 1} ${i} stalled downloads`); + for (let i = 0; i <= EXCLUDE_APPEND_COUNT; i++) { + loader.trigger('appendsdone'); + if (i === EXCLUDE_APPEND_COUNT) { + assert.equal(this.playbackWatcher[`${type}StalledDownloads_`], 0, `append #${i} resets stalled downloads to 0`); + } else { + assert.equal(this.playbackWatcher[`${type}StalledDownloads_`], i, `append #${i + 1} ${i} stalled downloads`); + } } - } - const expectedUsage = {}; + const expectedUsage = {}; - expectedUsage[`vhs-${type}-download-exclusion`] = 1; + expectedUsage[`vhs-${type}-download-exclusion`] = 1; - if (type !== 'subtitle') { - expectedUsage['vhs-rendition-blacklisted'] = 1; - expectedUsage['hls-rendition-blacklisted'] = 1; - } + if (type !== 'subtitle') { + expectedUsage['vhs-rendition-blacklisted'] = 1; + expectedUsage['hls-rendition-blacklisted'] = 1; + } - assert.deepEqual(this.usageEvents, expectedUsage, 'usage as expected'); + assert.deepEqual(this.usageEvents, expectedUsage, 'usage as expected'); - if (type !== 'subtitle') { - const message = 'Playback cannot continue. No available working or supported playlists.'; + if (type !== 'subtitle') { + const message = 'Playback cannot continue. No available working or supported playlists.'; - assert.equal(this.mpcErrors, 1, 'one mpc error'); - assert.equal(this.mpc.error, message, 'mpc error set'); - assert.equal(this.player.error().message, message, 'player error set'); - assert.equal(this.env.log.error.callCount, 1, 'player error logged'); - assert.equal(this.env.log.error.args[0][1], message, 'error message as expected'); + assert.equal(this.mpcErrors, 1, 'one mpc error'); + assert.equal(this.mpc.error, message, 'mpc error set'); + assert.equal(this.player.error().message, message, 'player error set'); + assert.equal(this.env.log.error.callCount, 1, 'player error logged'); + assert.equal(this.env.log.error.args[0][1], message, 'error message as expected'); - this.env.log.error.resetHistory(); - } else { - const message = 'Text track "foobar" is not working correctly. It will be disabled and excluded.'; + this.env.log.error.resetHistory(); + } else { + const message = 'Text track "foobar" is not working correctly. It will be disabled and excluded.'; - assert.equal(this.mpcErrors, 0, 'no mpc error set'); - assert.notOk(this.player.error(), 'no player error set'); - assert.equal(this.player.textTracks().removeTrack.callCount, 1, 'text track remove called'); - assert.equal(this.player.textTracks().removeTrack.args[0][0], track, 'text track remove called with expected'); - assert.equal(track.mode, 'disabled', 'mode set to disabled now'); - assert.equal(this.env.log.warn.callCount, 1, 'warning logged'); - assert.equal(this.env.log.warn.args[0][0], message, 'warning message as expected'); + assert.equal(this.mpcErrors, 0, 'no mpc error set'); + assert.notOk(this.player.error(), 'no player error set'); + assert.equal(this.player.textTracks().removeTrack.callCount, 1, 'text track remove called'); + assert.equal(this.player.textTracks().removeTrack.args[0][0], track, 'text track remove called with expected'); + assert.equal(track.mode, 'disabled', 'mode set to disabled now'); + assert.equal(this.env.log.warn.callCount, 1, 'warning logged'); + assert.equal(this.env.log.warn.args[0][0], message, 'warning message as expected'); - this.env.log.warn.resetHistory(); - } - }); + this.env.log.warn.resetHistory(); + } + }); - if (type !== 'subtitle') { QUnit.test(`detects ${type} appends without buffer changes and excludes many playlists`, function(assert) { this.setup({src: 'multipleAudioGroupsCombinedMain.m3u8', type: 'application/vnd.apple.mpegurl'}); From 0f66d8e8f54be3b656dcf3c78bd7a34349e2f04e Mon Sep 17 00:00:00 2001 From: Gary Katsevman Date: Tue, 3 Nov 2020 10:15:17 -0500 Subject: [PATCH 022/399] test(playback-watcher): subtitle test refactor (#986) Updates based on late comments from #980. --- test/playback-watcher.test.js | 238 ++++++++++++++++------------------ 1 file changed, 109 insertions(+), 129 deletions(-) diff --git a/test/playback-watcher.test.js b/test/playback-watcher.test.js index 3612838e7..ab127f359 100644 --- a/test/playback-watcher.test.js +++ b/test/playback-watcher.test.js @@ -13,7 +13,6 @@ import { } from '../src/playback-watcher'; // needed for plugin registration import '../src/videojs-http-streaming'; -import sinon from 'sinon'; let monitorCurrentTime_; @@ -933,134 +932,6 @@ QUnit.module('PlaybackWatcher download detection', { }); loaderTypes.forEach(function(type) { - if (type !== 'subtitle') { - QUnit.test(`detects ${type} appends without buffer changes and excludes`, function(assert) { - this.setup(); - const loader = this.mpc[`${type}SegmentLoader_`]; - const track = {label: 'foobar', mode: 'showing'}; - - if (type === 'subtitle') { - loader.track = () => track; - sinon.stub(this.player.tech_.textTracks(), 'removeTrack'); - } - - this.setBuffered(videojs.createTimeRanges([[0, 30]])); - - for (let i = 0; i <= EXCLUDE_APPEND_COUNT; i++) { - loader.trigger('appendsdone'); - if (i === EXCLUDE_APPEND_COUNT) { - assert.equal(this.playbackWatcher[`${type}StalledDownloads_`], 0, `append #${i} resets stalled downloads to 0`); - } else { - assert.equal(this.playbackWatcher[`${type}StalledDownloads_`], i, `append #${i + 1} ${i} stalled downloads`); - } - } - - const expectedUsage = {}; - - expectedUsage[`vhs-${type}-download-exclusion`] = 1; - - if (type !== 'subtitle') { - expectedUsage['vhs-rendition-blacklisted'] = 1; - expectedUsage['hls-rendition-blacklisted'] = 1; - } - - assert.deepEqual(this.usageEvents, expectedUsage, 'usage as expected'); - - if (type !== 'subtitle') { - const message = 'Playback cannot continue. No available working or supported playlists.'; - - assert.equal(this.mpcErrors, 1, 'one mpc error'); - assert.equal(this.mpc.error, message, 'mpc error set'); - assert.equal(this.player.error().message, message, 'player error set'); - assert.equal(this.env.log.error.callCount, 1, 'player error logged'); - assert.equal(this.env.log.error.args[0][1], message, 'error message as expected'); - - this.env.log.error.resetHistory(); - } else { - const message = 'Text track "foobar" is not working correctly. It will be disabled and excluded.'; - - assert.equal(this.mpcErrors, 0, 'no mpc error set'); - assert.notOk(this.player.error(), 'no player error set'); - assert.equal(this.player.textTracks().removeTrack.callCount, 1, 'text track remove called'); - assert.equal(this.player.textTracks().removeTrack.args[0][0], track, 'text track remove called with expected'); - assert.equal(track.mode, 'disabled', 'mode set to disabled now'); - assert.equal(this.env.log.warn.callCount, 1, 'warning logged'); - assert.equal(this.env.log.warn.args[0][0], message, 'warning message as expected'); - - this.env.log.warn.resetHistory(); - } - }); - - QUnit.test(`detects ${type} appends without buffer changes and excludes many playlists`, function(assert) { - this.setup({src: 'multipleAudioGroupsCombinedMain.m3u8', type: 'application/vnd.apple.mpegurl'}); - - const loader = this.mpc[`${type}SegmentLoader_`]; - const playlists = this.mpc.master().playlists; - const excludeAndVerify = () => { - let oldPlaylist; - // this test only needs 9 appends, since we do an intial append - - for (let i = 0; i < EXCLUDE_APPEND_COUNT; i++) { - oldPlaylist = this.mpc.media(); - loader.trigger('appendsdone'); - if (i === EXCLUDE_APPEND_COUNT - 1) { - assert.equal(this.playbackWatcher[`${type}StalledDownloads_`], 0, `append #${i} resets stalled downloads to 0`); - } else { - assert.equal(this.playbackWatcher[`${type}StalledDownloads_`], i + 1, `append #${i + 1} ${i + 1} stalled downloads`); - } - } - - const expectedUsage = {}; - - expectedUsage[`vhs-${type}-download-exclusion`] = 1; - expectedUsage['vhs-rendition-blacklisted'] = 1; - expectedUsage['hls-rendition-blacklisted'] = 1; - - assert.deepEqual(this.usageEvents, expectedUsage, 'usage as expected'); - this.usageEvents = {}; - - this.respondToPlaylists_(); - - const otherPlaylistsLeft = this.mpc.master().playlists.some((p) => p.excludeUntil !== Infinity); - - if (otherPlaylistsLeft) { - const message = `Problem encountered with playlist ${oldPlaylist.id}.` + - ` Excessive ${type} segment downloading detected.` + - ` Switching to playlist ${this.mpc.media().id}.`; - - assert.equal(this.mpcErrors, 0, 'no mpc error'); - assert.notOk(this.mpc.error, 'no mpc error set'); - assert.notOk(this.player.error(), 'player error not set'); - assert.equal(this.env.log.warn.callCount, 1, 'player warning logged'); - assert.equal(this.env.log.warn.args[0][0], message, 'warning message as expected'); - - this.env.log.warn.resetHistory(); - } else { - const message = 'Playback cannot continue. No available working or supported playlists.'; - - assert.equal(this.mpcErrors, 1, 'one mpc error'); - assert.equal(this.mpc.error, message, 'mpc error set'); - assert.equal(this.player.error().message, message, 'player error set'); - assert.equal(this.env.log.error.callCount, 1, 'player error logged'); - assert.equal(this.env.log.error.args[0][1], message, 'error message as expected'); - - this.env.log.error.resetHistory(); - } - }; - - this.setBuffered(videojs.createTimeRanges([[0, 30]])); - loader.trigger('appendsdone'); - assert.equal(this.playbackWatcher[`${type}StalledDownloads_`], 0, 'initial append 0 stalled downloads'); - let i = playlists.length; - - // exclude all playlists and verify - while (i--) { - excludeAndVerify(); - } - - }); - } - QUnit.test(`resets ${type} exclusion on playlistupdate, tech seeking, tech seeked`, function(assert) { this.setup(); const loader = this.mpc[`${type}SegmentLoader_`]; @@ -1120,6 +991,115 @@ loaderTypes.forEach(function(type) { loader.trigger('appendsdone'); assert.equal(this.playbackWatcher[`${type}StalledDownloads_`], 1, '2nd append 1 stalled downloads'); }); + + // the following two tests do not apply to the subtitle loader + if (type === 'subtitle') { + return; + } + + QUnit.test(`detects ${type} appends without buffer changes and excludes`, function(assert) { + this.setup(); + const loader = this.mpc[`${type}SegmentLoader_`]; + + this.setBuffered(videojs.createTimeRanges([[0, 30]])); + + for (let i = 0; i <= EXCLUDE_APPEND_COUNT; i++) { + loader.trigger('appendsdone'); + if (i === EXCLUDE_APPEND_COUNT) { + assert.equal(this.playbackWatcher[`${type}StalledDownloads_`], 0, `append #${i} resets stalled downloads to 0`); + } else { + assert.equal(this.playbackWatcher[`${type}StalledDownloads_`], i, `append #${i + 1} ${i} stalled downloads`); + } + } + + const expectedUsage = {}; + + expectedUsage[`vhs-${type}-download-exclusion`] = 1; + + expectedUsage['vhs-rendition-blacklisted'] = 1; + expectedUsage['hls-rendition-blacklisted'] = 1; + + assert.deepEqual(this.usageEvents, expectedUsage, 'usage as expected'); + + const message = 'Playback cannot continue. No available working or supported playlists.'; + + assert.equal(this.mpcErrors, 1, 'one mpc error'); + assert.equal(this.mpc.error, message, 'mpc error set'); + assert.equal(this.player.error().message, message, 'player error set'); + assert.equal(this.env.log.error.callCount, 1, 'player error logged'); + assert.equal(this.env.log.error.args[0][1], message, 'error message as expected'); + + this.env.log.error.resetHistory(); + }); + + QUnit.test(`detects ${type} appends without buffer changes and excludes many playlists`, function(assert) { + this.setup({src: 'multipleAudioGroupsCombinedMain.m3u8', type: 'application/vnd.apple.mpegurl'}); + + const loader = this.mpc[`${type}SegmentLoader_`]; + const playlists = this.mpc.master().playlists; + const excludeAndVerify = () => { + let oldPlaylist; + // this test only needs 9 appends, since we do an intial append + + for (let i = 0; i < EXCLUDE_APPEND_COUNT; i++) { + oldPlaylist = this.mpc.media(); + loader.trigger('appendsdone'); + if (i === EXCLUDE_APPEND_COUNT - 1) { + assert.equal(this.playbackWatcher[`${type}StalledDownloads_`], 0, `append #${i} resets stalled downloads to 0`); + } else { + assert.equal(this.playbackWatcher[`${type}StalledDownloads_`], i + 1, `append #${i + 1} ${i + 1} stalled downloads`); + } + } + + const expectedUsage = {}; + + expectedUsage[`vhs-${type}-download-exclusion`] = 1; + expectedUsage['vhs-rendition-blacklisted'] = 1; + expectedUsage['hls-rendition-blacklisted'] = 1; + + assert.deepEqual(this.usageEvents, expectedUsage, 'usage as expected'); + this.usageEvents = {}; + + this.respondToPlaylists_(); + + const otherPlaylistsLeft = this.mpc.master().playlists.some((p) => p.excludeUntil !== Infinity); + + if (otherPlaylistsLeft) { + const message = `Problem encountered with playlist ${oldPlaylist.id}.` + + ` Excessive ${type} segment downloading detected.` + + ` Switching to playlist ${this.mpc.media().id}.`; + + assert.equal(this.mpcErrors, 0, 'no mpc error'); + assert.notOk(this.mpc.error, 'no mpc error set'); + assert.notOk(this.player.error(), 'player error not set'); + assert.equal(this.env.log.warn.callCount, 1, 'player warning logged'); + assert.equal(this.env.log.warn.args[0][0], message, 'warning message as expected'); + + this.env.log.warn.resetHistory(); + } else { + const message = 'Playback cannot continue. No available working or supported playlists.'; + + assert.equal(this.mpcErrors, 1, 'one mpc error'); + assert.equal(this.mpc.error, message, 'mpc error set'); + assert.equal(this.player.error().message, message, 'player error set'); + assert.equal(this.env.log.error.callCount, 1, 'player error logged'); + assert.equal(this.env.log.error.args[0][1], message, 'error message as expected'); + + this.env.log.error.resetHistory(); + } + }; + + this.setBuffered(videojs.createTimeRanges([[0, 30]])); + loader.trigger('appendsdone'); + assert.equal(this.playbackWatcher[`${type}StalledDownloads_`], 0, 'initial append 0 stalled downloads'); + let i = playlists.length; + + // exclude all playlists and verify + while (i--) { + excludeAndVerify(); + } + + }); }); QUnit.module('PlaybackWatcher isolated functions', { From c31dee2df1b4956d5987cb4bea19c7cc23065133 Mon Sep 17 00:00:00 2001 From: Gary Katsevman Date: Tue, 3 Nov 2020 17:28:02 -0500 Subject: [PATCH 023/399] chore(package): update aes-decrypter, m3u8 and mpd parser for vhs-utils (#988) --- package-lock.json | 58 ++++++++++------------------------------------- package.json | 6 ++--- 2 files changed, 15 insertions(+), 49 deletions(-) diff --git a/package-lock.json b/package-lock.json index 737be7c66..28ded9846 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1292,26 +1292,16 @@ "dev": true }, "aes-decrypter": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/aes-decrypter/-/aes-decrypter-3.0.2.tgz", - "integrity": "sha512-SBAfPQpGTbHbAR6qSybPjMio+MYuZwdD/a/ltOq6hj53vK94dphAm88rR3FNaZyEa/x3SobYmdT5f46qUwroLQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aes-decrypter/-/aes-decrypter-3.1.0.tgz", + "integrity": "sha512-wL1NFwP2yNrJG4InpXYFhhYe9TfonnDyhyxMq2+K9/qt+SrZzUieOpviN6pkDly7GawTqw5feehk0rn5iYo00g==", "requires": { "@babel/runtime": "^7.5.5", - "@videojs/vhs-utils": "^1.0.0", + "@videojs/vhs-utils": "^2.2.1", "global": "^4.3.2", "pkcs7": "^1.0.4" }, "dependencies": { - "@videojs/vhs-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@videojs/vhs-utils/-/vhs-utils-1.3.0.tgz", - "integrity": "sha512-oiqXDtHQqDPun7JseWkirUHGrgdYdeF12goUut5z7vwAj4DmUufEPFJ4xK5hYGXGFDyDhk2rSFOR122Ze6qXyQ==", - "requires": { - "@babel/runtime": "^7.5.5", - "global": "^4.3.2", - "url-toolkit": "^2.1.6" - } - }, "pkcs7": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/pkcs7/-/pkcs7-1.0.4.tgz", @@ -6583,25 +6573,13 @@ } }, "m3u8-parser": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/m3u8-parser/-/m3u8-parser-4.4.3.tgz", - "integrity": "sha512-o6Z2I0lVeL95gE3BHPB5mSACAA6PTubYCFKlbdQmGNH+Ij0A0oEW8N4V5kqTPgYVnuLcb5UdqNiP7V+xEORhYA==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/m3u8-parser/-/m3u8-parser-4.5.0.tgz", + "integrity": "sha512-RGm/1WVCX3o1bSWbJGmJUu4zTbtJy8lImtgHM4CESFvJRXYztr1j6SW/q9/ghYOrUjgH7radsIar+z1Leln0sA==", "requires": { "@babel/runtime": "^7.5.5", - "@videojs/vhs-utils": "^1.1.0", + "@videojs/vhs-utils": "^2.2.1", "global": "^4.3.2" - }, - "dependencies": { - "@videojs/vhs-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@videojs/vhs-utils/-/vhs-utils-1.3.0.tgz", - "integrity": "sha512-oiqXDtHQqDPun7JseWkirUHGrgdYdeF12goUut5z7vwAj4DmUufEPFJ4xK5hYGXGFDyDhk2rSFOR122Ze6qXyQ==", - "requires": { - "@babel/runtime": "^7.5.5", - "global": "^4.3.2", - "url-toolkit": "^2.1.6" - } - } } }, "magic-string": { @@ -6864,26 +6842,14 @@ "dev": true }, "mpd-parser": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/mpd-parser/-/mpd-parser-0.12.0.tgz", - "integrity": "sha512-Ov5Oz9bw5X/G8V/6PlO+rHuqKywYYjQ6USyv8fqFMs413HkrzlpDjgUKSBD7C+/J19ID5mWtxzrpMf4Yp++iZg==", + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/mpd-parser/-/mpd-parser-0.14.0.tgz", + "integrity": "sha512-HqXQS3WLofcnYFcxv5oWdlciddUaEnN3NasXLVQ793mdnZRrinjz2Yk1DsUYPDYOUWf6ZBBqbFhaJT5LiT2ouA==", "requires": { "@babel/runtime": "^7.5.5", - "@videojs/vhs-utils": "^1.1.0", + "@videojs/vhs-utils": "^2.2.1", "global": "^4.3.2", "xmldom": "^0.1.27" - }, - "dependencies": { - "@videojs/vhs-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@videojs/vhs-utils/-/vhs-utils-1.3.0.tgz", - "integrity": "sha512-oiqXDtHQqDPun7JseWkirUHGrgdYdeF12goUut5z7vwAj4DmUufEPFJ4xK5hYGXGFDyDhk2rSFOR122Ze6qXyQ==", - "requires": { - "@babel/runtime": "^7.5.5", - "global": "^4.3.2", - "url-toolkit": "^2.1.6" - } - } } }, "ms": { diff --git a/package.json b/package.json index 80ecfea88..98f526013 100644 --- a/package.json +++ b/package.json @@ -58,10 +58,10 @@ "dependencies": { "@babel/runtime": "^7.5.5", "@videojs/vhs-utils": "^2.2.1", - "aes-decrypter": "3.0.2", + "aes-decrypter": "3.1.0", "global": "^4.3.2", - "m3u8-parser": "4.4.3", - "mpd-parser": "0.12.0", + "m3u8-parser": "4.5.0", + "mpd-parser": "0.14.0", "mux.js": "5.6.7", "video.js": "^6 || ^7" }, From a82be459e7970963f2f7689af6e80bc4ba2b7d87 Mon Sep 17 00:00:00 2001 From: Gary Katsevman Date: Thu, 5 Nov 2020 12:51:58 -0500 Subject: [PATCH 024/399] 2.3.0 --- CHANGELOG.md | 24 ++++++++++++++++++++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 28649cff3..305a90ad5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,27 @@ + +# [2.3.0](https://github.com/videojs/http-streaming/compare/v2.2.0...v2.3.0) (2020-11-05) + +### Features + +* add experimental buffer based ABR ([#886](https://github.com/videojs/http-streaming/issues/886)) ([a05d032](https://github.com/videojs/http-streaming/commit/a05d032)) + +### Bug Fixes + +* appendsdone abort and handle multiple id3 sections. ([#971](https://github.com/videojs/http-streaming/issues/971)) ([329d50a](https://github.com/videojs/http-streaming/commit/329d50a)) +* check tech error before pause loaders ([#969](https://github.com/videojs/http-streaming/issues/969)) ([0c7b2cb](https://github.com/videojs/http-streaming/commit/0c7b2cb)) +* inline json version ([#967](https://github.com/videojs/http-streaming/issues/967)) ([326ce1c](https://github.com/videojs/http-streaming/commit/326ce1c)) +* **experimentalBufferBasedABR:** call selectPlaylist and change media on an interval ([#978](https://github.com/videojs/http-streaming/issues/978)) ([200c87b](https://github.com/videojs/http-streaming/commit/200c87b)), closes [#886](https://github.com/videojs/http-streaming/issues/886) [#966](https://github.com/videojs/http-streaming/issues/966) [#964](https://github.com/videojs/http-streaming/issues/964) +* only prevent audio group creation if no other playlists are using it ([#981](https://github.com/videojs/http-streaming/issues/981)) ([645e979](https://github.com/videojs/http-streaming/commit/645e979)) +* **playback-watcher:** ignore subtitles ([#980](https://github.com/videojs/http-streaming/issues/980)) ([ca7655e](https://github.com/videojs/http-streaming/commit/ca7655e)) + +### Chores + +* **package:** update aes-decrypter, m3u8 and mpd parser for vhs-utils ([#988](https://github.com/videojs/http-streaming/issues/988)) ([c31dee2](https://github.com/videojs/http-streaming/commit/c31dee2)) + +### Tests + +* **playback-watcher:** subtitle test refactor ([#986](https://github.com/videojs/http-streaming/issues/986)) ([0f66d8e](https://github.com/videojs/http-streaming/commit/0f66d8e)), closes [#980](https://github.com/videojs/http-streaming/issues/980) + # [2.2.0](https://github.com/videojs/http-streaming/compare/v2.1.0...v2.2.0) (2020-09-25) diff --git a/package-lock.json b/package-lock.json index 28ded9846..be036f1dc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@videojs/http-streaming", - "version": "2.2.0", + "version": "2.3.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 98f526013..066bc9877 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@videojs/http-streaming", - "version": "2.2.0", + "version": "2.3.0", "description": "Play back HLS and DASH with Video.js, even where it's not natively supported", "main": "dist/videojs-http-streaming.cjs.js", "module": "dist/videojs-http-streaming.es.js", From c9b195b8d8451118960aba2977c1bbc95fda0120 Mon Sep 17 00:00:00 2001 From: Brandon Casey <2381475+brandonocasey@users.noreply.github.com> Date: Tue, 10 Nov 2020 15:17:34 -0500 Subject: [PATCH 025/399] chore: switch from travis to github actions for ci (#989) --- .github/workflows/ci.yml | 65 + .nvmrc | 2 +- .travis.yml | 20 - package-lock.json | 4129 ++++++++++++++++++++++---------------- package.json | 4 +- test/playback.test.js | 2 +- 6 files changed, 2458 insertions(+), 1764 deletions(-) create mode 100644 .github/workflows/ci.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000..c8fe389ef --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,65 @@ +name: ci + +on: [push, pull_request] + +jobs: + ci: + env: + BROWSER_STACK_USERNAME: ${{ secrets.BROWSER_STACK_USERNAME }} + BROWSER_STACK_ACCESS_KEY: ${{ secrets.BROWSER_STACK_ACCESS_KEY }} + runs-on: ${{ matrix.os }} + strategy: + # TODO: test IE 11, Legacy Edge, and New Edge on windows-latest + # test Safari on macos-latest + matrix: + os: [ubuntu-latest] + + steps: + - uses: actions/checkout@v2 + - name: Cache dependencies + uses: actions/cache@v2 + with: + path: | + ~/.npm + **/node_modules + key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-npm- + ${{ runner.os }}- + + - name: Read .nvmrc + run: echo ::set-output name=NVMRC::$(cat .nvmrc) + shell: bash + id: nvm + + - name: Install ffmpeg/pulseaudio for firefox on linux w/o browserstack + run: sudo apt-get install ffmpeg pulseaudio + if: ${{ startsWith(matrix.os, 'ubuntu') && !env.BROWSER_STACK_USERNAME }} + + - name: start pulseaudio for firefox on linux w/o browserstack + run: pulseaudio -D + if: ${{ startsWith(matrix.os, 'ubuntu') && !env.BROWSER_STACK_USERNAME }} + + - name: Setup node + uses: actions/setup-node@v1 + with: + node-version: '${{ steps.nvm.outputs.NVMRC }}' + - run: npm i --prefer-offline --no-audit + + # run safari on macos + - name: Run Mac test + run: npm run test -- --browsers Safari + if: ${{ startsWith(matrix.os, 'macos') }} + + # only run ie 11 on windows + - name: Run Windows test + run: npm run test -- --browsers IE + if: ${{ startsWith(matrix.os, 'windows') }} + + # run chrome/firefox or browserstack in linux + - name: Run linux test + uses: GabrielBB/xvfb-action@v1 + with: + run: npm test + if: ${{ startsWith(matrix.os, 'ubuntu') }} + diff --git a/.nvmrc b/.nvmrc index 03128968b..f599e28b8 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -lts/dubnium +10 diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 9778d26c0..000000000 --- a/.travis.yml +++ /dev/null @@ -1,20 +0,0 @@ -dist: xenial -language: node_js -# node version is specified using the .nvmrc file -cache: npm -before_install: - - npm install -g greenkeeper-lockfile@1 -before_script: - - greenkeeper-lockfile-update -after_script: - - greenkeeper-lockfile-upload -addons: - firefox: latest - chrome: stable - apt: - update: true - # libav-tools is needed by firefox for h.264 support on linux - packages: - libav-tools -services: - - xvfb diff --git a/package-lock.json b/package-lock.json index be036f1dc..7f613a542 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,69 +5,57 @@ "requires": true, "dependencies": { "@babel/code-frame": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", - "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", "dev": true, "requires": { - "@babel/highlight": "^7.8.3" + "@babel/highlight": "^7.10.4" } }, "@babel/compat-data": { - "version": "7.8.6", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.8.6.tgz", - "integrity": "sha512-CurCIKPTkS25Mb8mz267vU95vy+TyUpnctEX2lV33xWNmHAfjruztgiPBbXZRh3xZZy1CYvGx6XfxyTVS+sk7Q==", - "dev": true, - "requires": { - "browserslist": "^4.8.5", - "invariant": "^2.2.4", - "semver": "^5.5.0" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.12.5.tgz", + "integrity": "sha512-DTsS7cxrsH3by8nqQSpFSyjSfSYl57D6Cf4q8dW3LK83tBKBDCkfcay1nYkXq1nIHXnpX8WMMb/O25HOy3h1zg==", + "dev": true }, "@babel/core": { - "version": "7.8.7", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.8.7.tgz", - "integrity": "sha512-rBlqF3Yko9cynC5CCFy6+K/w2N+Sq/ff2BPy+Krp7rHlABIr5epbA7OxVeKoMHB39LZOp1UY5SuLjy6uWi35yA==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.8.7", - "@babel/helpers": "^7.8.4", - "@babel/parser": "^7.8.7", - "@babel/template": "^7.8.6", - "@babel/traverse": "^7.8.6", - "@babel/types": "^7.8.7", + "version": "7.12.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.3.tgz", + "integrity": "sha512-0qXcZYKZp3/6N2jKYVxZv0aNCsxTSVCiK72DTiTYZAu7sjg73W0/aynWjMbiGd87EQL4WyA8reiJVh92AVla9g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.12.1", + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helpers": "^7.12.1", + "@babel/parser": "^7.12.3", + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.12.1", + "@babel/types": "^7.12.1", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.1", - "json5": "^2.1.0", - "lodash": "^4.17.13", + "json5": "^2.1.2", + "lodash": "^4.17.19", "resolve": "^1.3.2", "semver": "^5.4.1", "source-map": "^0.5.0" }, "dependencies": { "@babel/parser": { - "version": "7.8.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.8.tgz", - "integrity": "sha512-mO5GWzBPsPf6865iIbzNE0AvkKF3NE+2S3eRUpE+FE07BOAkXh6G+GW/Pj01hhXjve1WScbaIO4UlY1JKeqCcA==", + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.5.tgz", + "integrity": "sha512-FVM6RZQ0mn2KCf1VUED7KepYeUWoVShczewOCfm3nzoBybaih51h+sYVVGthW9M6lPByEPTQf+xm27PBdlpwmQ==", "dev": true }, "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.0.tgz", + "integrity": "sha512-jjO6JD2rKfiZQnBoRzhRTbXjHLGLfH+UtGkWLc/UXAh/rzZMyjbgn0NcfFpqT8nd1kTtFnDiJcrIFkq4UKeJVg==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } }, "ms": { @@ -91,14 +79,13 @@ } }, "@babel/generator": { - "version": "7.8.8", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.8.tgz", - "integrity": "sha512-HKyUVu69cZoclptr8t8U5b6sx6zoWjh8jiUhnuj3MpZuKT2dJ8zPTuiy31luq32swhI0SpwItCIlU8XW7BZeJg==", + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.5.tgz", + "integrity": "sha512-m16TQQJ8hPt7E+OS/XVQg/7U184MLXtvuGbCdA7na61vha+ImkyyNM/9DDA0unYCVZn3ZOhng+qz48/KBOT96A==", "dev": true, "requires": { - "@babel/types": "^7.8.7", + "@babel/types": "^7.12.5", "jsesc": "^2.5.1", - "lodash": "^4.17.13", "source-map": "^0.5.0" }, "dependencies": { @@ -111,45 +98,33 @@ } }, "@babel/helper-annotate-as-pure": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.8.3.tgz", - "integrity": "sha512-6o+mJrZBxOoEX77Ezv9zwW7WV8DdluouRKNY/IR5u/YTMuKHgugHOzYWlYvYLpLA9nPsQCAAASpCIbjI9Mv+Uw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz", + "integrity": "sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA==", "dev": true, "requires": { - "@babel/types": "^7.8.3" + "@babel/types": "^7.10.4" } }, "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.8.3.tgz", - "integrity": "sha512-5eFOm2SyFPK4Rh3XMMRDjN7lBH0orh3ss0g3rTYZnBQ+r6YPj7lgDyCvPphynHvUrobJmeMignBr6Acw9mAPlw==", - "dev": true, - "requires": { - "@babel/helper-explode-assignable-expression": "^7.8.3", - "@babel/types": "^7.8.3" - } - }, - "@babel/helper-call-delegate": { - "version": "7.8.7", - "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.8.7.tgz", - "integrity": "sha512-doAA5LAKhsFCR0LAFIf+r2RSMmC+m8f/oQ+URnUET/rWeEzC0yTRmAGyWkD4sSu3xwbS7MYQ2u+xlt1V5R56KQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz", + "integrity": "sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg==", "dev": true, "requires": { - "@babel/helper-hoist-variables": "^7.8.3", - "@babel/traverse": "^7.8.3", - "@babel/types": "^7.8.7" + "@babel/helper-explode-assignable-expression": "^7.10.4", + "@babel/types": "^7.10.4" } }, "@babel/helper-compilation-targets": { - "version": "7.8.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.8.7.tgz", - "integrity": "sha512-4mWm8DCK2LugIS+p1yArqvG1Pf162upsIsjE7cNBjez+NjliQpVhj20obE520nao0o14DaTnFJv+Fw5a0JpoUw==", + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.5.tgz", + "integrity": "sha512-+qH6NrscMolUlzOYngSBMIOQpKUGPPsc61Bu5W10mg84LxZ7cmvnBHzARKbDoFxVvqqAbj6Tg6N7bSrWSPXMyw==", "dev": true, "requires": { - "@babel/compat-data": "^7.8.6", - "browserslist": "^4.9.1", - "invariant": "^2.2.4", - "levenary": "^1.1.1", + "@babel/compat-data": "^7.12.5", + "@babel/helper-validator-option": "^7.12.1", + "browserslist": "^4.14.5", "semver": "^5.5.0" }, "dependencies": { @@ -161,199 +136,231 @@ } } }, + "@babel/helper-create-class-features-plugin": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.12.1.tgz", + "integrity": "sha512-hkL++rWeta/OVOBTRJc9a5Azh5mt5WgZUGAKMD8JM141YsE08K//bp1unBBieO6rUKkIPyUE0USQ30jAy3Sk1w==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-member-expression-to-functions": "^7.12.1", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/helper-replace-supers": "^7.12.1", + "@babel/helper-split-export-declaration": "^7.10.4" + } + }, "@babel/helper-create-regexp-features-plugin": { - "version": "7.8.8", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.8.tgz", - "integrity": "sha512-LYVPdwkrQEiX9+1R29Ld/wTrmQu1SSKYnuOk3g0CkcZMA1p0gsNxJFj/3gBdaJ7Cg0Fnek5z0DsMULePP7Lrqg==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.1.tgz", + "integrity": "sha512-rsZ4LGvFTZnzdNZR5HZdmJVuXK8834R5QkF3WvcnBhrlVtF0HSIUC6zbreL9MgjTywhKokn8RIYRiq99+DLAxA==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.8.3", - "@babel/helper-regex": "^7.8.3", - "regexpu-core": "^4.7.0" + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-regex": "^7.10.4", + "regexpu-core": "^4.7.1" } }, "@babel/helper-define-map": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.8.3.tgz", - "integrity": "sha512-PoeBYtxoZGtct3md6xZOCWPcKuMuk3IHhgxsRRNtnNShebf4C8YonTSblsK4tvDbm+eJAw2HAPOfCr+Q/YRG/g==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz", + "integrity": "sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ==", "dev": true, "requires": { - "@babel/helper-function-name": "^7.8.3", - "@babel/types": "^7.8.3", - "lodash": "^4.17.13" + "@babel/helper-function-name": "^7.10.4", + "@babel/types": "^7.10.5", + "lodash": "^4.17.19" } }, "@babel/helper-explode-assignable-expression": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.8.3.tgz", - "integrity": "sha512-N+8eW86/Kj147bO9G2uclsg5pwfs/fqqY5rwgIL7eTBklgXjcOJ3btzS5iM6AitJcftnY7pm2lGsrJVYLGjzIw==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.12.1.tgz", + "integrity": "sha512-dmUwH8XmlrUpVqgtZ737tK88v07l840z9j3OEhCLwKTkjlvKpfqXVIZ0wpK3aeOxspwGrf/5AP5qLx4rO3w5rA==", "dev": true, "requires": { - "@babel/traverse": "^7.8.3", - "@babel/types": "^7.8.3" + "@babel/types": "^7.12.1" } }, "@babel/helper-function-name": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", - "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", + "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", "dev": true, "requires": { - "@babel/helper-get-function-arity": "^7.8.3", - "@babel/template": "^7.8.3", - "@babel/types": "^7.8.3" + "@babel/helper-get-function-arity": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" } }, "@babel/helper-get-function-arity": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", - "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", + "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", "dev": true, "requires": { - "@babel/types": "^7.8.3" + "@babel/types": "^7.10.4" } }, "@babel/helper-hoist-variables": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.8.3.tgz", - "integrity": "sha512-ky1JLOjcDUtSc+xkt0xhYff7Z6ILTAHKmZLHPxAhOP0Nd77O+3nCsd6uSVYur6nJnCI029CrNbYlc0LoPfAPQg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz", + "integrity": "sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA==", "dev": true, "requires": { - "@babel/types": "^7.8.3" + "@babel/types": "^7.10.4" } }, "@babel/helper-member-expression-to-functions": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz", - "integrity": "sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.1.tgz", + "integrity": "sha512-k0CIe3tXUKTRSoEx1LQEPFU9vRQfqHtl+kf8eNnDqb4AUJEy5pz6aIiog+YWtVm2jpggjS1laH68bPsR+KWWPQ==", "dev": true, "requires": { - "@babel/types": "^7.8.3" + "@babel/types": "^7.12.1" } }, "@babel/helper-module-imports": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz", - "integrity": "sha512-R0Bx3jippsbAEtzkpZ/6FIiuzOURPcMjHp+Z6xPe6DtApDJx+w7UYyOLanZqO8+wKR9G10s/FmHXvxaMd9s6Kg==", + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz", + "integrity": "sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA==", "dev": true, "requires": { - "@babel/types": "^7.8.3" + "@babel/types": "^7.12.5" } }, "@babel/helper-module-transforms": { - "version": "7.8.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.8.6.tgz", - "integrity": "sha512-RDnGJSR5EFBJjG3deY0NiL0K9TO8SXxS9n/MPsbPK/s9LbQymuLNtlzvDiNS7IpecuL45cMeLVkA+HfmlrnkRg==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz", + "integrity": "sha512-QQzehgFAZ2bbISiCpmVGfiGux8YVFXQ0abBic2Envhej22DVXV9nCFaS5hIQbkyo1AdGb+gNME2TSh3hYJVV/w==", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.8.3", - "@babel/helper-replace-supers": "^7.8.6", - "@babel/helper-simple-access": "^7.8.3", - "@babel/helper-split-export-declaration": "^7.8.3", - "@babel/template": "^7.8.6", - "@babel/types": "^7.8.6", - "lodash": "^4.17.13" + "@babel/helper-module-imports": "^7.12.1", + "@babel/helper-replace-supers": "^7.12.1", + "@babel/helper-simple-access": "^7.12.1", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/helper-validator-identifier": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.12.1", + "@babel/types": "^7.12.1", + "lodash": "^4.17.19" } }, "@babel/helper-optimise-call-expression": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz", - "integrity": "sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz", + "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==", "dev": true, "requires": { - "@babel/types": "^7.8.3" + "@babel/types": "^7.10.4" } }, "@babel/helper-plugin-utils": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", - "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", "dev": true }, "@babel/helper-regex": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.8.3.tgz", - "integrity": "sha512-BWt0QtYv/cg/NecOAZMdcn/waj/5P26DR4mVLXfFtDokSR6fyuG0Pj+e2FqtSME+MqED1khnSMulkmGl8qWiUQ==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.10.5.tgz", + "integrity": "sha512-68kdUAzDrljqBrio7DYAEgCoJHxppJOERHOgOrDN7WjOzP0ZQ1LsSDRXcemzVZaLvjaJsJEESb6qt+znNuENDg==", "dev": true, "requires": { - "lodash": "^4.17.13" + "lodash": "^4.17.19" } }, "@babel/helper-remap-async-to-generator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.8.3.tgz", - "integrity": "sha512-kgwDmw4fCg7AVgS4DukQR/roGp+jP+XluJE5hsRZwxCYGg+Rv9wSGErDWhlI90FODdYfd4xG4AQRiMDjjN0GzA==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.12.1.tgz", + "integrity": "sha512-9d0KQCRM8clMPcDwo8SevNs+/9a8yWVVmaE80FGJcEP8N1qToREmWEGnBn8BUlJhYRFz6fqxeRL1sl5Ogsed7A==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.8.3", - "@babel/helper-wrap-function": "^7.8.3", - "@babel/template": "^7.8.3", - "@babel/traverse": "^7.8.3", - "@babel/types": "^7.8.3" + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-wrap-function": "^7.10.4", + "@babel/types": "^7.12.1" } }, "@babel/helper-replace-supers": { - "version": "7.8.6", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.8.6.tgz", - "integrity": "sha512-PeMArdA4Sv/Wf4zXwBKPqVj7n9UF/xg6slNRtZW84FM7JpE1CbG8B612FyM4cxrf4fMAMGO0kR7voy1ForHHFA==", + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.12.5.tgz", + "integrity": "sha512-5YILoed0ZyIpF4gKcpZitEnXEJ9UoDRki1Ey6xz46rxOzfNMAhVIJMoune1hmPVxh40LRv1+oafz7UsWX+vyWA==", "dev": true, "requires": { - "@babel/helper-member-expression-to-functions": "^7.8.3", - "@babel/helper-optimise-call-expression": "^7.8.3", - "@babel/traverse": "^7.8.6", - "@babel/types": "^7.8.6" + "@babel/helper-member-expression-to-functions": "^7.12.1", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/traverse": "^7.12.5", + "@babel/types": "^7.12.5" } }, "@babel/helper-simple-access": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.8.3.tgz", - "integrity": "sha512-VNGUDjx5cCWg4vvCTR8qQ7YJYZ+HBjxOgXEl7ounz+4Sn7+LMD3CFrCTEU6/qXKbA2nKg21CwhhBzO0RpRbdCw==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.12.1.tgz", + "integrity": "sha512-OxBp7pMrjVewSSC8fXDFrHrBcJATOOFssZwv16F3/6Xtc138GHybBfPbm9kfiqQHKhYQrlamWILwlDCeyMFEaA==", + "dev": true, + "requires": { + "@babel/types": "^7.12.1" + } + }, + "@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.12.1.tgz", + "integrity": "sha512-Mf5AUuhG1/OCChOJ/HcADmvcHM42WJockombn8ATJG3OnyiSxBK/Mm5x78BQWvmtXZKHgbjdGL2kin/HOLlZGA==", "dev": true, "requires": { - "@babel/template": "^7.8.3", - "@babel/types": "^7.8.3" + "@babel/types": "^7.12.1" } }, "@babel/helper-split-export-declaration": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", - "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", + "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", "dev": true, "requires": { - "@babel/types": "^7.8.3" + "@babel/types": "^7.11.0" } }, + "@babel/helper-validator-identifier": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.1.tgz", + "integrity": "sha512-YpJabsXlJVWP0USHjnC/AQDTLlZERbON577YUVO/wLpqyj6HAtVYnWaQaN0iUN+1/tWn3c+uKKXjRut5115Y2A==", + "dev": true + }, "@babel/helper-wrap-function": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.8.3.tgz", - "integrity": "sha512-LACJrbUET9cQDzb6kG7EeD7+7doC3JNvUgTEQOx2qaO1fKlzE/Bf05qs9w1oXQMmXlPO65lC3Tq9S6gZpTErEQ==", + "version": "7.12.3", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.12.3.tgz", + "integrity": "sha512-Cvb8IuJDln3rs6tzjW3Y8UeelAOdnpB8xtQ4sme2MSZ9wOxrbThporC0y/EtE16VAtoyEfLM404Xr1e0OOp+ow==", "dev": true, "requires": { - "@babel/helper-function-name": "^7.8.3", - "@babel/template": "^7.8.3", - "@babel/traverse": "^7.8.3", - "@babel/types": "^7.8.3" + "@babel/helper-function-name": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" } }, "@babel/helpers": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.8.4.tgz", - "integrity": "sha512-VPbe7wcQ4chu4TDQjimHv/5tj73qz88o12EPkO2ValS2QiQS/1F2SsjyIGNnAD0vF/nZS6Cf9i+vW6HIlnaR8w==", + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.12.5.tgz", + "integrity": "sha512-lgKGMQlKqA8meJqKsW6rUnc4MdUk35Ln0ATDqdM1a/UpARODdI4j5Y5lVfUScnSNkJcdCRAaWkspykNoFg9sJA==", "dev": true, "requires": { - "@babel/template": "^7.8.3", - "@babel/traverse": "^7.8.4", - "@babel/types": "^7.8.3" + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.12.5", + "@babel/types": "^7.12.5" } }, "@babel/highlight": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", - "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", "dev": true, "requires": { + "@babel/helper-validator-identifier": "^7.10.4", "chalk": "^2.0.0", - "esutils": "^2.0.2", "js-tokens": "^4.0.0" } }, @@ -364,84 +371,136 @@ "dev": true }, "@babel/plugin-proposal-async-generator-functions": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.8.3.tgz", - "integrity": "sha512-NZ9zLv848JsV3hs8ryEh7Uaz/0KsmPLqv0+PdkDJL1cJy0K4kOCFa8zc1E3mp+RHPQcpdfb/6GovEsW4VDrOMw==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.1.tgz", + "integrity": "sha512-d+/o30tJxFxrA1lhzJqiUcEJdI6jKlNregCv5bASeGf2Q4MXmnwH7viDo7nhx1/ohf09oaH8j1GVYG/e3Yqk6A==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/helper-remap-async-to-generator": "^7.8.3", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-remap-async-to-generator": "^7.12.1", "@babel/plugin-syntax-async-generators": "^7.8.0" } }, + "@babel/plugin-proposal-class-properties": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.12.1.tgz", + "integrity": "sha512-cKp3dlQsFsEs5CWKnN7BnSHOd0EOW8EKpEjkoz1pO2E5KzIDNV9Ros1b0CnmbVgAGXJubOYVBOGCT1OmJwOI7w==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, "@babel/plugin-proposal-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.8.3.tgz", - "integrity": "sha512-NyaBbyLFXFLT9FP+zk0kYlUlA8XtCUbehs67F0nnEg7KICgMc2mNkIeu9TYhKzyXMkrapZFwAhXLdnt4IYHy1w==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.12.1.tgz", + "integrity": "sha512-a4rhUSZFuq5W8/OO8H7BL5zspjnc1FLd9hlOxIK/f7qG4a0qsqk8uvF/ywgBA8/OmjsapjpvaEOYItfGG1qIvQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-plugin-utils": "^7.10.4", "@babel/plugin-syntax-dynamic-import": "^7.8.0" } }, + "@babel/plugin-proposal-export-namespace-from": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.12.1.tgz", + "integrity": "sha512-6CThGf0irEkzujYS5LQcjBx8j/4aQGiVv7J9+2f7pGfxqyKh3WnmVJYW3hdrQjyksErMGBPQrCnHfOtna+WLbw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + } + }, "@babel/plugin-proposal-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.8.3.tgz", - "integrity": "sha512-KGhQNZ3TVCQG/MjRbAUwuH+14y9q0tpxs1nWWs3pbSleRdDro9SAMMDyye8HhY1gqZ7/NqIc8SKhya0wRDgP1Q==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.12.1.tgz", + "integrity": "sha512-GoLDUi6U9ZLzlSda2Df++VSqDJg3CG+dR0+iWsv6XRw1rEq+zwt4DirM9yrxW6XWaTpmai1cWJLMfM8qQJf+yw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-plugin-utils": "^7.10.4", "@babel/plugin-syntax-json-strings": "^7.8.0" } }, + "@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.12.1.tgz", + "integrity": "sha512-k8ZmVv0JU+4gcUGeCDZOGd0lCIamU/sMtIiX3UWnUc5yzgq6YUGyEolNYD+MLYKfSzgECPcqetVcJP9Afe/aCA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + } + }, "@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-TS9MlfzXpXKt6YYomudb/KU7nQI6/xnapG6in1uZxoxDghuSMZsPb6D2fyUwNYSAp4l1iR7QtFOjkqcRYcUsfw==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.12.1.tgz", + "integrity": "sha512-nZY0ESiaQDI1y96+jk6VxMOaL4LPo/QDHBqL+SF3/vl6dHkTwHlOI8L4ZwuRBHgakRBw5zsVylel7QPbbGuYgg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-plugin-utils": "^7.10.4", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0" } }, + "@babel/plugin-proposal-numeric-separator": { + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.5.tgz", + "integrity": "sha512-UiAnkKuOrCyjZ3sYNHlRlfuZJbBHknMQ9VMwVeX97Ofwx7RpD6gS2HfqTCh8KNUQgcOm8IKt103oR4KIjh7Q8g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + } + }, "@babel/plugin-proposal-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-8qvuPwU/xxUCt78HocNlv0mXXo0wdh9VT1R04WU8HGOfaOob26pF+9P5/lYjN/q7DHOX1bvX60hnhOvuQUJdbA==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz", + "integrity": "sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/plugin-syntax-object-rest-spread": "^7.8.0" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-transform-parameters": "^7.12.1" } }, "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-0gkX7J7E+AtAw9fcwlVQj8peP61qhdg/89D5swOkjYbkboA2CVckn3kiyum1DE0wskGb7KJJxBdyEBApDLLVdw==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.12.1.tgz", + "integrity": "sha512-hFvIjgprh9mMw5v42sJWLI1lzU5L2sznP805zeT6rySVRA0Y18StRhDqhSxlap0oVgItRsB6WSROp4YnJTJz0g==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-plugin-utils": "^7.10.4", "@babel/plugin-syntax-optional-catch-binding": "^7.8.0" } }, "@babel/plugin-proposal-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.8.3.tgz", - "integrity": "sha512-QIoIR9abkVn+seDE3OjA08jWcs3eZ9+wJCKSRgo3WdEU2csFYgdScb+8qHB3+WXsGJD55u+5hWCISI7ejXS+kg==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.1.tgz", + "integrity": "sha512-c2uRpY6WzaVDzynVY9liyykS+kVU+WRZPMPYpkelXH8KBt1oXoI89kPbZKKG/jDT5UK92FTW2fZkZaJhdiBabw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-skip-transparent-expression-wrappers": "^7.12.1", "@babel/plugin-syntax-optional-chaining": "^7.8.0" } }, + "@babel/plugin-proposal-private-methods": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.12.1.tgz", + "integrity": "sha512-mwZ1phvH7/NHK6Kf8LP7MYDogGV+DKB1mryFOEwx5EBNQrosvIczzZFTUmWaeujd5xT6G1ELYWUz3CutMhjE1w==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.8.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.8.8.tgz", - "integrity": "sha512-EVhjVsMpbhLw9ZfHWSx2iy13Q8Z/eg8e8ccVWt23sWQK5l1UdkoLJPN5w69UA4uITGBnEZD2JOe4QOHycYKv8A==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.12.1.tgz", + "integrity": "sha512-MYq+l+PvHuw/rKUz1at/vb6nCnQ2gmJBNaM62z0OgH7B2W1D9pvkpYtlti9bGtizNIU1K3zm4bZF9F91efVY0w==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.8.8", - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-create-regexp-features-plugin": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-syntax-async-generators": { @@ -453,6 +512,15 @@ "@babel/helper-plugin-utils": "^7.8.0" } }, + "@babel/plugin-syntax-class-properties": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.1.tgz", + "integrity": "sha512-U40A76x5gTwmESz+qiqssqmeEsKvcSyvtgktrm0uzcARAmM9I1jR221f6Oq+GmHrcD+LvZDag1UTOTe2fL3TeA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, "@babel/plugin-syntax-dynamic-import": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", @@ -462,6 +530,15 @@ "@babel/helper-plugin-utils": "^7.8.0" } }, + "@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, "@babel/plugin-syntax-json-strings": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", @@ -471,6 +548,15 @@ "@babel/helper-plugin-utils": "^7.8.0" } }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, "@babel/plugin-syntax-nullish-coalescing-operator": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", @@ -480,6 +566,15 @@ "@babel/helper-plugin-utils": "^7.8.0" } }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, "@babel/plugin-syntax-object-rest-spread": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", @@ -508,281 +603,279 @@ } }, "@babel/plugin-syntax-top-level-await": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.8.3.tgz", - "integrity": "sha512-kwj1j9lL/6Wd0hROD3b/OZZ7MSrZLqqn9RAZ5+cYYsflQ9HZBIKCUkr3+uL1MEJ1NePiUbf98jjiMQSv0NMR9g==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.1.tgz", + "integrity": "sha512-i7ooMZFS+a/Om0crxZodrTzNEPJHZrlMVGMTEpFAj6rYY/bKCddB0Dk/YxfPuYXOopuhKk/e1jV6h+WUU9XN3A==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-arrow-functions": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.8.3.tgz", - "integrity": "sha512-0MRF+KC8EqH4dbuITCWwPSzsyO3HIWWlm30v8BbbpOrS1B++isGxPnnuq/IZvOX5J2D/p7DQalQm+/2PnlKGxg==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.12.1.tgz", + "integrity": "sha512-5QB50qyN44fzzz4/qxDPQMBCTHgxg3n0xRBLJUmBlLoU/sFvxVWGZF/ZUfMVDQuJUKXaBhbupxIzIfZ6Fwk/0A==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-async-to-generator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.8.3.tgz", - "integrity": "sha512-imt9tFLD9ogt56Dd5CI/6XgpukMwd/fLGSrix2httihVe7LOGVPhyhMh1BU5kDM7iHD08i8uUtmV2sWaBFlHVQ==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.12.1.tgz", + "integrity": "sha512-SDtqoEcarK1DFlRJ1hHRY5HvJUj5kX4qmtpMAm2QnhOlyuMC4TMdCRgW6WXpv93rZeYNeLP22y8Aq2dbcDRM1A==", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/helper-remap-async-to-generator": "^7.8.3" + "@babel/helper-module-imports": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-remap-async-to-generator": "^7.12.1" } }, "@babel/plugin-transform-block-scoped-functions": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.8.3.tgz", - "integrity": "sha512-vo4F2OewqjbB1+yaJ7k2EJFHlTP3jR634Z9Cj9itpqNjuLXvhlVxgnjsHsdRgASR8xYDrx6onw4vW5H6We0Jmg==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.12.1.tgz", + "integrity": "sha512-5OpxfuYnSgPalRpo8EWGPzIYf0lHBWORCkj5M0oLBwHdlux9Ri36QqGW3/LR13RSVOAoUUMzoPI/jpE4ABcHoA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-block-scoping": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.8.3.tgz", - "integrity": "sha512-pGnYfm7RNRgYRi7bids5bHluENHqJhrV4bCZRwc5GamaWIIs07N4rZECcmJL6ZClwjDz1GbdMZFtPs27hTB06w==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.1.tgz", + "integrity": "sha512-zJyAC9sZdE60r1nVQHblcfCj29Dh2Y0DOvlMkcqSo0ckqjiCwNiUezUKw+RjOCwGfpLRwnAeQ2XlLpsnGkvv9w==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3", - "lodash": "^4.17.13" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-classes": { - "version": "7.8.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.8.6.tgz", - "integrity": "sha512-k9r8qRay/R6v5aWZkrEclEhKO6mc1CCQr2dLsVHBmOQiMpN6I2bpjX3vgnldUWeEI1GHVNByULVxZ4BdP4Hmdg==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.8.3", - "@babel/helper-define-map": "^7.8.3", - "@babel/helper-function-name": "^7.8.3", - "@babel/helper-optimise-call-expression": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/helper-replace-supers": "^7.8.6", - "@babel/helper-split-export-declaration": "^7.8.3", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.12.1.tgz", + "integrity": "sha512-/74xkA7bVdzQTBeSUhLLJgYIcxw/dpEpCdRDiHgPJ3Mv6uC11UhjpOhl72CgqbBCmt1qtssCyB2xnJm1+PFjog==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-define-map": "^7.10.4", + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-replace-supers": "^7.12.1", + "@babel/helper-split-export-declaration": "^7.10.4", "globals": "^11.1.0" } }, "@babel/plugin-transform-computed-properties": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.8.3.tgz", - "integrity": "sha512-O5hiIpSyOGdrQZRQ2ccwtTVkgUDBBiCuK//4RJ6UfePllUTCENOzKxfh6ulckXKc0DixTFLCfb2HVkNA7aDpzA==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.12.1.tgz", + "integrity": "sha512-vVUOYpPWB7BkgUWPo4C44mUQHpTZXakEqFjbv8rQMg7TC6S6ZhGZ3otQcRH6u7+adSlE5i0sp63eMC/XGffrzg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-destructuring": { - "version": "7.8.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.8.8.tgz", - "integrity": "sha512-eRJu4Vs2rmttFCdhPUM3bV0Yo/xPSdPw6ML9KHs/bjB4bLA5HXlbvYXPOD5yASodGod+krjYx21xm1QmL8dCJQ==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.12.1.tgz", + "integrity": "sha512-fRMYFKuzi/rSiYb2uRLiUENJOKq4Gnl+6qOv5f8z0TZXg3llUwUhsNNwrwaT/6dUhJTzNpBr+CUvEWBtfNY1cw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-dotall-regex": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.8.3.tgz", - "integrity": "sha512-kLs1j9Nn4MQoBYdRXH6AeaXMbEJFaFu/v1nQkvib6QzTj8MZI5OQzqmD83/2jEM1z0DLilra5aWO5YpyC0ALIw==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.12.1.tgz", + "integrity": "sha512-B2pXeRKoLszfEW7J4Hg9LoFaWEbr/kzo3teWHmtFCszjRNa/b40f9mfeqZsIDLLt/FjwQ6pz/Gdlwy85xNckBA==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-create-regexp-features-plugin": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-duplicate-keys": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.8.3.tgz", - "integrity": "sha512-s8dHiBUbcbSgipS4SMFuWGqCvyge5V2ZeAWzR6INTVC3Ltjig/Vw1G2Gztv0vU/hRG9X8IvKvYdoksnUfgXOEQ==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.12.1.tgz", + "integrity": "sha512-iRght0T0HztAb/CazveUpUQrZY+aGKKaWXMJ4uf9YJtqxSUe09j3wteztCUDRHs+SRAL7yMuFqUsLoAKKzgXjw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-exponentiation-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.8.3.tgz", - "integrity": "sha512-zwIpuIymb3ACcInbksHaNcR12S++0MDLKkiqXHl3AzpgdKlFNhog+z/K0+TGW+b0w5pgTq4H6IwV/WhxbGYSjQ==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.12.1.tgz", + "integrity": "sha512-7tqwy2bv48q+c1EHbXK0Zx3KXd2RVQp6OC7PbwFNt/dPTAV3Lu5sWtWuAj8owr5wqtWnqHfl2/mJlUmqkChKug==", "dev": true, "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-for-of": { - "version": "7.8.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.8.6.tgz", - "integrity": "sha512-M0pw4/1/KI5WAxPsdcUL/w2LJ7o89YHN3yLkzNjg7Yl15GlVGgzHyCU+FMeAxevHGsLVmUqbirlUIKTafPmzdw==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.12.1.tgz", + "integrity": "sha512-Zaeq10naAsuHo7heQvyV0ptj4dlZJwZgNAtBYBnu5nNKJoW62m0zKcIEyVECrUKErkUkg6ajMy4ZfnVZciSBhg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-function-name": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.8.3.tgz", - "integrity": "sha512-rO/OnDS78Eifbjn5Py9v8y0aR+aSYhDhqAwVfsTl0ERuMZyr05L1aFSCJnbv2mmsLkit/4ReeQ9N2BgLnOcPCQ==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.12.1.tgz", + "integrity": "sha512-JF3UgJUILoFrFMEnOJLJkRHSk6LUSXLmEFsA23aR2O5CSLUxbeUX1IZ1YQ7Sn0aXb601Ncwjx73a+FVqgcljVw==", "dev": true, "requires": { - "@babel/helper-function-name": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-literals": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.8.3.tgz", - "integrity": "sha512-3Tqf8JJ/qB7TeldGl+TT55+uQei9JfYaregDcEAyBZ7akutriFrt6C/wLYIer6OYhleVQvH/ntEhjE/xMmy10A==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.12.1.tgz", + "integrity": "sha512-+PxVGA+2Ag6uGgL0A5f+9rklOnnMccwEBzwYFL3EUaKuiyVnUipyXncFcfjSkbimLrODoqki1U9XxZzTvfN7IQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-member-expression-literals": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.8.3.tgz", - "integrity": "sha512-3Wk2EXhnw+rP+IDkK6BdtPKsUE5IeZ6QOGrPYvw52NwBStw9V1ZVzxgK6fSKSxqUvH9eQPR3tm3cOq79HlsKYA==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.12.1.tgz", + "integrity": "sha512-1sxePl6z9ad0gFMB9KqmYofk34flq62aqMt9NqliS/7hPEpURUCMbyHXrMPlo282iY7nAvUB1aQd5mg79UD9Jg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-modules-amd": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.8.3.tgz", - "integrity": "sha512-MadJiU3rLKclzT5kBH4yxdry96odTUwuqrZM+GllFI/VhxfPz+k9MshJM+MwhfkCdxxclSbSBbUGciBngR+kEQ==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.12.1.tgz", + "integrity": "sha512-tDW8hMkzad5oDtzsB70HIQQRBiTKrhfgwC/KkJeGsaNFTdWhKNt/BiE8c5yj19XiGyrxpbkOfH87qkNg1YGlOQ==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3", - "babel-plugin-dynamic-import-node": "^2.3.0" + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4", + "babel-plugin-dynamic-import-node": "^2.3.3" } }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.8.3.tgz", - "integrity": "sha512-JpdMEfA15HZ/1gNuB9XEDlZM1h/gF/YOH7zaZzQu2xCFRfwc01NXBMHHSTT6hRjlXJJs5x/bfODM3LiCk94Sxg==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.12.1.tgz", + "integrity": "sha512-dY789wq6l0uLY8py9c1B48V8mVL5gZh/+PQ5ZPrylPYsnAvnEMjqsUXkuoDVPeVK+0VyGar+D08107LzDQ6pag==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/helper-simple-access": "^7.8.3", - "babel-plugin-dynamic-import-node": "^2.3.0" + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-simple-access": "^7.12.1", + "babel-plugin-dynamic-import-node": "^2.3.3" } }, "@babel/plugin-transform-modules-systemjs": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.8.3.tgz", - "integrity": "sha512-8cESMCJjmArMYqa9AO5YuMEkE4ds28tMpZcGZB/jl3n0ZzlsxOAi3mC+SKypTfT8gjMupCnd3YiXCkMjj2jfOg==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.12.1.tgz", + "integrity": "sha512-Hn7cVvOavVh8yvW6fLwveFqSnd7rbQN3zJvoPNyNaQSvgfKmDBO9U1YL9+PCXGRlZD9tNdWTy5ACKqMuzyn32Q==", "dev": true, "requires": { - "@babel/helper-hoist-variables": "^7.8.3", - "@babel/helper-module-transforms": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3", - "babel-plugin-dynamic-import-node": "^2.3.0" + "@babel/helper-hoist-variables": "^7.10.4", + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-validator-identifier": "^7.10.4", + "babel-plugin-dynamic-import-node": "^2.3.3" } }, "@babel/plugin-transform-modules-umd": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.8.3.tgz", - "integrity": "sha512-evhTyWhbwbI3/U6dZAnx/ePoV7H6OUG+OjiJFHmhr9FPn0VShjwC2kdxqIuQ/+1P50TMrneGzMeyMTFOjKSnAw==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.12.1.tgz", + "integrity": "sha512-aEIubCS0KHKM0zUos5fIoQm+AZUMt1ZvMpqz0/H5qAQ7vWylr9+PLYurT+Ic7ID/bKLd4q8hDovaG3Zch2uz5Q==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.8.3.tgz", - "integrity": "sha512-f+tF/8UVPU86TrCb06JoPWIdDpTNSGGcAtaD9mLP0aYGA0OS0j7j7DHJR0GTFrUZPUU6loZhbsVZgTh0N+Qdnw==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.12.1.tgz", + "integrity": "sha512-tB43uQ62RHcoDp9v2Nsf+dSM8sbNodbEicbQNA53zHz8pWUhsgHSJCGpt7daXxRydjb0KnfmB+ChXOv3oADp1Q==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.8.3" + "@babel/helper-create-regexp-features-plugin": "^7.12.1" } }, "@babel/plugin-transform-new-target": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.8.3.tgz", - "integrity": "sha512-QuSGysibQpyxexRyui2vca+Cmbljo8bcRckgzYV4kRIsHpVeyeC3JDO63pY+xFZ6bWOBn7pfKZTqV4o/ix9sFw==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.12.1.tgz", + "integrity": "sha512-+eW/VLcUL5L9IvJH7rT1sT0CzkdUTvPrXC2PXTn/7z7tXLBuKvezYbGdxD5WMRoyvyaujOq2fWoKl869heKjhw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-object-assign": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-assign/-/plugin-transform-object-assign-7.8.3.tgz", - "integrity": "sha512-i3LuN8tPDqUCRFu3dkzF2r1Nx0jp4scxtm7JxtIqI9he9Vk20YD+/zshdzR9JLsoBMlJlNR82a62vQExNEVx/Q==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-assign/-/plugin-transform-object-assign-7.12.1.tgz", + "integrity": "sha512-geUHn4XwHznRAFiuROTy0Hr7bKbpijJCmr1Svt/VNGhpxmp0OrdxURNpWbOAf94nUbL+xj6gbxRVPHWIbRpRoA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-object-super": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.8.3.tgz", - "integrity": "sha512-57FXk+gItG/GejofIyLIgBKTas4+pEU47IXKDBWFTxdPd7F80H8zybyAY7UoblVfBhBGs2EKM+bJUu2+iUYPDQ==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.12.1.tgz", + "integrity": "sha512-AvypiGJH9hsquNUn+RXVcBdeE3KHPZexWRdimhuV59cSoOt5kFBmqlByorAeUlGG2CJWd0U+4ZtNKga/TB0cAw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/helper-replace-supers": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-replace-supers": "^7.12.1" } }, "@babel/plugin-transform-parameters": { - "version": "7.8.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.8.8.tgz", - "integrity": "sha512-hC4Ld/Ulpf1psQciWWwdnUspQoQco2bMzSrwU6TmzRlvoYQe4rQFy9vnCZDTlVeCQj0JPfL+1RX0V8hCJvkgBA==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.12.1.tgz", + "integrity": "sha512-xq9C5EQhdPK23ZeCdMxl8bbRnAgHFrw5EOC3KJUsSylZqdkCaFEXxGSBuTSObOpiiHHNyb82es8M1QYgfQGfNg==", "dev": true, "requires": { - "@babel/helper-call-delegate": "^7.8.7", - "@babel/helper-get-function-arity": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-property-literals": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.8.3.tgz", - "integrity": "sha512-uGiiXAZMqEoQhRWMK17VospMZh5sXWg+dlh2soffpkAl96KAm+WZuJfa6lcELotSRmooLqg0MWdH6UUq85nmmg==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.12.1.tgz", + "integrity": "sha512-6MTCR/mZ1MQS+AwZLplX4cEySjCpnIF26ToWo942nqn8hXSm7McaHQNeGx/pt7suI1TWOWMfa/NgBhiqSnX0cQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-regenerator": { - "version": "7.8.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.7.tgz", - "integrity": "sha512-TIg+gAl4Z0a3WmD3mbYSk+J9ZUH6n/Yc57rtKRnlA/7rcCvpekHXe0CMZHP1gYp7/KLe9GHTuIba0vXmls6drA==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.12.1.tgz", + "integrity": "sha512-gYrHqs5itw6i4PflFX3OdBPMQdPbF4bj2REIUxlMRUFk0/ZOAIpDFuViuxPjUL7YC8UPnf+XG7/utJvqXdPKng==", "dev": true, "requires": { "regenerator-transform": "^0.14.2" } }, "@babel/plugin-transform-reserved-words": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.8.3.tgz", - "integrity": "sha512-mwMxcycN3omKFDjDQUl+8zyMsBfjRFr0Zn/64I41pmjv4NJuqcYlEtezwYtw9TFd9WR1vN5kiM+O0gMZzO6L0A==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.12.1.tgz", + "integrity": "sha512-pOnUfhyPKvZpVyBHhSBoX8vfA09b7r00Pmm1sH+29ae2hMTKVmSp4Ztsr8KBKjLjx17H0eJqaRC3bR2iThM54A==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-runtime": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.8.3.tgz", - "integrity": "sha512-/vqUt5Yh+cgPZXXjmaG9NT8aVfThKk7G4OqkVhrXqwsC5soMn/qTCxs36rZ2QFhpfTJcjw4SNDIZ4RUb8OL4jQ==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.12.1.tgz", + "integrity": "sha512-Ac/H6G9FEIkS2tXsZjL4RAdS3L3WHxci0usAnz7laPWUmFiGtj7tIASChqKZMHTSQTQY6xDbOq+V1/vIq3QrWg==", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-module-imports": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4", "resolve": "^1.8.1", "semver": "^5.5.1" }, @@ -796,124 +889,142 @@ } }, "@babel/plugin-transform-shorthand-properties": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.8.3.tgz", - "integrity": "sha512-I9DI6Odg0JJwxCHzbzW08ggMdCezoWcuQRz3ptdudgwaHxTjxw5HgdFJmZIkIMlRymL6YiZcped4TTCB0JcC8w==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.12.1.tgz", + "integrity": "sha512-GFZS3c/MhX1OusqB1MZ1ct2xRzX5ppQh2JU1h2Pnfk88HtFTM+TWQqJNfwkmxtPQtb/s1tk87oENfXJlx7rSDw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.8.3.tgz", - "integrity": "sha512-CkuTU9mbmAoFOI1tklFWYYbzX5qCIZVXPVy0jpXgGwkplCndQAa58s2jr66fTeQnA64bDox0HL4U56CFYoyC7g==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.12.1.tgz", + "integrity": "sha512-vuLp8CP0BE18zVYjsEBZ5xoCecMK6LBMMxYzJnh01rxQRvhNhH1csMMmBfNo5tGpGO+NhdSNW2mzIvBu3K1fng==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-skip-transparent-expression-wrappers": "^7.12.1" } }, "@babel/plugin-transform-sticky-regex": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.8.3.tgz", - "integrity": "sha512-9Spq0vGCD5Bb4Z/ZXXSK5wbbLFMG085qd2vhL1JYu1WcQ5bXqZBAYRzU1d+p79GcHs2szYv5pVQCX13QgldaWw==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.12.1.tgz", + "integrity": "sha512-CiUgKQ3AGVk7kveIaPEET1jNDhZZEl1RPMWdTBE1799bdz++SwqDHStmxfCtDfBhQgCl38YRiSnrMuUMZIWSUQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/helper-regex": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-regex": "^7.10.4" } }, "@babel/plugin-transform-template-literals": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.8.3.tgz", - "integrity": "sha512-820QBtykIQOLFT8NZOcTRJ1UNuztIELe4p9DCgvj4NK+PwluSJ49we7s9FB1HIGNIYT7wFUJ0ar2QpCDj0escQ==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.12.1.tgz", + "integrity": "sha512-b4Zx3KHi+taXB1dVRBhVJtEPi9h1THCeKmae2qP0YdUHIFhVjtpqqNfxeVAa1xeHVhAy4SbHxEwx5cltAu5apw==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-typeof-symbol": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.8.4.tgz", - "integrity": "sha512-2QKyfjGdvuNfHsb7qnBBlKclbD4CfshH2KvDabiijLMGXPHJXGxtDzwIF7bQP+T0ysw8fYTtxPafgfs/c1Lrqg==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.12.1.tgz", + "integrity": "sha512-EPGgpGy+O5Kg5pJFNDKuxt9RdmTgj5sgrus2XVeMp/ZIbOESadgILUbm50SNpghOh3/6yrbsH+NB5+WJTmsA7Q==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-unicode-escapes": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.12.1.tgz", + "integrity": "sha512-I8gNHJLIc7GdApm7wkVnStWssPNbSRMPtgHdmH3sRM1zopz09UWPS4x5V4n1yz/MIWTVnJ9sp6IkuXdWM4w+2Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-unicode-regex": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.8.3.tgz", - "integrity": "sha512-+ufgJjYdmWfSQ+6NS9VGUR2ns8cjJjYbrbi11mZBTaWm+Fui/ncTLFF28Ei1okavY+xkojGr1eJxNsWYeA5aZw==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.12.1.tgz", + "integrity": "sha512-SqH4ClNngh/zGwHZOOQMTD+e8FGWexILV+ePMyiDJttAWRh5dhDL8rcl5lSgU3Huiq6Zn6pWTMvdPAb21Dwdyg==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-create-regexp-features-plugin": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/preset-env": { - "version": "7.8.7", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.8.7.tgz", - "integrity": "sha512-BYftCVOdAYJk5ASsznKAUl53EMhfBbr8CJ1X+AJLfGPscQkwJFiaV/Wn9DPH/7fzm2v6iRYJKYHSqyynTGw0nw==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.8.6", - "@babel/helper-compilation-targets": "^7.8.7", - "@babel/helper-module-imports": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/plugin-proposal-async-generator-functions": "^7.8.3", - "@babel/plugin-proposal-dynamic-import": "^7.8.3", - "@babel/plugin-proposal-json-strings": "^7.8.3", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-proposal-object-rest-spread": "^7.8.3", - "@babel/plugin-proposal-optional-catch-binding": "^7.8.3", - "@babel/plugin-proposal-optional-chaining": "^7.8.3", - "@babel/plugin-proposal-unicode-property-regex": "^7.8.3", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.12.1.tgz", + "integrity": "sha512-H8kxXmtPaAGT7TyBvSSkoSTUK6RHh61So05SyEbpmr0MCZrsNYn7mGMzzeYoOUCdHzww61k8XBft2TaES+xPLg==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.12.1", + "@babel/helper-compilation-targets": "^7.12.1", + "@babel/helper-module-imports": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-validator-option": "^7.12.1", + "@babel/plugin-proposal-async-generator-functions": "^7.12.1", + "@babel/plugin-proposal-class-properties": "^7.12.1", + "@babel/plugin-proposal-dynamic-import": "^7.12.1", + "@babel/plugin-proposal-export-namespace-from": "^7.12.1", + "@babel/plugin-proposal-json-strings": "^7.12.1", + "@babel/plugin-proposal-logical-assignment-operators": "^7.12.1", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.1", + "@babel/plugin-proposal-numeric-separator": "^7.12.1", + "@babel/plugin-proposal-object-rest-spread": "^7.12.1", + "@babel/plugin-proposal-optional-catch-binding": "^7.12.1", + "@babel/plugin-proposal-optional-chaining": "^7.12.1", + "@babel/plugin-proposal-private-methods": "^7.12.1", + "@babel/plugin-proposal-unicode-property-regex": "^7.12.1", "@babel/plugin-syntax-async-generators": "^7.8.0", + "@babel/plugin-syntax-class-properties": "^7.12.1", "@babel/plugin-syntax-dynamic-import": "^7.8.0", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", "@babel/plugin-syntax-json-strings": "^7.8.0", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", "@babel/plugin-syntax-object-rest-spread": "^7.8.0", "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", "@babel/plugin-syntax-optional-chaining": "^7.8.0", - "@babel/plugin-syntax-top-level-await": "^7.8.3", - "@babel/plugin-transform-arrow-functions": "^7.8.3", - "@babel/plugin-transform-async-to-generator": "^7.8.3", - "@babel/plugin-transform-block-scoped-functions": "^7.8.3", - "@babel/plugin-transform-block-scoping": "^7.8.3", - "@babel/plugin-transform-classes": "^7.8.6", - "@babel/plugin-transform-computed-properties": "^7.8.3", - "@babel/plugin-transform-destructuring": "^7.8.3", - "@babel/plugin-transform-dotall-regex": "^7.8.3", - "@babel/plugin-transform-duplicate-keys": "^7.8.3", - "@babel/plugin-transform-exponentiation-operator": "^7.8.3", - "@babel/plugin-transform-for-of": "^7.8.6", - "@babel/plugin-transform-function-name": "^7.8.3", - "@babel/plugin-transform-literals": "^7.8.3", - "@babel/plugin-transform-member-expression-literals": "^7.8.3", - "@babel/plugin-transform-modules-amd": "^7.8.3", - "@babel/plugin-transform-modules-commonjs": "^7.8.3", - "@babel/plugin-transform-modules-systemjs": "^7.8.3", - "@babel/plugin-transform-modules-umd": "^7.8.3", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.8.3", - "@babel/plugin-transform-new-target": "^7.8.3", - "@babel/plugin-transform-object-super": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.8.7", - "@babel/plugin-transform-property-literals": "^7.8.3", - "@babel/plugin-transform-regenerator": "^7.8.7", - "@babel/plugin-transform-reserved-words": "^7.8.3", - "@babel/plugin-transform-shorthand-properties": "^7.8.3", - "@babel/plugin-transform-spread": "^7.8.3", - "@babel/plugin-transform-sticky-regex": "^7.8.3", - "@babel/plugin-transform-template-literals": "^7.8.3", - "@babel/plugin-transform-typeof-symbol": "^7.8.4", - "@babel/plugin-transform-unicode-regex": "^7.8.3", - "@babel/types": "^7.8.7", - "browserslist": "^4.8.5", + "@babel/plugin-syntax-top-level-await": "^7.12.1", + "@babel/plugin-transform-arrow-functions": "^7.12.1", + "@babel/plugin-transform-async-to-generator": "^7.12.1", + "@babel/plugin-transform-block-scoped-functions": "^7.12.1", + "@babel/plugin-transform-block-scoping": "^7.12.1", + "@babel/plugin-transform-classes": "^7.12.1", + "@babel/plugin-transform-computed-properties": "^7.12.1", + "@babel/plugin-transform-destructuring": "^7.12.1", + "@babel/plugin-transform-dotall-regex": "^7.12.1", + "@babel/plugin-transform-duplicate-keys": "^7.12.1", + "@babel/plugin-transform-exponentiation-operator": "^7.12.1", + "@babel/plugin-transform-for-of": "^7.12.1", + "@babel/plugin-transform-function-name": "^7.12.1", + "@babel/plugin-transform-literals": "^7.12.1", + "@babel/plugin-transform-member-expression-literals": "^7.12.1", + "@babel/plugin-transform-modules-amd": "^7.12.1", + "@babel/plugin-transform-modules-commonjs": "^7.12.1", + "@babel/plugin-transform-modules-systemjs": "^7.12.1", + "@babel/plugin-transform-modules-umd": "^7.12.1", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.12.1", + "@babel/plugin-transform-new-target": "^7.12.1", + "@babel/plugin-transform-object-super": "^7.12.1", + "@babel/plugin-transform-parameters": "^7.12.1", + "@babel/plugin-transform-property-literals": "^7.12.1", + "@babel/plugin-transform-regenerator": "^7.12.1", + "@babel/plugin-transform-reserved-words": "^7.12.1", + "@babel/plugin-transform-shorthand-properties": "^7.12.1", + "@babel/plugin-transform-spread": "^7.12.1", + "@babel/plugin-transform-sticky-regex": "^7.12.1", + "@babel/plugin-transform-template-literals": "^7.12.1", + "@babel/plugin-transform-typeof-symbol": "^7.12.1", + "@babel/plugin-transform-unicode-escapes": "^7.12.1", + "@babel/plugin-transform-unicode-regex": "^7.12.1", + "@babel/preset-modules": "^0.1.3", + "@babel/types": "^7.12.1", "core-js-compat": "^3.6.2", - "invariant": "^2.2.2", - "levenary": "^1.1.1", "semver": "^5.5.0" }, "dependencies": { @@ -925,63 +1036,76 @@ } } }, + "@babel/preset-modules": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz", + "integrity": "sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + } + }, "@babel/runtime": { - "version": "7.8.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.8.7.tgz", - "integrity": "sha512-+AATMUFppJDw6aiR5NVPHqIQBlV/Pj8wY/EZH+lmvRdUo9xBaz/rF3alAwFJQavvKfeOlPE7oaaDHVbcySbCsg==", + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.5.tgz", + "integrity": "sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg==", "requires": { "regenerator-runtime": "^0.13.4" } }, "@babel/template": { - "version": "7.8.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.6.tgz", - "integrity": "sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", + "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", "dev": true, "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/parser": "^7.8.6", - "@babel/types": "^7.8.6" + "@babel/code-frame": "^7.10.4", + "@babel/parser": "^7.10.4", + "@babel/types": "^7.10.4" }, "dependencies": { "@babel/parser": { - "version": "7.8.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.8.tgz", - "integrity": "sha512-mO5GWzBPsPf6865iIbzNE0AvkKF3NE+2S3eRUpE+FE07BOAkXh6G+GW/Pj01hhXjve1WScbaIO4UlY1JKeqCcA==", + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.5.tgz", + "integrity": "sha512-FVM6RZQ0mn2KCf1VUED7KepYeUWoVShczewOCfm3nzoBybaih51h+sYVVGthW9M6lPByEPTQf+xm27PBdlpwmQ==", "dev": true } } }, "@babel/traverse": { - "version": "7.8.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.6.tgz", - "integrity": "sha512-2B8l0db/DPi8iinITKuo7cbPznLCEk0kCxDoB9/N6gGNg/gxOXiR/IcymAFPiBwk5w6TtQ27w4wpElgp9btR9A==", + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.5.tgz", + "integrity": "sha512-xa15FbQnias7z9a62LwYAA5SZZPkHIXpd42C6uW68o8uTuua96FHZy1y61Va5P/i83FAAcMpW8+A/QayntzuqA==", "dev": true, "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.8.6", - "@babel/helper-function-name": "^7.8.3", - "@babel/helper-split-export-declaration": "^7.8.3", - "@babel/parser": "^7.8.6", - "@babel/types": "^7.8.6", + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.12.5", + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/parser": "^7.12.5", + "@babel/types": "^7.12.5", "debug": "^4.1.0", "globals": "^11.1.0", - "lodash": "^4.17.13" + "lodash": "^4.17.19" }, "dependencies": { "@babel/parser": { - "version": "7.8.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.8.tgz", - "integrity": "sha512-mO5GWzBPsPf6865iIbzNE0AvkKF3NE+2S3eRUpE+FE07BOAkXh6G+GW/Pj01hhXjve1WScbaIO4UlY1JKeqCcA==", + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.5.tgz", + "integrity": "sha512-FVM6RZQ0mn2KCf1VUED7KepYeUWoVShczewOCfm3nzoBybaih51h+sYVVGthW9M6lPByEPTQf+xm27PBdlpwmQ==", "dev": true }, "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.0.tgz", + "integrity": "sha512-jjO6JD2rKfiZQnBoRzhRTbXjHLGLfH+UtGkWLc/UXAh/rzZMyjbgn0NcfFpqT8nd1kTtFnDiJcrIFkq4UKeJVg==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } }, "ms": { @@ -993,13 +1117,13 @@ } }, "@babel/types": { - "version": "7.8.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.7.tgz", - "integrity": "sha512-k2TreEHxFA4CjGkL+GYjRyx35W0Mr7DP5+9q6WMkyKXB+904bYmG40syjMFV0oLlhhFCwWl0vA0DyzTDkwAiJw==", + "version": "7.12.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.6.tgz", + "integrity": "sha512-hwyjw6GvjBLiyy3W0YQf0Z5Zf4NpYejUnKFcfcUhZCSffoBBp30w6wP2Wn6pk31jMYZvcOrB/1b7cGXvEoKogA==", "dev": true, "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.13", + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", "to-fast-properties": "^2.0.0" } }, @@ -1010,13 +1134,13 @@ "dev": true }, "@rollup/plugin-replace": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.3.3.tgz", - "integrity": "sha512-XPmVXZ7IlaoWaJLkSCDaa0Y6uVo5XQYHhiMFzOd5qSv5rE+t/UJToPIOE56flKIxBFQI27ONsxb7dqHnwSsjKQ==", + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.3.4.tgz", + "integrity": "sha512-waBhMzyAtjCL1GwZes2jaE9MjuQ/DQF2BatH3fRivUF3z0JBFrU0U6iBNC/4WR+2rLKhaAhPWDNPYp4mI6RqdQ==", "dev": true, "requires": { - "@rollup/pluginutils": "^3.0.8", - "magic-string": "^0.25.5" + "@rollup/pluginutils": "^3.1.0", + "magic-string": "^0.25.7" } }, "@rollup/pluginutils": { @@ -1028,41 +1152,21 @@ "@types/estree": "0.0.39", "estree-walker": "^1.0.1", "picomatch": "^2.2.2" - }, - "dependencies": { - "@types/estree": { - "version": "0.0.39", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", - "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", - "dev": true - }, - "estree-walker": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", - "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", - "dev": true - }, - "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "dev": true - } } }, "@samverschueren/stream-to-observable": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz", - "integrity": "sha512-MI4Xx6LHs4Webyvi6EbspgyAb4D2Q2VtnCQ1blOJcoLS6mVa8lNN2rkIy1CVxfTUpoyIbCTkXES1rLXztFD1lg==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.1.tgz", + "integrity": "sha512-c/qwwcHyafOQuVQJj0IlBjf5yYgBI7YPJ77k4fOJYesb41jio65eaJODRUmfYKhTOFBrIZ66kgvGPlNbjuoRdQ==", "dev": true, "requires": { "any-observable": "^0.3.0" } }, "@sinonjs/commons": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.7.1.tgz", - "integrity": "sha512-Debi3Baff1Qu1Unc3mjJ96MgpbwTn43S1+9yJ0llWygPwDNu2aaWBD6yc9y/Z8XDRNhx7U+u2UDg2OGQXkclUQ==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.1.tgz", + "integrity": "sha512-892K+kWUUi3cl+LlqEWIDrhvLgdL79tECi8JZUyq6IviKy/DNhuzCRlbHUjxK89f4ypPMMaFnFuR9Ie6DoIMsw==", "dev": true, "requires": { "type-detect": "4.0.8" @@ -1096,9 +1200,9 @@ "dev": true }, "@textlint/ast-node-types": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@textlint/ast-node-types/-/ast-node-types-4.2.5.tgz", - "integrity": "sha512-+rEx4jLOeZpUcdvll7jEg/7hNbwYvHWFy4IGW/tk2JdbyB3SJVyIP6arAwzTH/sp/pO9jftfyZnRj4//sLbLvQ==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/@textlint/ast-node-types/-/ast-node-types-4.3.4.tgz", + "integrity": "sha512-Grq+vJuNH7HCa278eFeiqJvowrD+onMCoG2ctLyoN+fXYIQGIr1/8fo8AcIg+VM16Kga+N6Y1UWNOWPd8j1nFg==", "dev": true }, "@textlint/markdown-to-ast": { @@ -1117,15 +1221,21 @@ } }, "@types/estree": { - "version": "0.0.42", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.42.tgz", - "integrity": "sha512-K1DPVvnBCPxzD+G51/cxVIoc2X8uUVl1zpJeE6iKcgHMj4+tbat5Xu4TjV7v2QSDbIeAfLi2hIk+u2+s0MlpUQ==", + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true + }, + "@types/minimist": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.1.tgz", + "integrity": "sha512-fZQQafSREFyuZcdWFAExYjBiCL7AUCdgsk80iO0q4yihYYdcIiH28CcuPTGFgLOCC8RlW49GSQxdHwZP+I7CNg==", "dev": true }, "@types/node": { - "version": "13.9.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-13.9.0.tgz", - "integrity": "sha512-0ARSQootUG1RljH2HncpsY2TJBfGQIKOOi7kxzUY6z54ePu/ZD+wJA8zI2Q6v8rol2qpG/rvqsReco8zNMPvhQ==", + "version": "14.14.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.7.tgz", + "integrity": "sha512-Zw1vhUSQZYw+7u5dAwNbIA9TuTotpzY/OF7sJM9FqPOF3SPjKnxrjoTktXDZgUjybf4cWVBP7O8wvKdSaGHweg==", "dev": true }, "@types/normalize-package-data": { @@ -1162,63 +1272,18 @@ } }, "@videojs/http-streaming": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@videojs/http-streaming/-/http-streaming-1.13.2.tgz", - "integrity": "sha512-U4Xhh+HxGpRBx9Gm0LlEadq85k9BwckzFgZmyhacauhK/27Mz0goKKFAt+BpxBNp2oHVdAdk8NHfneinsqni3Q==", - "requires": { - "aes-decrypter": "3.0.0", - "global": "^4.3.0", - "m3u8-parser": "4.4.0", - "mpd-parser": "0.10.0", - "mux.js": "5.5.1", - "url-toolkit": "^2.1.3", - "video.js": "^6.8.0 || ^7.0.0" - }, - "dependencies": { - "@videojs/vhs-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@videojs/vhs-utils/-/vhs-utils-1.3.0.tgz", - "integrity": "sha512-oiqXDtHQqDPun7JseWkirUHGrgdYdeF12goUut5z7vwAj4DmUufEPFJ4xK5hYGXGFDyDhk2rSFOR122Ze6qXyQ==", - "requires": { - "@babel/runtime": "^7.5.5", - "global": "^4.3.2", - "url-toolkit": "^2.1.6" - } - }, - "aes-decrypter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/aes-decrypter/-/aes-decrypter-3.0.0.tgz", - "integrity": "sha1-eEihwUW5/b9Xrj4rWxvHzwZEqPs=", - "requires": { - "commander": "^2.9.0", - "global": "^4.3.2", - "pkcs7": "^1.0.2" - } - }, - "m3u8-parser": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/m3u8-parser/-/m3u8-parser-4.4.0.tgz", - "integrity": "sha512-iH2AygTFILtato+XAgnoPYzLHM4R3DjATj7Ozbk7EHdB2XoLF2oyOUguM7Kc4UVHbQHHL/QPaw98r7PbWzG0gg==", - "requires": { - "global": "^4.3.2" - } - }, - "mpd-parser": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/mpd-parser/-/mpd-parser-0.10.0.tgz", - "integrity": "sha512-eIqkH/2osPr7tIIjhRmDWqm2wdJ7Q8oPfWvdjealzsLV2D2oNe0a0ae2gyYYs1sw5e5hdssDA2V6Sz8MW+Uvvw==", - "requires": { - "@babel/runtime": "^7.5.5", - "@videojs/vhs-utils": "^1.1.0", - "global": "^4.3.2", - "xmldom": "^0.1.27" - } - }, - "mux.js": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/mux.js/-/mux.js-5.5.1.tgz", - "integrity": "sha512-5VmmjADBqS4++8pTI6poSRJ+chHdaoI4XErcQPM5w4QfwaDl+FQlSI0iOgWbYDn6CBCbDRKaSCcEiN2K5aHNGQ==" - } + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/@videojs/http-streaming/-/http-streaming-2.2.4.tgz", + "integrity": "sha512-gzT46RpAEegOhMId/zZ6uXCVGDMPOv8qmoTykBuvd6/4lVM3lZ1ZJCq0kytAkisDuDKipy93gP46oZEtonlc/Q==", + "requires": { + "@babel/runtime": "^7.5.5", + "@videojs/vhs-utils": "^2.2.1", + "aes-decrypter": "3.1.0", + "global": "^4.3.2", + "m3u8-parser": "4.5.0", + "mpd-parser": "0.14.0", + "mux.js": "5.6.7", + "video.js": "^6 || ^7" } }, "@videojs/vhs-utils": { @@ -1274,15 +1339,15 @@ } }, "acorn": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz", - "integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==", + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", "dev": true }, "acorn-jsx": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.2.0.tgz", - "integrity": "sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", "dev": true }, "add-stream": { @@ -1300,16 +1365,6 @@ "@videojs/vhs-utils": "^2.2.1", "global": "^4.3.2", "pkcs7": "^1.0.4" - }, - "dependencies": { - "pkcs7": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/pkcs7/-/pkcs7-1.0.4.tgz", - "integrity": "sha512-afRERtHn54AlwaF2/+LFszyAANTCggGilmcmILUzEjvs3XgFZT+xE6+QWQcAGmu4xajy+Xtj7acLOPdx5/eXWQ==", - "requires": { - "@babel/runtime": "^7.5.5" - } - } } }, "after": { @@ -1328,9 +1383,9 @@ } }, "ajv": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.0.tgz", - "integrity": "sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==", + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", @@ -1525,13 +1580,10 @@ "dev": true }, "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "dev": true, - "requires": { - "lodash": "^4.17.14" - } + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true }, "async-array-reduce": { "version": "0.2.1", @@ -1635,9 +1687,9 @@ } }, "babel-plugin-dynamic-import-node": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz", - "integrity": "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", "dev": true, "requires": { "object.assign": "^4.1.0" @@ -1799,15 +1851,15 @@ } }, "base64-arraybuffer": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", - "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz", + "integrity": "sha1-mBjHngWbE1X5fgQooBfIOOkLqBI=", "dev": true }, "base64id": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", - "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", "dev": true }, "better-assert": { @@ -1836,9 +1888,9 @@ } }, "binary-extensions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", - "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", + "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", "dev": true }, "blob": { @@ -1917,14 +1969,16 @@ } }, "browserslist": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.9.1.tgz", - "integrity": "sha512-Q0DnKq20End3raFulq6Vfp1ecB9fh8yUNV55s8sekaDDeqBaCtWlRHCUdaWyUeSSBJM7IbM6HcsyaeYqgeDhnw==", + "version": "4.14.7", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.14.7.tgz", + "integrity": "sha512-BSVRLCeG3Xt/j/1cCGj1019Wbty0H+Yvu2AOuZSuoaUWn3RatbL33Cxk+Q4jRMRAbOm0p7SLravLjpnT6s0vzQ==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001030", - "electron-to-chromium": "^1.3.363", - "node-releases": "^1.1.50" + "caniuse-lite": "^1.0.30001157", + "colorette": "^1.2.1", + "electron-to-chromium": "^1.3.591", + "escalade": "^3.1.1", + "node-releases": "^1.1.66" } }, "browserstack": { @@ -1946,28 +2000,6 @@ "unzipper": "^0.9.3" } }, - "buffer-alloc": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", - "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", - "dev": true, - "requires": { - "buffer-alloc-unsafe": "^1.1.0", - "buffer-fill": "^1.0.0" - } - }, - "buffer-alloc-unsafe": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", - "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", - "dev": true - }, - "buffer-fill": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", - "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", - "dev": true - }, "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", @@ -1975,9 +2007,9 @@ "dev": true }, "buffer-indexof-polyfill": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.1.tgz", - "integrity": "sha1-qfuAbOgUXVQoUQznLyeLs2OmOL8=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", + "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", "dev": true }, "buffers": { @@ -2015,6 +2047,16 @@ "unset-value": "^1.0.0" } }, + "call-bind": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.0.tgz", + "integrity": "sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.0" + } + }, "caller-callsite": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", @@ -2046,26 +2088,26 @@ "dev": true }, "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, "camelcase-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz", - "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", "dev": true, "requires": { - "camelcase": "^4.1.0", - "map-obj": "^2.0.0", - "quick-lru": "^1.0.0" + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" } }, "caniuse-lite": { - "version": "1.0.30001035", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001035.tgz", - "integrity": "sha512-C1ZxgkuA4/bUEdMbU5WrGY4+UhMFFiXrgNAfxiMIqWgFTWfv/xsZCS2xEHT2LMq7xAZfuAnu6mcqyDl0ZR6wLQ==", + "version": "1.0.30001157", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001157.tgz", + "integrity": "sha512-gOerH9Wz2IRZ2ZPdMfBvyOi3cjaz4O4dgNwPGzx8EhqAs4+2IL/O+fJsbt+znSigujoZG8bVcIAUM/I/E5K3MA==", "dev": true }, "caporal": { @@ -2147,9 +2189,9 @@ "dev": true }, "chokidar": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.1.tgz", - "integrity": "sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", + "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", "dev": true, "requires": { "anymatch": "~3.1.1", @@ -2159,7 +2201,7 @@ "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", - "readdirp": "~3.3.0" + "readdirp": "~3.5.0" }, "dependencies": { "braces": { @@ -2290,13 +2332,99 @@ } }, "cli-width": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", + "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", "dev": true }, - "code-point-at": { - "version": "1.1.0", + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + } + } + }, + "code-point-at": { + "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true @@ -2333,9 +2461,9 @@ "dev": true }, "colorette": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.1.0.tgz", - "integrity": "sha512-6S062WDQUXi6hOfkO/sBPVwE5ASXY4G2+b4atvhJfSsuUUhIaUKlkjLe9692Ipyt5/a+IPF5aVTu3V5gvXq5cg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz", + "integrity": "sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==", "dev": true }, "colors": { @@ -2347,7 +2475,8 @@ "commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true }, "comment-parser": { "version": "0.5.5", @@ -2356,13 +2485,13 @@ "dev": true }, "compare-func": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-1.3.2.tgz", - "integrity": "sha1-md0LpFfh+bxyKxLAjsM+6rMfpkg=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", + "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", "dev": true, "requires": { "array-ify": "^1.0.0", - "dot-prop": "^3.0.0" + "dot-prop": "^5.1.0" } }, "component-bind": { @@ -2452,184 +2581,184 @@ "dev": true }, "conventional-changelog": { - "version": "3.1.19", - "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-3.1.19.tgz", - "integrity": "sha512-3GjaHiQK5c2LAedY3Dfwa54yc5x6blzbp2x0f5fLkWxqHXufi5wSSozA4V93bojMDHKRNH/QUfe73aUwkcCS0w==", + "version": "3.1.24", + "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-3.1.24.tgz", + "integrity": "sha512-ed6k8PO00UVvhExYohroVPXcOJ/K1N0/drJHx/faTH37OIZthlecuLIRX/T6uOp682CAoVoFpu+sSEaeuH6Asg==", "dev": true, "requires": { - "conventional-changelog-angular": "^5.0.6", - "conventional-changelog-atom": "^2.0.3", - "conventional-changelog-codemirror": "^2.0.3", - "conventional-changelog-conventionalcommits": "^4.2.3", - "conventional-changelog-core": "^4.1.5", - "conventional-changelog-ember": "^2.0.4", - "conventional-changelog-eslint": "^3.0.4", - "conventional-changelog-express": "^2.0.1", - "conventional-changelog-jquery": "^3.0.6", - "conventional-changelog-jshint": "^2.0.3", - "conventional-changelog-preset-loader": "^2.3.0" + "conventional-changelog-angular": "^5.0.12", + "conventional-changelog-atom": "^2.0.8", + "conventional-changelog-codemirror": "^2.0.8", + "conventional-changelog-conventionalcommits": "^4.5.0", + "conventional-changelog-core": "^4.2.1", + "conventional-changelog-ember": "^2.0.9", + "conventional-changelog-eslint": "^3.0.9", + "conventional-changelog-express": "^2.0.6", + "conventional-changelog-jquery": "^3.0.11", + "conventional-changelog-jshint": "^2.0.9", + "conventional-changelog-preset-loader": "^2.3.4" } }, "conventional-changelog-angular": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.6.tgz", - "integrity": "sha512-QDEmLa+7qdhVIv8sFZfVxU1VSyVvnXPsxq8Vam49mKUcO1Z8VTLEJk9uI21uiJUsnmm0I4Hrsdc9TgkOQo9WSA==", + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.12.tgz", + "integrity": "sha512-5GLsbnkR/7A89RyHLvvoExbiGbd9xKdKqDTrArnPbOqBqG/2wIosu0fHwpeIRI8Tl94MhVNBXcLJZl92ZQ5USw==", "dev": true, "requires": { - "compare-func": "^1.3.1", + "compare-func": "^2.0.0", "q": "^1.5.1" } }, "conventional-changelog-atom": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/conventional-changelog-atom/-/conventional-changelog-atom-2.0.3.tgz", - "integrity": "sha512-szZe2ut97qNO6vCCMkm1I/tWu6ol4Rr8a9Lx0y/VlpDnpY0PNp+oGpFgU55lplhx+I3Lro9Iv4/gRj0knfgjzg==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/conventional-changelog-atom/-/conventional-changelog-atom-2.0.8.tgz", + "integrity": "sha512-xo6v46icsFTK3bb7dY/8m2qvc8sZemRgdqLb/bjpBsH2UyOS8rKNTgcb5025Hri6IpANPApbXMg15QLb1LJpBw==", "dev": true, "requires": { "q": "^1.5.1" } }, "conventional-changelog-cli": { - "version": "2.0.32", - "resolved": "https://registry.npmjs.org/conventional-changelog-cli/-/conventional-changelog-cli-2.0.32.tgz", - "integrity": "sha512-7i8kDbMsQKDBVfdgpL2oEyTiYKEmq8SGgPYtmwhhGC1aupBmv6pcoJmxmn5jdCpMcc8LML9RQHSL7u1ycw0tmg==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/conventional-changelog-cli/-/conventional-changelog-cli-2.1.1.tgz", + "integrity": "sha512-xMGQdKJ+4XFDDgfX5aK7UNFduvJMbvF5BB+g0OdVhA3rYdYyhctrIE2Al+WYdZeKTdg9YzMWF2iFPT8MupIwng==", "dev": true, "requires": { "add-stream": "^1.0.0", - "conventional-changelog": "^3.1.19", + "conventional-changelog": "^3.1.24", "lodash": "^4.17.15", - "meow": "^5.0.0", + "meow": "^8.0.0", "tempfile": "^3.0.0" } }, "conventional-changelog-codemirror": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/conventional-changelog-codemirror/-/conventional-changelog-codemirror-2.0.3.tgz", - "integrity": "sha512-t2afackdgFV2yBdHhWPqrKbpaQeVnz2hSJKdWqjasPo5EpIB6TBL0er3cOP1mnGQmuzk9JSvimNSuqjWGDtU5Q==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/conventional-changelog-codemirror/-/conventional-changelog-codemirror-2.0.8.tgz", + "integrity": "sha512-z5DAsn3uj1Vfp7po3gpt2Boc+Bdwmw2++ZHa5Ak9k0UKsYAO5mH1UBTN0qSCuJZREIhX6WU4E1p3IW2oRCNzQw==", "dev": true, "requires": { "q": "^1.5.1" } }, "conventional-changelog-conventionalcommits": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.2.3.tgz", - "integrity": "sha512-atGa+R4vvEhb8N/8v3IoW59gCBJeeFiX6uIbPu876ENAmkMwsenyn0R21kdDHJFLQdy6zW4J6b4xN8KI3b9oww==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.5.0.tgz", + "integrity": "sha512-buge9xDvjjOxJlyxUnar/+6i/aVEVGA7EEh4OafBCXPlLUQPGbRUBhBUveWRxzvR8TEjhKEP4BdepnpG2FSZXw==", "dev": true, "requires": { - "compare-func": "^1.3.1", + "compare-func": "^2.0.0", "lodash": "^4.17.15", "q": "^1.5.1" } }, "conventional-changelog-core": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-4.1.5.tgz", - "integrity": "sha512-o647uE5iZDTqgnsoJuprUHFFK7XGD/h5iWXEEAyiKgfhVyAzKOEBEDnlzRaG7JV5BBd5x2NSd+llfn3oF3/iuQ==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-4.2.1.tgz", + "integrity": "sha512-8cH8/DEoD3e5Q6aeogdR5oaaKs0+mG6+f+Om0ZYt3PNv7Zo0sQhu4bMDRsqAF+UTekTAtP1W/C41jH/fkm8Jtw==", "dev": true, "requires": { "add-stream": "^1.0.0", - "conventional-changelog-writer": "^4.0.11", - "conventional-commits-parser": "^3.0.8", + "conventional-changelog-writer": "^4.0.18", + "conventional-commits-parser": "^3.2.0", "dateformat": "^3.0.0", "get-pkg-repo": "^1.0.0", "git-raw-commits": "2.0.0", "git-remote-origin-url": "^2.0.0", - "git-semver-tags": "^3.0.1", + "git-semver-tags": "^4.1.1", "lodash": "^4.17.15", - "normalize-package-data": "^2.3.5", + "normalize-package-data": "^3.0.0", "q": "^1.5.1", "read-pkg": "^3.0.0", "read-pkg-up": "^3.0.0", "shelljs": "^0.8.3", - "through2": "^3.0.0" + "through2": "^4.0.0" } }, "conventional-changelog-ember": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/conventional-changelog-ember/-/conventional-changelog-ember-2.0.4.tgz", - "integrity": "sha512-q1u73sO9uCnxN4TSw8xu6MRU8Y1h9kpwtcdJuNRwu/LSKI1IE/iuNSH5eQ6aLlQ3HTyrIpTfUuVybW4W0F17rA==", + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/conventional-changelog-ember/-/conventional-changelog-ember-2.0.9.tgz", + "integrity": "sha512-ulzIReoZEvZCBDhcNYfDIsLTHzYHc7awh+eI44ZtV5cx6LVxLlVtEmcO+2/kGIHGtw+qVabJYjdI5cJOQgXh1A==", "dev": true, "requires": { "q": "^1.5.1" } }, "conventional-changelog-eslint": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/conventional-changelog-eslint/-/conventional-changelog-eslint-3.0.4.tgz", - "integrity": "sha512-CPwTUENzhLGl3auunrJxiIEWncAGaby7gOFCdj2gslIuOFJ0KPJVOUhRz4Da/I53sdo/7UncUJkiLg94jEsjxg==", + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/conventional-changelog-eslint/-/conventional-changelog-eslint-3.0.9.tgz", + "integrity": "sha512-6NpUCMgU8qmWmyAMSZO5NrRd7rTgErjrm4VASam2u5jrZS0n38V7Y9CzTtLT2qwz5xEChDR4BduoWIr8TfwvXA==", "dev": true, "requires": { "q": "^1.5.1" } }, "conventional-changelog-express": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/conventional-changelog-express/-/conventional-changelog-express-2.0.1.tgz", - "integrity": "sha512-G6uCuCaQhLxdb4eEfAIHpcfcJ2+ao3hJkbLrw/jSK/eROeNfnxCJasaWdDAfFkxsbpzvQT4W01iSynU3OoPLIw==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/conventional-changelog-express/-/conventional-changelog-express-2.0.6.tgz", + "integrity": "sha512-SDez2f3iVJw6V563O3pRtNwXtQaSmEfTCaTBPCqn0oG0mfkq0rX4hHBq5P7De2MncoRixrALj3u3oQsNK+Q0pQ==", "dev": true, "requires": { "q": "^1.5.1" } }, "conventional-changelog-jquery": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/conventional-changelog-jquery/-/conventional-changelog-jquery-3.0.6.tgz", - "integrity": "sha512-gHAABCXUNA/HjnZEm+vxAfFPJkgtrZvCDIlCKfdPVXtCIo/Q0lN5VKpx8aR5p8KdVRQFF3OuTlvv5kv6iPuRqA==", + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/conventional-changelog-jquery/-/conventional-changelog-jquery-3.0.11.tgz", + "integrity": "sha512-x8AWz5/Td55F7+o/9LQ6cQIPwrCjfJQ5Zmfqi8thwUEKHstEn4kTIofXub7plf1xvFA2TqhZlq7fy5OmV6BOMw==", "dev": true, "requires": { "q": "^1.5.1" } }, "conventional-changelog-jshint": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/conventional-changelog-jshint/-/conventional-changelog-jshint-2.0.3.tgz", - "integrity": "sha512-Pc2PnMPcez634ckzr4EOWviwRSpZcURaK7bjyD9oK6N5fsC/a+3G7LW5m/JpcHPhA9ZxsfIbm7uqZ3ZDGsQ/sw==", + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/conventional-changelog-jshint/-/conventional-changelog-jshint-2.0.9.tgz", + "integrity": "sha512-wMLdaIzq6TNnMHMy31hql02OEQ8nCQfExw1SE0hYL5KvU+JCTuPaDO+7JiogGT2gJAxiUGATdtYYfh+nT+6riA==", "dev": true, "requires": { - "compare-func": "^1.3.1", + "compare-func": "^2.0.0", "q": "^1.5.1" } }, "conventional-changelog-preset-loader": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.0.tgz", - "integrity": "sha512-/rHb32J2EJnEXeK4NpDgMaAVTFZS3o1ExmjKMtYVgIC4MQn0vkNSbYpdGRotkfGGRWiqk3Ri3FBkiZGbAfIfOQ==", + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.4.tgz", + "integrity": "sha512-GEKRWkrSAZeTq5+YjUZOYxdHq+ci4dNwHvpaBC3+ENalzFWuCWa9EZXSuZBpkr72sMdKB+1fyDV4takK1Lf58g==", "dev": true }, "conventional-changelog-videojs": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-videojs/-/conventional-changelog-videojs-3.0.0.tgz", - "integrity": "sha1-GMJt52U1lZmzXyQ4tYl6gg2wtxg=", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/conventional-changelog-videojs/-/conventional-changelog-videojs-3.0.1.tgz", + "integrity": "sha512-SOubwIReSKixpVFc0wFolZO4ELx0rlIPwF1voyWkgGOquzYI9HcDVk8PDGjgQH/6kWIQJu18b9cdGVLWyhCRgg==", "dev": true, "requires": { - "compare-func": "^1.3.1", + "compare-func": "^2.0.0", "github-url-from-git": "^1.4.0", "q": "^1.4.1" } }, "conventional-changelog-writer": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-4.0.11.tgz", - "integrity": "sha512-g81GQOR392I+57Cw3IyP1f+f42ME6aEkbR+L7v1FBBWolB0xkjKTeCWVguzRrp6UiT1O6gBpJbEy2eq7AnV1rw==", + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-4.0.18.tgz", + "integrity": "sha512-mAQDCKyB9HsE8Ko5cCM1Jn1AWxXPYV0v8dFPabZRkvsiWUul2YyAqbIaoMKF88Zf2ffnOPSvKhboLf3fnjo5/A==", "dev": true, "requires": { - "compare-func": "^1.3.1", - "conventional-commits-filter": "^2.0.2", + "compare-func": "^2.0.0", + "conventional-commits-filter": "^2.0.7", "dateformat": "^3.0.0", - "handlebars": "^4.4.0", + "handlebars": "^4.7.6", "json-stringify-safe": "^5.0.1", "lodash": "^4.17.15", - "meow": "^5.0.0", + "meow": "^8.0.0", "semver": "^6.0.0", "split": "^1.0.0", - "through2": "^3.0.0" + "through2": "^4.0.0" } }, "conventional-commits-filter": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-2.0.2.tgz", - "integrity": "sha512-WpGKsMeXfs21m1zIw4s9H5sys2+9JccTzpN6toXtxhpw2VNF2JUXwIakthKBy+LN4DvJm+TzWhxOMWOs1OFCFQ==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-2.0.7.tgz", + "integrity": "sha512-ASS9SamOP4TbCClsRHxIHXRfcGCnIoQqkvAzCSbZzTFLfcTqJVugB0agRgsEELsqaeWgsXv513eS116wnlSSPA==", "dev": true, "requires": { "lodash.ismatch": "^4.4.0", @@ -2637,17 +2766,17 @@ } }, "conventional-commits-parser": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.0.8.tgz", - "integrity": "sha512-YcBSGkZbYp7d+Cr3NWUeXbPDFUN6g3SaSIzOybi8bjHL5IJ5225OSCxJJ4LgziyEJ7AaJtE9L2/EU6H7Nt/DDQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.2.0.tgz", + "integrity": "sha512-XmJiXPxsF0JhAKyfA2Nn+rZwYKJ60nanlbSWwwkGwLQFbugsc0gv1rzc7VbbUWAzJfR1qR87/pNgv9NgmxtBMQ==", "dev": true, "requires": { "JSONStream": "^1.0.4", "is-text-path": "^1.0.1", "lodash": "^4.17.15", - "meow": "^5.0.0", + "meow": "^8.0.0", "split2": "^2.0.0", - "through2": "^3.0.0", + "through2": "^4.0.0", "trim-off-newlines": "^1.0.0" } }, @@ -2687,12 +2816,12 @@ "dev": true }, "core-js-compat": { - "version": "3.6.4", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.4.tgz", - "integrity": "sha512-zAa3IZPvsJ0slViBQ2z+vgyyTuhd3MFn1rBQjZSKVEgB0UMYhUkCj9jJUVPgGTGqWvsBVmfnruXgTcNyTlEiSA==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.7.0.tgz", + "integrity": "sha512-V8yBI3+ZLDVomoWICO6kq/CD28Y4r1M7CWeO4AGpMdMfseu8bkSubBmUPySMGKRTS+su4XQ07zUkAsiu9FCWTg==", "dev": true, "requires": { - "browserslist": "^4.8.3", + "browserslist": "^4.14.6", "semver": "7.0.0" }, "dependencies": { @@ -2720,6 +2849,18 @@ "is-directory": "^0.3.1", "js-yaml": "^3.13.1", "parse-json": "^4.0.0" + }, + "dependencies": { + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + } } }, "cp-data": { @@ -2811,9 +2952,9 @@ "dev": true }, "date-format": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz", - "integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-3.0.0.tgz", + "integrity": "sha512-eyTcpKOcamdhWJXj56DpQMo1ylSQpcGtGKXcU0Tb97+K56/CF5amAqqqNj0+KvA0iw2ynxtHWFsPDSClCxe48w==", "dev": true }, "dateformat": { @@ -2935,6 +3076,14 @@ "p-map": "^1.1.1", "pify": "^3.0.0", "rimraf": "^2.2.8" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } } }, "delegates": { @@ -2988,14 +3137,6 @@ "minimist": "~1.2.0", "underscore": "~1.8.3", "update-section": "^0.3.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.4.tgz", - "integrity": "sha512-wTiNDqe4D2rbTJGZk1qcdZgFtY0/r+iuE6GDT7V0/+Gu5MLpIDm4+CssDECR79OJs/OxLPXMzdxy153b5Qy3hg==", - "dev": true - } } }, "doctrine": { @@ -3030,23 +3171,23 @@ }, "dependencies": { "domelementtype": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz", - "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.2.tgz", + "integrity": "sha512-wFwTwCVebUrMgGeAwRL/NhZtHAUyT9n9yg4IMDwf10+6iCMxSkVq9MGCVEH+QZWo1nNidy8kNvwmv4zWHDTqvA==", "dev": true }, "entities": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.0.tgz", - "integrity": "sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", "dev": true } } }, "dom-walk": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz", - "integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg=" + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", + "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==" }, "domelementtype": { "version": "1.3.1", @@ -3074,12 +3215,12 @@ } }, "dot-prop": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-3.0.0.tgz", - "integrity": "sha1-G3CK8JSknJoOfbyteQq6U52sEXc=", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", "dev": true, "requires": { - "is-obj": "^1.0.0" + "is-obj": "^2.0.0" } }, "duplexer2": { @@ -3130,9 +3271,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.376", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.376.tgz", - "integrity": "sha512-cv/PYVz5szeMz192ngilmezyPNFkUjuynuL2vNdiqIrio440nfTDdc0JJU0TS2KHLSVCs9gBbt4CFqM+HcBnjw==", + "version": "1.3.591", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.591.tgz", + "integrity": "sha512-ol/0WzjL4NS4Kqy9VD6xXQON91xIihDT36sYCew/G/bnd1v0/4D+kahp26JauQhgFUjrdva3kRSo7URcUmQ+qw==", "dev": true }, "elegant-spinner": { @@ -3163,55 +3304,55 @@ } }, "engine.io": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", - "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.4.2.tgz", + "integrity": "sha512-b4Q85dFkGw+TqgytGPrGgACRUhsdKc9S9ErRAXpPGy/CXKs4tYoHDkvIRdsseAF7NjfVwjRFIn6KTnbw7LwJZg==", "dev": true, "requires": { "accepts": "~1.3.4", - "base64id": "1.0.0", + "base64id": "2.0.0", "cookie": "0.3.1", - "debug": "~3.1.0", - "engine.io-parser": "~2.1.0", - "ws": "~3.3.1" + "debug": "~4.1.0", + "engine.io-parser": "~2.2.0", + "ws": "^7.1.2" }, "dependencies": { "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true } } }, "engine.io-client": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", - "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.4.4.tgz", + "integrity": "sha512-iU4CRr38Fecj8HoZEnFtm2EiKGbYZcPn3cHxqNGl/tmdWRf60KhK+9vE0JeSjgnlS/0oynEfLgKbT9ALpim0sQ==", "dev": true, "requires": { - "component-emitter": "1.2.1", + "component-emitter": "~1.3.0", "component-inherit": "0.0.3", "debug": "~3.1.0", - "engine.io-parser": "~2.1.1", + "engine.io-parser": "~2.2.0", "has-cors": "1.1.0", "indexof": "0.0.1", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "ws": "~3.3.1", + "parseqs": "0.0.6", + "parseuri": "0.0.6", + "ws": "~6.1.0", "xmlhttprequest-ssl": "~1.5.4", "yeast": "0.1.2" }, "dependencies": { - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", - "dev": true - }, "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", @@ -3220,18 +3361,39 @@ "requires": { "ms": "2.0.0" } + }, + "parseqs": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz", + "integrity": "sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w==", + "dev": true + }, + "parseuri": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz", + "integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow==", + "dev": true + }, + "ws": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz", + "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } } } }, "engine.io-parser": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", - "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.2.1.tgz", + "integrity": "sha512-x+dN/fBH8Ro8TFwJ+rkB2AmuVw9Yu2mockR/p3W8f8YtExwFgDvBDi0GWyb4ZLkpahtDGZgtr3zLovanJghPqg==", "dev": true, "requires": { "after": "0.8.2", "arraybuffer.slice": "~0.0.7", - "base64-arraybuffer": "0.1.5", + "base64-arraybuffer": "0.1.4", "blob": "0.0.5", "has-binary2": "~1.0.2" } @@ -3258,39 +3420,39 @@ } }, "es-abstract": { - "version": "1.17.4", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", - "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", "dev": true, "requires": { "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", "has": "^1.0.3", "has-symbols": "^1.0.1", - "is-callable": "^1.1.5", - "is-regex": "^1.0.5", - "object-inspect": "^1.7.0", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimleft": "^2.1.1", - "string.prototype.trimright": "^2.1.1" + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" } }, "es-check": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/es-check/-/es-check-5.1.0.tgz", - "integrity": "sha512-QlRhlUmEpdnleBFYWRFROm8u9cNPOWdE1iXQPWiQXnwmlJZ0hSxWpLOXwpFLyRrwnTmt5xqYM/5OR8Ao0MYa8w==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/es-check/-/es-check-5.1.2.tgz", + "integrity": "sha512-uecftCFHR0ggaI3cKwqOu5b5j21z78NgoLlQitE0fDh+xATDZKrFdMoMM9L2ihiGq/d2L2sFPsgzWEsb4Vnr6Q==", "dev": true, "requires": { - "acorn": "6.1.1", + "acorn": "^6.4.1", "caporal": "1.3.0", "glob": "^7.1.2" }, "dependencies": { "acorn": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz", - "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==", + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", "dev": true } } @@ -3307,15 +3469,9 @@ } }, "es5-shim": { - "version": "4.5.13", - "resolved": "https://registry.npmjs.org/es5-shim/-/es5-shim-4.5.13.tgz", - "integrity": "sha512-xi6hh6gsvDE0MaW4Vp1lgNEBpVcCXRWfPXj5egDvtgLz4L9MEvNwYEMdJH+JJinWkwa8c3c3o5HduV7dB/e1Hw==", - "dev": true - }, - "es6-object-assign": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz", - "integrity": "sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw=", + "version": "4.5.14", + "resolved": "https://registry.npmjs.org/es5-shim/-/es5-shim-4.5.14.tgz", + "integrity": "sha512-7SwlpL+2JpymWTt8sNLuC2zdhhc+wrfe5cMPI2j0o6WsPdfAiPwmFy2f0AocPB4RQVBOZ9kNTgi5YF7TdhkvEg==", "dev": true }, "es6-promise": { @@ -3334,9 +3490,15 @@ } }, "es6-shim": { - "version": "0.35.5", - "resolved": "https://registry.npmjs.org/es6-shim/-/es6-shim-0.35.5.tgz", - "integrity": "sha512-E9kK/bjtCQRpN1K28Xh4BlmP8egvZBGJJ+9GtnzOwt7mdqtrjHFuVGr7QJfdjBIKqrlU5duPf3pCBoDrkjVYFg==", + "version": "0.35.6", + "resolved": "https://registry.npmjs.org/es6-shim/-/es6-shim-0.35.6.tgz", + "integrity": "sha512-EmTr31wppcaIAgblChZiuN/l9Y7DPyw8Xtbg7fIVngn6zMW+IEBJDJngeKC3x6wr0V/vcA2wqeFnaw1bFJbDdA==", + "dev": true + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true }, "escape-html": { @@ -3433,12 +3595,12 @@ "dev": true }, "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.0.tgz", + "integrity": "sha512-jjO6JD2rKfiZQnBoRzhRTbXjHLGLfH+UtGkWLc/UXAh/rzZMyjbgn0NcfFpqT8nd1kTtFnDiJcrIFkq4UKeJVg==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } }, "external-editor": { @@ -3462,9 +3624,9 @@ } }, "import-fresh": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", - "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.2.tgz", + "integrity": "sha512-cTPNrlvJT6twpYy+YmKUKrTSjWFs3bjYjAhCwm+z4EOCubZxAuO+hHpRN64TqjEaYSHs7tJAE0w1CKMGmsG/lw==", "dev": true, "requires": { "parent-module": "^1.0.0", @@ -3557,6 +3719,15 @@ "requires": { "ansi-regex": "^3.0.0" } + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } } } }, @@ -3625,9 +3796,9 @@ } }, "eslint-visitor-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", - "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", "dev": true }, "espree": { @@ -3642,9 +3813,9 @@ }, "dependencies": { "acorn": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", - "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==", + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", "dev": true } } @@ -3656,35 +3827,35 @@ "dev": true }, "esquery": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.1.0.tgz", - "integrity": "sha512-MxYW9xKmROWF672KqjO75sszsA8Mxhw06YFeS5VHlB98KDHbOSurm3ArsjO60Eaf3QmGMCP1yn+0JQkNLo/97Q==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", + "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", "dev": true, "requires": { - "estraverse": "^4.0.0" + "estraverse": "^5.1.0" }, "dependencies": { "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", "dev": true } } }, "esrecurse": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", - "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, "requires": { - "estraverse": "^4.1.0" + "estraverse": "^5.2.0" }, "dependencies": { "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", "dev": true } } @@ -3696,9 +3867,9 @@ "dev": true }, "estree-walker": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", - "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", "dev": true }, "esutils": { @@ -3714,9 +3885,9 @@ "dev": true }, "eventemitter3": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.0.tgz", - "integrity": "sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", "dev": true }, "execa": { @@ -3905,9 +4076,9 @@ "dev": true }, "fast-deep-equal": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", - "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, "fast-json-stable-stringify": { @@ -3995,12 +4166,13 @@ "dev": true }, "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "requires": { - "locate-path": "^2.0.0" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" } }, "flat-cache": { @@ -4026,9 +4198,9 @@ } }, "flatted": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", - "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", "dev": true }, "fn-name": { @@ -4038,30 +4210,10 @@ "dev": true }, "follow-redirects": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.10.0.tgz", - "integrity": "sha512-4eyLK6s6lH32nOvLLwlIOnr9zrL8Sm+OvW4pVTJNoXeGzYIkHVf+pADQi+OJ0E67hiuSLezPVPyBcIZO50TmmQ==", - "dev": true, - "requires": { - "debug": "^3.0.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz", + "integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==", + "dev": true }, "for-in": { "version": "1.0.2", @@ -4090,22 +4242,13 @@ "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", "dev": true }, - "fs-access": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fs-access/-/fs-access-1.0.1.tgz", - "integrity": "sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=", - "dev": true, - "requires": { - "null-check": "^1.0.0" - } - }, "fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "dev": true, "requires": { - "graceful-fs": "^4.1.2", + "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } @@ -4117,9 +4260,9 @@ "dev": true }, "fsevents": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz", - "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", "dev": true, "optional": true }, @@ -4172,11 +4315,28 @@ } }, "gensync": { - "version": "1.0.0-beta.1", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", - "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==", + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, + "get-intrinsic": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.1.tgz", + "integrity": "sha512-ZnWP+AmS1VUaLgTRy47+zKtjTxz+0xMpx3I52i+aalBK1QP19ggLF3Db89KJX7kjfOfP2eoa01qc++GwPgufPg==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, "get-own-enumerable-property-symbols": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", @@ -4222,6 +4382,12 @@ "pinkie-promise": "^2.0.0" } }, + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, "indent-string": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", @@ -4231,19 +4397,6 @@ "repeating": "^2.0.0" } }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - } - }, "map-obj": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", @@ -4268,19 +4421,16 @@ "trim-newlines": "^1.0.0" } }, - "minimist": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.4.tgz", - "integrity": "sha512-wTiNDqe4D2rbTJGZk1qcdZgFtY0/r+iuE6GDT7V0/+Gu5MLpIDm4+CssDECR79OJs/OxLPXMzdxy153b5Qy3hg==", - "dev": true - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, "requires": { - "error-ex": "^1.2.0" + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" } }, "path-exists": { @@ -4292,23 +4442,6 @@ "pinkie-promise": "^2.0.0" } }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, "read-pkg": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", @@ -4361,24 +4494,21 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { "safe-buffer": "~5.1.0" } }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } - }, "strip-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", @@ -4440,6 +4570,41 @@ "through2": "^2.0.0" }, "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "camelcase-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz", + "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=", + "dev": true, + "requires": { + "camelcase": "^4.1.0", + "map-obj": "^2.0.0", + "quick-lru": "^1.0.0" + } + }, + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "dev": true + }, + "map-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz", + "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=", + "dev": true + }, "meow": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/meow/-/meow-4.0.1.tgz", @@ -4457,10 +4622,32 @@ "trim-newlines": "^2.0.0" } }, - "minimist": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.4.tgz", - "integrity": "sha512-wTiNDqe4D2rbTJGZk1qcdZgFtY0/r+iuE6GDT7V0/+Gu5MLpIDm4+CssDECR79OJs/OxLPXMzdxy153b5Qy3hg==", + "minimist-options": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-3.0.2.tgz", + "integrity": "sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==", + "dev": true, + "requires": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0" + } + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "quick-lru": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz", + "integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=", "dev": true }, "readable-stream": { @@ -4478,12 +4665,28 @@ "util-deprecate": "~1.0.1" } }, + "redent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz", + "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=", + "dev": true, + "requires": { + "indent-string": "^3.0.0", + "strip-indent": "^2.0.0" + } + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -4493,6 +4696,12 @@ "safe-buffer": "~5.1.0" } }, + "strip-indent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", + "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", + "dev": true + }, "through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", @@ -4502,6 +4711,12 @@ "readable-stream": "~2.3.6", "xtend": "~4.0.1" } + }, + "trim-newlines": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz", + "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=", + "dev": true } } }, @@ -4513,23 +4728,15 @@ "requires": { "gitconfiglocal": "^1.0.0", "pify": "^2.3.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } } }, "git-semver-tags": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-3.0.1.tgz", - "integrity": "sha512-Hzd1MOHXouITfCasrpVJbRDg9uvW7LfABk3GQmXYZByerBDrfrEMP9HXpNT7RxAbieiocP6u+xq20DkvjwxnCA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-4.1.1.tgz", + "integrity": "sha512-OWyMt5zBe7xFs8vglMmhM9lRQzCWL3WjHtxNNfJTMngGym7pC1kh8sP6jevfydJ6LP3ZvGxfb6ABYgPUM0mtsA==", "dev": true, "requires": { - "meow": "^5.0.0", + "meow": "^8.0.0", "semver": "^6.0.0" } }, @@ -4563,9 +4770,9 @@ } }, "glob-parent": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", - "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", "dev": true, "requires": { "is-glob": "^4.0.1" @@ -4610,6 +4817,12 @@ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true }, + "globalyzer": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.4.tgz", + "integrity": "sha512-LeguVWaxgHN0MNbWC6YljNMzHkrCny9fzjmEUdnF1kQ7wATFD1RHFRqA1qxaX2tgxGENlcxjOflopBwj3YZiXA==", + "dev": true + }, "globby": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", @@ -4621,20 +4834,18 @@ "object-assign": "^4.0.1", "pify": "^2.0.0", "pinkie-promise": "^2.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } } }, + "globrex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", + "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", + "dev": true + }, "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", "dev": true }, "graphlib": { @@ -4647,17 +4858,24 @@ } }, "handlebars": { - "version": "4.7.3", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.3.tgz", - "integrity": "sha512-SRGwSYuNfx8DwHD/6InAPzD6RgeruWLT+B8e8a7gGs8FWgHzlExpTFMEq2IA6QpAfOClpKHy6+8IqTjeBCu6Kg==", + "version": "4.7.6", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz", + "integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==", "dev": true, "requires": { + "minimist": "^1.2.5", "neo-async": "^2.6.0", - "optimist": "^0.6.1", "source-map": "^0.6.1", - "uglify-js": "^3.1.4" + "uglify-js": "^3.1.4", + "wordwrap": "^1.0.0" } }, + "hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true + }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -4785,10 +5003,13 @@ } }, "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", - "dev": true + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.7.tgz", + "integrity": "sha512-fWqc0IcuXs+BmE9orLDyVykAG9GJtGLGuZAAqgcckPgv5xad4AcXGIv8galtQvlwutxSlaMcdw7BUtq2EIvqCQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } }, "htmlparser2": { "version": "3.9.2", @@ -4858,9 +5079,9 @@ } }, "http-proxy": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.0.tgz", - "integrity": "sha512-84I2iJM/n1d4Hdgc6y2+qY5mDaz2PUVjlg9znE9byl+q0uC3DeByqBGReQu5tpLK0TAqTIXScRUV+dg7+bUPpQ==", + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", "dev": true, "requires": { "eventemitter3": "^4.0.0", @@ -4928,6 +5149,12 @@ "integrity": "sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ==", "dev": true }, + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, "locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", @@ -4938,13 +5165,16 @@ "path-exists": "^3.0.0" } }, - "p-limit": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz", - "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==", + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, "requires": { - "p-try": "^2.0.0" + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" } }, "p-locate": { @@ -4956,24 +5186,12 @@ "p-limit": "^2.0.0" } }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "dev": true }, - "parse-json": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz", - "integrity": "sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1", - "lines-and-columns": "^1.1.6" - } - }, "read-pkg": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", @@ -4985,6 +5203,18 @@ "parse-json": "^5.0.0", "type-fest": "^0.6.0" } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true } } }, @@ -5020,9 +5250,9 @@ "dev": true }, "indent-string": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", - "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true }, "indexof": { @@ -5139,9 +5369,9 @@ } }, "interpret": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", - "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", "dev": true }, "invariant": { @@ -5211,9 +5441,9 @@ "dev": true }, "is-callable": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", - "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", + "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", "dev": true }, "is-ci": { @@ -5225,6 +5455,15 @@ "ci-info": "^2.0.0" } }, + "is-core-module": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.1.0.tgz", + "integrity": "sha512-YcV7BgVMRFRua2FqQzKtTDMz8iCuLEyGKjr70q8Zm1yy2qKcurbFEd79PAdHV77oL3NrAaOVQIbMmiHQCHB7ZA==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, "is-data-descriptor": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", @@ -5282,6 +5521,12 @@ "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", "dev": true }, + "is-docker": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.1.1.tgz", + "integrity": "sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw==", + "dev": true + }, "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", @@ -5335,6 +5580,12 @@ "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", "dev": true }, + "is-negative-zero": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", + "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", + "dev": true + }, "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", @@ -5356,9 +5607,9 @@ } }, "is-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", "dev": true }, "is-observable": { @@ -5410,35 +5661,27 @@ } }, "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", "dev": true }, "is-reference": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.1.4.tgz", - "integrity": "sha512-uJA/CDPO3Tao3GTrxYn6AwkM4nUPJiGGYu5+cB8qbC7WGFlrKZbiRo7SFKxUAEpFUfiHofWCXBUNhvYJMh+6zw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", + "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", "dev": true, "requires": { - "@types/estree": "0.0.39" - }, - "dependencies": { - "@types/estree": { - "version": "0.0.39", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", - "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", - "dev": true - } + "@types/estree": "*" } }, "is-regex": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", - "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", "dev": true, "requires": { - "has": "^1.0.3" + "has-symbols": "^1.0.1" } }, "is-regexp": { @@ -5502,10 +5745,13 @@ "dev": true }, "is-wsl": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.1.1.tgz", - "integrity": "sha512-umZHcSrwlDHo2TGMXv0DZ8dIUGunZ2Iv68YZnrmCiBPkZ4aaOhtv7pXJKeki9k3qJ3RJr0cDyitcl5wEH3AYog==", - "dev": true + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "requires": { + "is-docker": "^2.0.0" + } }, "isarray": { "version": "1.0.0", @@ -5514,13 +5760,10 @@ "dev": true }, "isbinaryfile": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", - "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", - "dev": true, - "requires": { - "buffer-alloc": "^1.2.0" - } + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.6.tgz", + "integrity": "sha512-ORrEy+SNVqUhrCaal4hA4fBzhggQQ+BaLntyPOdoEiwlKZW9BZiJXjg3RMiruE4tPEI3pyVPpySHQF/dKWperg==", + "dev": true }, "isexe": { "version": "2.0.0", @@ -5562,12 +5805,6 @@ "wordwrap": "^1.0.0" }, "dependencies": { - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, "esprima": { "version": "2.7.3", "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", @@ -5607,12 +5844,6 @@ "requires": { "has-flag": "^1.0.0" } - }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true } } }, @@ -5667,9 +5898,9 @@ } }, "js-reporters": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/js-reporters/-/js-reporters-1.2.1.tgz", - "integrity": "sha1-+IxgjjJKM3OpW8xFrTBeXJecRZs=", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/js-reporters/-/js-reporters-1.2.3.tgz", + "integrity": "sha512-2YzWkHbbRu6LueEs5ZP3P1LqbECvAeUJYrjw3H4y1ofW06hqCS0AbzBtLwbr+Hke51bt9CUepJ/Fj1hlCRIF6A==", "dev": true }, "js-tokens": { @@ -5679,9 +5910,9 @@ "dev": true }, "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", + "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", "dev": true, "requires": { "argparse": "^1.0.7", @@ -5744,6 +5975,12 @@ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -5763,20 +6000,12 @@ "dev": true }, "json5": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.1.tgz", - "integrity": "sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", + "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", "dev": true, "requires": { - "minimist": "^1.2.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.4.tgz", - "integrity": "sha512-wTiNDqe4D2rbTJGZk1qcdZgFtY0/r+iuE6GDT7V0/+Gu5MLpIDm4+CssDECR79OJs/OxLPXMzdxy153b5Qy3hg==", - "dev": true - } + "minimist": "^1.2.5" } }, "jsonfile": { @@ -5805,43 +6034,40 @@ "dev": true }, "just-extend": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.1.0.tgz", - "integrity": "sha512-ApcjaOdVTJ7y4r08xI5wIqpvwS48Q0PBG4DJROcEkH1f8MdAiNFyFxz3xoL0LWAVwjrwPYZdVHHxhRHcx/uGLA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.1.1.tgz", + "integrity": "sha512-aWgeGFW67BP3e5181Ep1Fv2v8z//iBJfrvyTnq8wG86vEESwmonn1zPBJ0VfmT9CJq2FIT0VsETtrNFm2a+SHA==", "dev": true }, "karma": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/karma/-/karma-4.4.1.tgz", - "integrity": "sha512-L5SIaXEYqzrh6b1wqYC42tNsFMx2PWuxky84pK9coK09MvmL7mxii3G3bZBh/0rvD27lqDd0le9jyhzvwif73A==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/karma/-/karma-5.2.3.tgz", + "integrity": "sha512-tHdyFADhVVPBorIKCX8A37iLHxc6RBRphkSoQ+MLKdAtFn1k97tD8WUGi1KlEtDZKL3hui0qhsY9HXUfSNDYPQ==", "dev": true, "requires": { - "bluebird": "^3.3.0", - "body-parser": "^1.16.1", + "body-parser": "^1.19.0", "braces": "^3.0.2", - "chokidar": "^3.0.0", - "colors": "^1.1.0", - "connect": "^3.6.0", + "chokidar": "^3.4.2", + "colors": "^1.4.0", + "connect": "^3.7.0", "di": "^0.0.1", - "dom-serialize": "^2.2.0", - "flatted": "^2.0.0", - "glob": "^7.1.1", - "graceful-fs": "^4.1.2", - "http-proxy": "^1.13.0", - "isbinaryfile": "^3.0.0", - "lodash": "^4.17.14", - "log4js": "^4.0.0", - "mime": "^2.3.1", - "minimatch": "^3.0.2", - "optimist": "^0.6.1", - "qjobs": "^1.1.4", - "range-parser": "^1.2.0", - "rimraf": "^2.6.0", - "safe-buffer": "^5.0.1", - "socket.io": "2.1.1", + "dom-serialize": "^2.2.1", + "glob": "^7.1.6", + "graceful-fs": "^4.2.4", + "http-proxy": "^1.18.1", + "isbinaryfile": "^4.0.6", + "lodash": "^4.17.19", + "log4js": "^6.2.1", + "mime": "^2.4.5", + "minimatch": "^3.0.4", + "qjobs": "^1.2.0", + "range-parser": "^1.2.1", + "rimraf": "^3.0.2", + "socket.io": "^2.3.0", "source-map": "^0.6.1", - "tmp": "0.0.33", - "useragent": "2.3.0" + "tmp": "0.2.1", + "ua-parser-js": "0.7.22", + "yargs": "^15.3.1" }, "dependencies": { "braces": { @@ -5868,6 +6094,15 @@ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -5891,12 +6126,11 @@ } }, "karma-chrome-launcher": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz", - "integrity": "sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.1.0.tgz", + "integrity": "sha512-3dPs/n7vgz1rxxtynpzZTvb9y/GIaW8xjAwcIGttLbycqoFtI7yo1NGnQi6oFTherRE+GIhCAHZC4vEqWGhNvg==", "dev": true, "requires": { - "fs-access": "^1.0.0", "which": "^1.2.1" } }, @@ -5949,6 +6183,12 @@ "pinkie-promise": "^2.0.0" } }, + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, "indent-string": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", @@ -5958,19 +6198,6 @@ "repeating": "^2.0.0" } }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - } - }, "map-obj": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", @@ -5995,19 +6222,16 @@ "trim-newlines": "^1.0.0" } }, - "minimist": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.4.tgz", - "integrity": "sha512-wTiNDqe4D2rbTJGZk1qcdZgFtY0/r+iuE6GDT7V0/+Gu5MLpIDm4+CssDECR79OJs/OxLPXMzdxy153b5Qy3hg==", - "dev": true - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, "requires": { - "error-ex": "^1.2.0" + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" } }, "path-exists": { @@ -6019,23 +6243,6 @@ "pinkie-promise": "^2.0.0" } }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, "read-pkg": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", @@ -6067,21 +6274,18 @@ "strip-indent": "^1.0.1" } }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } - }, "strip-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", @@ -6109,12 +6313,24 @@ } }, "karma-firefox-launcher": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/karma-firefox-launcher/-/karma-firefox-launcher-1.3.0.tgz", - "integrity": "sha512-Fi7xPhwrRgr+94BnHX0F5dCl1miIW4RHnzjIGxF8GaIEp7rNqX7LSi7ok63VXs3PS/5MQaQMhGxw+bvD+pibBQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/karma-firefox-launcher/-/karma-firefox-launcher-2.1.0.tgz", + "integrity": "sha512-dkiyqN2R6fCWt78rciOXJLFDWcQ7QEQi++HgebPJlw1y0ycDjGNDHuSrhdh48QG02fzZKK20WHFWVyBZ6CPngg==", "dev": true, "requires": { - "is-wsl": "^2.1.0" + "is-wsl": "^2.2.0", + "which": "^2.0.1" + }, + "dependencies": { + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } } }, "karma-ie-launcher": { @@ -6127,9 +6343,9 @@ } }, "karma-qunit": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/karma-qunit/-/karma-qunit-3.1.3.tgz", - "integrity": "sha512-RX2M2bmk3/LMJJ8BwddmKMe/nom5QXdQmbpeB7t8tf8CSy4FQaR+m3+ONuHlPsgA8snbfcZiG/KHLhN1cvi98A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/karma-qunit/-/karma-qunit-4.1.1.tgz", + "integrity": "sha512-sl4rSTGK1fXWyXdNu8ySQvsf77OuJ1gQg9gbHIj0V05h4FvcNogpirO7R4ijU4L7ioXk8WupvSJZHE7QI9B7uQ==", "dev": true }, "karma-safari-applescript-launcher": { @@ -6176,21 +6392,6 @@ "graceful-fs": "^4.1.9" } }, - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true - }, - "levenary": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/levenary/-/levenary-1.1.1.tgz", - "integrity": "sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ==", - "dev": true, - "requires": { - "leven": "^3.1.0" - } - }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", @@ -6262,9 +6463,15 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true - } - } - }, + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, "listenercount": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", @@ -6337,6 +6544,12 @@ "supports-color": "^2.0.0" } }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "dev": true + }, "log-symbols": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", @@ -6378,31 +6591,42 @@ } }, "load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "dev": true, "requires": { "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + }, + "dependencies": { + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + } } }, "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" + "p-locate": "^4.1.0" } }, "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", "dev": true }, "lodash-compat": { @@ -6505,25 +6729,25 @@ } }, "log4js": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-4.5.1.tgz", - "integrity": "sha512-EEEgFcE9bLgaYUKuozyFfytQM2wDHtXn4tAN41pkaxpNjAykv11GVdeI4tHtmPWW4Xrgh9R/2d7XYghDVjbKKw==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.3.0.tgz", + "integrity": "sha512-Mc8jNuSFImQUIateBFwdOQcmC6Q5maU0VVvdC2R6XMb66/VnT+7WS4D/0EeNMZu1YODmJe5NIn2XftCzEocUgw==", "dev": true, "requires": { - "date-format": "^2.0.0", + "date-format": "^3.0.0", "debug": "^4.1.1", - "flatted": "^2.0.0", + "flatted": "^2.0.1", "rfdc": "^1.1.4", - "streamroller": "^1.0.6" + "streamroller": "^2.2.4" }, "dependencies": { "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.0.tgz", + "integrity": "sha512-jjO6JD2rKfiZQnBoRzhRTbXjHLGLfH+UtGkWLc/UXAh/rzZMyjbgn0NcfFpqT8nd1kTtFnDiJcrIFkq4UKeJVg==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } }, "ms": { @@ -6563,13 +6787,12 @@ } }, "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" + "yallist": "^4.0.0" } }, "m3u8-parser": { @@ -6598,9 +6821,9 @@ "dev": true }, "map-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz", - "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.1.0.tgz", + "integrity": "sha512-glc9y00wgtwcDmp7GaE/0b0OnxpNJsVf3ael/An6Fe2Q51LLwN1er6sdomLRzz5h0+yMpiYLhWYF5R7HeqVd4g==", "dev": true }, "map-visit": { @@ -6685,20 +6908,87 @@ "dev": true }, "meow": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-5.0.0.tgz", - "integrity": "sha512-CbTqYU17ABaLefO8vCU153ZZlprKYWDljcndKKDCFcYQITzWCXZAVk4QMFZPgvzrnUQ3uItnIE/LoUOwrT15Ig==", - "dev": true, - "requires": { - "camelcase-keys": "^4.0.0", - "decamelize-keys": "^1.0.0", - "loud-rejection": "^1.0.0", - "minimist-options": "^3.0.1", - "normalize-package-data": "^2.3.4", - "read-pkg-up": "^3.0.0", - "redent": "^2.0.0", - "trim-newlines": "^2.0.0", - "yargs-parser": "^10.0.0" + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-8.0.0.tgz", + "integrity": "sha512-nbsTRz2fwniJBFgUkcdISq8y/q9n9VbiHYbfwklFh5V4V2uAcxtKQkDc0yCLPM/kP0d+inZBewn3zJqewHE7kg==", + "dev": true, + "requires": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" + }, + "dependencies": { + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, + "read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "requires": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "dependencies": { + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true + } + } + }, + "read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "requires": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "dependencies": { + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + } + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } } }, "merge-stream": { @@ -6738,24 +7028,24 @@ } }, "mime": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", - "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", + "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==", "dev": true }, "mime-db": { - "version": "1.43.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", - "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==", + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", "dev": true }, "mime-types": { - "version": "2.1.26", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", - "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", "dev": true, "requires": { - "mime-db": "1.43.0" + "mime-db": "1.44.0" } }, "mimic-fn": { @@ -6772,6 +7062,12 @@ "dom-walk": "^0.1.0" } }, + "min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -6782,19 +7078,20 @@ } }, "minimist": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", - "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, "minimist-options": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-3.0.2.tgz", - "integrity": "sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", "dev": true, "requires": { "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0" + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" } }, "mixin-deep": { @@ -6819,20 +7116,12 @@ } }, "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "dev": true, "requires": { - "minimist": "0.0.8" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - } + "minimist": "^1.2.5" } }, "modify-values": { @@ -6901,9 +7190,9 @@ "dev": true }, "neo-async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", - "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, "nice-try": { @@ -6927,18 +7216,15 @@ } }, "node-releases": { - "version": "1.1.52", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.52.tgz", - "integrity": "sha512-snSiT1UypkgGt2wxPqS6ImEUICbNCMb31yaxWrOLXjhlt2z2/IBpaOxzONExqSm4y5oLnAqjjRWu+wsDzK5yNQ==", - "dev": true, - "requires": { - "semver": "^6.3.0" - } + "version": "1.1.66", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.66.tgz", + "integrity": "sha512-JHEQ1iWPGK+38VLB2H9ef2otU4l8s3yAMt9Xf934r6+ojCYDMHPMqvCc9TnzfeFSP1QEOeU6YZEd3+De0LTCgg==", + "dev": true }, "node-watch": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/node-watch/-/node-watch-0.6.1.tgz", - "integrity": "sha512-gwQiR7weFRV8mAtT0x0kXkZ18dfRLB45xH7q0hCOVQMLfLb2f1ZaSvR57q4/b/Vj6B0RwMNJYbvb69e1yM7qEA==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/node-watch/-/node-watch-0.7.0.tgz", + "integrity": "sha512-OOBiglke5SlRQT5WYfwXTmYqTfXjcTNBHpalyHLtLxDpQYVpVRkJqabcch1kmwJsjV/J4OZuzEafeb4soqtFZA==", "dev": true }, "nomnom": { @@ -7016,21 +7302,21 @@ "dev": true }, "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.0.tgz", + "integrity": "sha512-6lUjEI0d3v6kFrtgA/lOx4zHCWULXsFNIjHolnZCKCTLA6m/G625cdn3O7eNmT0iD3jfo6HZ9cdImGZwf21prw==", "dev": true, "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", + "hosted-git-info": "^3.0.6", + "resolve": "^1.17.0", + "semver": "^7.3.2", "validate-npm-package-license": "^3.0.1" }, "dependencies": { "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", "dev": true } } @@ -7059,9 +7345,9 @@ } }, "npm-merge-driver": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/npm-merge-driver/-/npm-merge-driver-2.3.5.tgz", - "integrity": "sha512-MUxE26ZdDWAc+wlqwyOEIhRH1EdaIXCWSZbqAQ76dUkz3uSrxrLhfgQ3nb3oZbqC5e4NyLcCdzTSDVwkisoJpg==", + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/npm-merge-driver/-/npm-merge-driver-2.3.6.tgz", + "integrity": "sha512-uPjCEWZ93f379zw0AMEgFtZIlpSSnpXc8BEIcs8yYHEZs5Y3d85OZHisLjNhjbYnbdAznxTq+VbyBWAQZDEm9w==", "dev": true, "requires": { "mkdirp": "^0.5.1", @@ -7518,12 +7804,6 @@ "gauge": "~1.2.5" } }, - "null-check": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/null-check/-/null-check-1.0.0.tgz", - "integrity": "sha1-l33/1xdgErnsMNKjnbXPcqBDnt0=", - "dev": true - }, "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", @@ -7574,9 +7854,9 @@ } }, "object-inspect": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", - "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", "dev": true }, "object-keys": { @@ -7595,15 +7875,15 @@ } }, "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", "dev": true, "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" } }, "object.pick": { @@ -7642,16 +7922,6 @@ "mimic-fn": "^1.0.0" } }, - "optimist": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "dev": true, - "requires": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" - } - }, "optionator": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", @@ -7685,21 +7955,21 @@ "dev": true }, "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "requires": { - "p-try": "^1.0.0" + "p-try": "^2.0.0" } }, "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "requires": { - "p-limit": "^1.1.0" + "p-limit": "^2.2.0" } }, "p-map": { @@ -7709,9 +7979,9 @@ "dev": true }, "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, "parent-module": { @@ -7752,13 +8022,15 @@ "dev": true }, "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.1.0.tgz", + "integrity": "sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ==", "dev": true, "requires": { + "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" } }, "parse-passwd": { @@ -7798,9 +8070,9 @@ "dev": true }, "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true }, "path-is-absolute": { @@ -7845,30 +8117,32 @@ } }, "path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", "dev": true, "requires": { - "pify": "^3.0.0" + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" } }, "picomatch": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.1.tgz", - "integrity": "sha512-ISBaA8xQNmwELC7eOjqFKMESB2VIqt4PPDD0nsS95b/9dZXvVKOlz9keMSnoGGKcOHXfTvDD6WMaRoSc9UuhRA==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", "dev": true }, "pidtree": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.0.tgz", - "integrity": "sha512-9CT4NFlDcosssyg8KVFltgokyKZIFjoBxw8CTGy+5F38Y1eQWrt8tRayiUOXE+zVKQnYu5BR8JjCtvK3BcnBhg==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", + "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", "dev": true }, "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true }, "pinkie": { @@ -7887,9 +8161,9 @@ } }, "pkcs7": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pkcs7/-/pkcs7-1.0.3.tgz", - "integrity": "sha512-3MP+alokz148xIxdMpLovjxIUia1cMzxyJ6FjyZl2a1UPapjRk4Y8hni4KsZRGrdbD1woArGMKe/OsSB7ggzHQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/pkcs7/-/pkcs7-1.0.4.tgz", + "integrity": "sha512-afRERtHn54AlwaF2/+LFszyAANTCggGilmcmILUzEjvs3XgFZT+xE6+QWQcAGmu4xajy+Xtj7acLOPdx5/eXWQ==", "requires": { "@babel/runtime": "^7.5.5" } @@ -7910,70 +8184,138 @@ "dev": true, "requires": { "find-up": "^4.0.0" + } + }, + "pkg-ok": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/pkg-ok/-/pkg-ok-2.3.1.tgz", + "integrity": "sha512-ObdQTDZO+zUJpljXM5HZdx+354o5qbQUs05oilAp2WisGoAmFw80y4RKMduZOmGpuXV1DWJ7PkZnkybd8QB68g==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "meow": "^5.0.0", + "normalize-newline": "^3.0.0" }, "dependencies": { - "find-up": { + "camelcase": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "camelcase-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz", + "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=", "dev": true, "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "camelcase": "^4.1.0", + "map-obj": "^2.0.0", + "quick-lru": "^1.0.0" } }, - "locate-path": { + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "dev": true + }, + "map-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz", + "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=", + "dev": true + }, + "meow": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "resolved": "https://registry.npmjs.org/meow/-/meow-5.0.0.tgz", + "integrity": "sha512-CbTqYU17ABaLefO8vCU153ZZlprKYWDljcndKKDCFcYQITzWCXZAVk4QMFZPgvzrnUQ3uItnIE/LoUOwrT15Ig==", "dev": true, "requires": { - "p-locate": "^4.1.0" + "camelcase-keys": "^4.0.0", + "decamelize-keys": "^1.0.0", + "loud-rejection": "^1.0.0", + "minimist-options": "^3.0.1", + "normalize-package-data": "^2.3.4", + "read-pkg-up": "^3.0.0", + "redent": "^2.0.0", + "trim-newlines": "^2.0.0", + "yargs-parser": "^10.0.0" } }, - "p-limit": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz", - "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==", + "minimist-options": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-3.0.2.tgz", + "integrity": "sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==", "dev": true, "requires": { - "p-try": "^2.0.0" + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0" } }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, "requires": { - "p-limit": "^2.2.0" + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" } }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "quick-lru": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz", + "integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=", "dev": true }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "redent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz", + "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=", + "dev": true, + "requires": { + "indent-string": "^3.0.0", + "strip-indent": "^2.0.0" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "strip-indent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", + "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", + "dev": true + }, + "trim-newlines": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz", + "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=", "dev": true + }, + "yargs-parser": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", + "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", + "dev": true, + "requires": { + "camelcase": "^4.1.0" + } } } }, - "pkg-ok": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/pkg-ok/-/pkg-ok-2.3.1.tgz", - "integrity": "sha512-ObdQTDZO+zUJpljXM5HZdx+354o5qbQUs05oilAp2WisGoAmFw80y4RKMduZOmGpuXV1DWJ7PkZnkybd8QB68g==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "meow": "^5.0.0", - "normalize-newline": "^3.0.0" - } - }, "please-upgrade-node": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", @@ -8003,22 +8345,8 @@ "requires": { "colors": "^1.1.2", "minimist": "^1.2.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.4.tgz", - "integrity": "sha512-wTiNDqe4D2rbTJGZk1qcdZgFtY0/r+iuE6GDT7V0/+Gu5MLpIDm4+CssDECR79OJs/OxLPXMzdxy153b5Qy3hg==", - "dev": true - } } }, - "private": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", - "dev": true - }, "process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -8042,12 +8370,6 @@ "integrity": "sha512-CGuc0VUTGthpJXL36ydB6jnbyOf/rAHFvmVrJlH+Rg0DqqLFQGAP6hIaxD/G0OAmBJPhXDHuEJigrp0e0wFV6g==", "dev": true }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, "pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -8083,41 +8405,40 @@ "dev": true }, "quick-lru": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz", - "integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", "dev": true }, "qunit": { - "version": "2.9.3", - "resolved": "https://registry.npmjs.org/qunit/-/qunit-2.9.3.tgz", - "integrity": "sha512-RH4VYSaVsNRDthMFFboTJAJ8q4kJM5LvOqWponKUYPEAeOcmc/YFV1QsZ7ikknA3TjqliWFJYEV63vvVXaALmQ==", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/qunit/-/qunit-2.12.0.tgz", + "integrity": "sha512-Lu3tbKziVzXTfseoEtTiiSAbSPB6SGU4Emc2uo8n+fbsXuRCLzfqPwJfAVJwKu9NdukX1V/L0qWf2UvmPX+QeA==", "dev": true, "requires": { - "commander": "2.12.2", - "js-reporters": "1.2.1", - "minimatch": "3.0.4", - "node-watch": "0.6.1", - "resolve": "1.9.0" + "commander": "6.2.0", + "js-reporters": "1.2.3", + "node-watch": "0.7.0", + "tiny-glob": "0.2.6" }, "dependencies": { "commander": { - "version": "2.12.2", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.12.2.tgz", - "integrity": "sha512-BFnaq5ZOGcDN7FlrtBT4xxkgIToalIIxwjxLWVJ8bGTpe1LroqMiqQXdA7ygc7CRvaYS+9zfPGFnJqFSayx+AA==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.0.tgz", + "integrity": "sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==", "dev": true - }, - "resolve": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.9.0.tgz", - "integrity": "sha512-TZNye00tI67lwYvzxCxHGjwTNlUV70io54/Ed4j6PscB8xVfuBJpRenI/o6dVk0cY0PYTY27AgCoGGxRnYuItQ==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } } } }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, "range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -8145,16 +8466,136 @@ "load-json-file": "^4.0.0", "normalize-package-data": "^2.3.2", "path-type": "^3.0.0" - } - }, - "read-pkg-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", - "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", - "dev": true, + }, + "dependencies": { + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + } + } + }, + "read-pkg-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", + "dev": true, "requires": { "find-up": "^2.0.0", "read-pkg": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + } } }, "readable-stream": { @@ -8169,12 +8610,12 @@ } }, "readdirp": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.3.0.tgz", - "integrity": "sha512-zz0pAkSPOXXm1viEwygWIPSPkcBYjW1xU5j/JBh5t9bGCJwa6f9+BJa6VaB2g+b55yVrmXzqkyLf4xaWYM0IkQ==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", "dev": true, "requires": { - "picomatch": "^2.0.7" + "picomatch": "^2.2.1" } }, "rechoir": { @@ -8187,19 +8628,19 @@ } }, "redent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz", - "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", "dev": true, "requires": { - "indent-string": "^3.0.0", - "strip-indent": "^2.0.0" + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" } }, "regenerate": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", - "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", "dev": true }, "regenerate-unicode-properties": { @@ -8212,18 +8653,17 @@ } }, "regenerator-runtime": { - "version": "0.13.4", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.4.tgz", - "integrity": "sha512-plpwicqEzfEyTQohIKktWigcLzmNStMGwbOUbykx51/29Z3JOGYldaaNGK7ngNXV+UcoqvIMmloZ48Sr74sd+g==" + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" }, "regenerator-transform": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.2.tgz", - "integrity": "sha512-V4+lGplCM/ikqi5/mkkpJ06e9Bujq1NFmNLvsCs56zg3ZbzrnUzAtizZ24TXxtRX/W2jcdScwQCnbL0CICTFkQ==", + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", + "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", "dev": true, "requires": { - "@babel/runtime": "^7.8.4", - "private": "^0.1.8" + "@babel/runtime": "^7.8.4" } }, "regex-not": { @@ -8243,9 +8683,9 @@ "dev": true }, "regexpu-core": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.0.tgz", - "integrity": "sha512-TQ4KXRnIn6tz6tjnrXEkD/sshygKH/j5KzK86X8MkeHyZ8qst/LZ89j3X4/8HEIfHANTFIP/AbXakeRhWIl5YQ==", + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.1.tgz", + "integrity": "sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ==", "dev": true, "requires": { "regenerate": "^1.4.0", @@ -8257,9 +8697,9 @@ } }, "regjsgen": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.1.tgz", - "integrity": "sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", + "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==", "dev": true }, "regjsparser": { @@ -8280,9 +8720,9 @@ } }, "remark-frontmatter": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/remark-frontmatter/-/remark-frontmatter-1.3.2.tgz", - "integrity": "sha512-2eayxITZ8rezsXdgcXnYB3iLivohm2V/ZT4Ne8uhua6A4pk6GdLE2ZzJnbnINtD1HRLaTdB7RwF9sgUbMptJZA==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/remark-frontmatter/-/remark-frontmatter-1.3.3.tgz", + "integrity": "sha512-fM5eZPBvu2pVNoq3ZPW22q+5Ativ1oLozq2qYt9I2oNyxiUd/tDl0iLLntEVAegpZIslPWg1brhcP1VsaSVUag==", "dev": true, "requires": { "fault": "^1.0.1", @@ -8339,6 +8779,18 @@ "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", "dev": true }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, "requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", @@ -8355,11 +8807,12 @@ } }, "resolve": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", - "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.18.1.tgz", + "integrity": "sha512-lDfCPaMKfOJXjy0dPayzPdF1phampNWr3qFCjAu+rw/qbQmr5jWH5xN2hwh9QKfw9E5v4hwV7A+jrCmL8yjjqA==", "dev": true, "requires": { + "is-core-module": "^2.0.0", "path-parse": "^1.0.6" } }, @@ -8448,6 +8901,14 @@ "magic-string": "^0.25.2", "resolve": "^1.11.0", "rollup-pluginutils": "^2.8.1" + }, + "dependencies": { + "estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "dev": true + } } }, "rollup-plugin-istanbul": { @@ -8492,15 +8953,15 @@ } }, "rollup-plugin-terser": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-5.3.0.tgz", - "integrity": "sha512-XGMJihTIO3eIBsVGq7jiNYOdDMb3pVxuzY0uhOE/FM4x/u9nQgr3+McsjzqBn3QfHIpNSZmFnpoKAwHBEcsT7g==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-5.3.1.tgz", + "integrity": "sha512-1pkwkervMJQGFYvM9nscrUoncPwiKR/K+bHdjv6PFgRo3cgPHoRT83y2Aa3GvINj4539S15t/tpFPb775TDs6w==", "dev": true, "requires": { "@babel/code-frame": "^7.5.5", "jest-worker": "^24.9.0", "rollup-pluginutils": "^2.8.2", - "serialize-javascript": "^2.1.2", + "serialize-javascript": "^4.0.0", "terser": "^4.6.2" } }, @@ -8511,6 +8972,14 @@ "dev": true, "requires": { "estree-walker": "^0.6.1" + }, + "dependencies": { + "estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "dev": true + } } }, "run-applescript": { @@ -8546,13 +9015,10 @@ } }, "run-async": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.0.tgz", - "integrity": "sha512-xJTbh/d7Lm7SBhc1tNvTpeCHaEzoyxPrqNlvSdMfBTYwaY++UJFyXUOxAtsRUXjlqOfj8luNaR9vjCh4KeV+pg==", - "dev": true, - "requires": { - "is-promise": "^2.1.0" - } + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true }, "run-node": { "version": "1.0.0", @@ -8575,18 +9041,18 @@ "dev": true }, "rxjs": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.4.tgz", - "integrity": "sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==", + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", + "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", "dev": true, "requires": { "tslib": "^1.9.0" } }, "safe-buffer": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", - "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true }, "safe-json-parse": { @@ -8660,10 +9126,13 @@ } }, "serialize-javascript": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz", - "integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==", - "dev": true + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } }, "serve-static": { "version": "1.14.1", @@ -8677,6 +9146,12 @@ "send": "0.17.1" } }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, "set-value": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", @@ -8734,9 +9209,9 @@ "dev": true }, "shelljs": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.3.tgz", - "integrity": "sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==", + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz", + "integrity": "sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ==", "dev": true, "requires": { "glob": "^7.0.0", @@ -8745,28 +9220,19 @@ } }, "shx": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/shx/-/shx-0.3.2.tgz", - "integrity": "sha512-aS0mWtW3T2sHAenrSrip2XGv39O9dXIFUqxAEWHEOS1ePtGIBavdPJY1kE2IHl14V/4iCbUiNDPGdyYTtmhSoA==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/shx/-/shx-0.3.3.tgz", + "integrity": "sha512-nZJ3HFWVoTSyyB+evEKjJ1STiixGztlqwKLTUNV5KqMWtGey9fTd4KU1gdZ1X9BV6215pswQ/Jew9NsuS/fNDA==", "dev": true, "requires": { - "es6-object-assign": "^1.0.3", - "minimist": "^1.2.0", - "shelljs": "^0.8.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.4.tgz", - "integrity": "sha512-wTiNDqe4D2rbTJGZk1qcdZgFtY0/r+iuE6GDT7V0/+Gu5MLpIDm4+CssDECR79OJs/OxLPXMzdxy153b5Qy3hg==", - "dev": true - } + "minimist": "^1.2.3", + "shelljs": "^0.8.4" } }, "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", "dev": true }, "simple-git": { @@ -8779,12 +9245,12 @@ }, "dependencies": { "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.0.tgz", + "integrity": "sha512-jjO6JD2rKfiZQnBoRzhRTbXjHLGLfH+UtGkWLc/UXAh/rzZMyjbgn0NcfFpqT8nd1kTtFnDiJcrIFkq4UKeJVg==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } }, "ms": { @@ -8817,9 +9283,9 @@ "dev": true }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -8953,27 +9419,33 @@ } }, "socket.io": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", - "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.3.0.tgz", + "integrity": "sha512-2A892lrj0GcgR/9Qk81EaY2gYhCBxurV0PfmmESO6p27QPrUK1J3zdns+5QPqvUYK2q657nSj0guoIil9+7eFg==", "dev": true, "requires": { - "debug": "~3.1.0", - "engine.io": "~3.2.0", + "debug": "~4.1.0", + "engine.io": "~3.4.0", "has-binary2": "~1.0.2", "socket.io-adapter": "~1.1.0", - "socket.io-client": "2.1.1", - "socket.io-parser": "~3.2.0" + "socket.io-client": "2.3.0", + "socket.io-parser": "~3.4.0" }, "dependencies": { "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true } } }, @@ -8984,27 +9456,33 @@ "dev": true }, "socket.io-client": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", - "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.3.0.tgz", + "integrity": "sha512-cEQQf24gET3rfhxZ2jJ5xzAOo/xhZwK+mOqtGRg5IowZsMgwvHwnf/mCRapAAkadhM26y+iydgwsXGObBB5ZdA==", "dev": true, "requires": { "backo2": "1.0.2", "base64-arraybuffer": "0.1.5", "component-bind": "1.0.0", "component-emitter": "1.2.1", - "debug": "~3.1.0", - "engine.io-client": "~3.2.0", + "debug": "~4.1.0", + "engine.io-client": "~3.4.0", "has-binary2": "~1.0.2", "has-cors": "1.1.0", "indexof": "0.0.1", "object-component": "0.0.3", "parseqs": "0.0.5", "parseuri": "0.0.5", - "socket.io-parser": "~3.2.0", + "socket.io-parser": "~3.3.0", "to-array": "0.1.4" }, "dependencies": { + "base64-arraybuffer": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", + "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", + "dev": true + }, "component-emitter": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", @@ -9012,24 +9490,70 @@ "dev": true }, "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" + } + }, + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "socket.io-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.1.tgz", + "integrity": "sha512-1QLvVAe8dTz+mKmZ07Swxt+LAo4Y1ff50rlyoEx00TQmDFVQYPfcqGvIDJLGaBdhdNCecXtyKpD+EgKGcmmbuQ==", + "dev": true, + "requires": { + "component-emitter": "~1.3.0", + "debug": "~3.1.0", + "isarray": "2.0.1" + }, + "dependencies": { + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } } } } }, "socket.io-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", - "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.4.1.tgz", + "integrity": "sha512-11hMgzL+WCLWf1uFtHSNvliI++tcRUWdoeYuwIl+Axvwy9z2gQM+7nJyN3STj1tLj5JyIUH8/gpDGxzAlDdi0A==", "dev": true, "requires": { "component-emitter": "1.2.1", - "debug": "~3.1.0", + "debug": "~4.1.0", "isarray": "2.0.1" }, "dependencies": { @@ -9040,12 +9564,12 @@ "dev": true }, "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } }, "isarray": { @@ -9053,6 +9577,12 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true } } }, @@ -9076,9 +9606,9 @@ } }, "source-map-support": { - "version": "0.5.16", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz", - "integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==", + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", "dev": true, "requires": { "buffer-from": "^1.0.0", @@ -9108,9 +9638,9 @@ } }, "spdx-correct": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", - "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", @@ -9118,15 +9648,15 @@ } }, "spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", "dev": true }, "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dev": true, "requires": { "spdx-exceptions": "^2.1.0", @@ -9134,9 +9664,9 @@ } }, "spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz", + "integrity": "sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw==", "dev": true }, "split": { @@ -9260,25 +9790,29 @@ "dev": true }, "streamroller": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-1.0.6.tgz", - "integrity": "sha512-3QC47Mhv3/aZNFpDDVO44qQb9gwB9QggMEE0sQmkTAwBVYdBRWISdsywlkfm5II1Q5y/pmrHflti/IgmIzdDBg==", + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-2.2.4.tgz", + "integrity": "sha512-OG79qm3AujAM9ImoqgWEY1xG4HX+Lw+yY6qZj9R1K2mhF5bEmQ849wvrb+4vt4jLMLzwXttJlQbOdPOQVRv7DQ==", "dev": true, "requires": { - "async": "^2.6.2", - "date-format": "^2.0.0", - "debug": "^3.2.6", - "fs-extra": "^7.0.1", - "lodash": "^4.17.14" + "date-format": "^2.1.0", + "debug": "^4.1.1", + "fs-extra": "^8.1.0" }, "dependencies": { + "date-format": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz", + "integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==", + "dev": true + }, "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.0.tgz", + "integrity": "sha512-jjO6JD2rKfiZQnBoRzhRTbXjHLGLfH+UtGkWLc/UXAh/rzZMyjbgn0NcfFpqT8nd1kTtFnDiJcrIFkq4UKeJVg==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } }, "ms": { @@ -9316,24 +9850,68 @@ "es-abstract": "^1.17.0-next.1" } }, - "string.prototype.trimleft": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", - "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==", + "string.prototype.trimend": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.2.tgz", + "integrity": "sha512-8oAG/hi14Z4nOVP0z6mdiVZ/wqjDtWSLygMigTzAb+7aPEDTleeFf+WrF+alzecxIRkckkJVn+dTlwzJXORATw==", "dev": true, "requires": { "define-properties": "^1.1.3", - "function-bind": "^1.1.1" + "es-abstract": "^1.18.0-next.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.18.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", + "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } } }, - "string.prototype.trimright": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz", - "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==", + "string.prototype.trimstart": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.2.tgz", + "integrity": "sha512-7F6CdBTl5zyu30BJFdzSTlSlLPwODC23Od+iLoVH8X6+3fvDPPuBVVj9iaB1GOsSTSIgVfsfm27R2FGrAPznWg==", "dev": true, "requires": { "define-properties": "^1.1.3", - "function-bind": "^1.1.1" + "es-abstract": "^1.18.0-next.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.18.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", + "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } } }, "string_decoder": { @@ -9354,6 +9932,14 @@ "get-own-enumerable-property-symbols": "^3.0.0", "is-obj": "^1.0.1", "is-regexp": "^1.0.0" + }, + "dependencies": { + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "dev": true + } } }, "strip-ansi": { @@ -9366,10 +9952,13 @@ } }, "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } }, "strip-eof": { "version": "1.0.0", @@ -9378,10 +9967,13 @@ "dev": true }, "strip-indent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", - "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", - "dev": true + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "requires": { + "min-indent": "^1.0.0" + } }, "strip-json-comments": { "version": "2.0.1", @@ -9414,9 +10006,9 @@ "dev": true }, "synchronous-promise": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/synchronous-promise/-/synchronous-promise-2.0.10.tgz", - "integrity": "sha512-6PC+JRGmNjiG3kJ56ZMNWDPL8hjyghF5cMXIFOKg+NiwwEZZIvxTWd0pinWKyD227odg9ygF8xVhhz7gb8Uq7A==", + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/synchronous-promise/-/synchronous-promise-2.0.15.tgz", + "integrity": "sha512-k8uzYIkIVwmT+TcglpdN50pS2y1BDcUnBPK9iJeGu0Pl1lOI8pD6wtzgw91Pjpe+RxtTncw32tLxs/R0yNL2Mg==", "dev": true }, "table": { @@ -9496,14 +10088,6 @@ "mkdirp": "^0.5.1", "npmlog": "^2.0.3", "object-assign": "^4.1.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.4.tgz", - "integrity": "sha512-wTiNDqe4D2rbTJGZk1qcdZgFtY0/r+iuE6GDT7V0/+Gu5MLpIDm4+CssDECR79OJs/OxLPXMzdxy153b5Qy3hg==", - "dev": true - } } }, "taffydb": { @@ -9529,9 +10113,9 @@ } }, "terser": { - "version": "4.6.6", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.6.6.tgz", - "integrity": "sha512-4lYPyeNmstjIIESr/ysHg2vUPRGf2tzF9z2yYwnowXVuVzLEamPN1Gfrz7f8I9uEPuHcbFlW4PLIAsJoxXyJ1g==", + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", "dev": true, "requires": { "commander": "^2.20.0", @@ -9558,21 +10142,42 @@ "dev": true }, "through2": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.1.tgz", - "integrity": "sha512-M96dvTalPT3YbYLaKaCuwu+j06D/8Jfib0o/PxbVt6Amhv3dUAtW6rTV1jPgJSBG83I/e04Y6xkVdVhSRhi0ww==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", "dev": true, "requires": { - "readable-stream": "2 || 3" + "readable-stream": "3" + } + }, + "tiny-glob": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.6.tgz", + "integrity": "sha512-A7ewMqPu1B5PWwC3m7KVgAu96Ch5LA0w4SnEN/LbDREj/gAD0nPWboRbn8YoP9ISZXqeNAlMvKSKoEuhcfK3Pw==", + "dev": true, + "requires": { + "globalyzer": "^0.1.0", + "globrex": "^0.1.1" } }, "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", "dev": true, "requires": { - "os-tmpdir": "~1.0.2" + "rimraf": "^3.0.0" + }, + "dependencies": { + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } } }, "to-array": { @@ -9654,9 +10259,9 @@ "dev": true }, "trim-newlines": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz", - "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.0.tgz", + "integrity": "sha512-C4+gOpvmxaSMKuEf9Qc134F1ZuOHVXKRbtEflf4NTtuuJDEIJ9p5PXsalL8SkeRw+qit1Mo+yuvMPAKwWg/1hA==", "dev": true }, "trim-off-newlines": { @@ -9672,9 +10277,9 @@ "dev": true }, "trim-trailing-lines": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.3.tgz", - "integrity": "sha512-4ku0mmjXifQcTVfYDfR5lpgV7zVqPg6zV9rdZmwOPqq0+Zq19xDqEgagqVbc4pOOShbncuAOIs59R3+3gcF3ZA==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz", + "integrity": "sha512-rjUWSqnfTNrjbB9NQWfPMH/xRK1deHeGsHoVfpxJ++XeYXE0d6B1En37AHfw3jtfTU7dzMzZL2jjpe8Qb5gLIQ==", "dev": true }, "trough": { @@ -9684,9 +10289,9 @@ "dev": true }, "tslib": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz", - "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, "tsmlb": { @@ -9711,9 +10316,9 @@ "dev": true }, "type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.0.tgz", + "integrity": "sha512-fbDukFPnJBdn2eZ3RR+5mK2slHLFd6gYHY7jna1KWWy4Yr4XysHuCdXRzy+RiG/HwG4WJat00vdC2UHky5eKiQ==", "dev": true }, "type-is": { @@ -9732,6 +10337,12 @@ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, + "ua-parser-js": { + "version": "0.7.22", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.22.tgz", + "integrity": "sha512-YUxzMjJ5T71w6a8WWVcMGM6YWOTX27rCoIQgLXiWaxqXSx9D7DNjiGWn1aJIRSQ5qr0xuhra77bSIh6voR/46Q==", + "dev": true + }, "uc.micro": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", @@ -9739,21 +10350,11 @@ "dev": true }, "uglify-js": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.8.0.tgz", - "integrity": "sha512-ugNSTT8ierCsDHso2jkBHXYrU8Y5/fY2ZUprfrJUiD7YpuFvV4jODLFmb3h4btQjqr5Nh4TX4XtgDfCU1WdioQ==", + "version": "3.11.5", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.11.5.tgz", + "integrity": "sha512-btvv/baMqe7HxP7zJSF7Uc16h1mSfuuSplT0/qdjxseesDU+yYzH33eHBH+eMdeRXwujXspaCTooWHQVVBh09w==", "dev": true, - "optional": true, - "requires": { - "commander": "~2.20.3", - "source-map": "~0.6.1" - } - }, - "ultron": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", - "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", - "dev": true + "optional": true }, "underscore": { "version": "1.8.3", @@ -9978,9 +10579,9 @@ "dev": true }, "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", + "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", "dev": true, "requires": { "punycode": "^2.1.0" @@ -9993,9 +10594,9 @@ "dev": true }, "url-toolkit": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/url-toolkit/-/url-toolkit-2.1.6.tgz", - "integrity": "sha512-UaZ2+50am4HwrV2crR/JAf63Q4VvPYphe63WGeoJxeu8gmOm0qxPt+KsukfakPNrX9aymGNEkkaoICwn+OuvBw==" + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/url-toolkit/-/url-toolkit-2.2.1.tgz", + "integrity": "sha512-8+DzgrtDZYZGhHaAop5WGVghMdCfOLGbhcArsJD0qDll71FXa7EeKxi2hilPIscn2nwMz4PRjML32Sz4JTN0Xw==" }, "use": { "version": "3.1.1", @@ -10003,16 +10604,6 @@ "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", "dev": true }, - "useragent": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", - "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", - "dev": true, - "requires": { - "lru-cache": "4.1.x", - "tmp": "0.0.x" - } - }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -10069,12 +10660,12 @@ } }, "video.js": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/video.js/-/video.js-7.8.3.tgz", - "integrity": "sha512-u8/1qEZdBeOm7TgBhJg8ab28vd3x62UMaaSnZ79yOMaxCqACP9CzWJT9c3Isfv2jY9BNLBIIft+BqNLTWudtLw==", + "version": "7.10.2", + "resolved": "https://registry.npmjs.org/video.js/-/video.js-7.10.2.tgz", + "integrity": "sha512-kJTTrqcQn2MhPzWR8zQs6W3HPJWpowO/ZGZcKt2dcJeJdJT0dEDLYtiFdjV37SylCmu66V0flRnV8cipbthveQ==", "requires": { "@babel/runtime": "^7.9.2", - "@videojs/http-streaming": "1.13.2", + "@videojs/http-streaming": "2.2.4", "@videojs/xhr": "2.5.1", "global": "4.3.2", "keycode": "^2.2.0", @@ -10083,14 +10674,6 @@ "videojs-vtt.js": "^0.15.2" }, "dependencies": { - "@babel/runtime": { - "version": "7.10.3", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.3.tgz", - "integrity": "sha512-RzGO0RLSdokm9Ipe/YD+7ww8X2Ro79qiXZF3HU9ljrM+qnJmH1Vqth+hbiQZy761LnMJTMitHDuKVYTk3k4dLw==", - "requires": { - "regenerator-runtime": "^0.13.4" - } - }, "global": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", @@ -10108,9 +10691,9 @@ } }, "videojs-contrib-eme": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/videojs-contrib-eme/-/videojs-contrib-eme-3.6.0.tgz", - "integrity": "sha512-AuFwXEHasJdJ8j3vDhD6Sx770wj4pFz8SpzudyKfbNonUNGScG0wsxi3/0MuBuBzHyWjuI7nhsVPtwDlx02mJQ==", + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/videojs-contrib-eme/-/videojs-contrib-eme-3.7.1.tgz", + "integrity": "sha512-zWUT2TFZ1zJ0gILZIx9KQELwHQmtaQzmlPJ36pWHh3IogMcWOeWIGBmrIc6leSGN7ZCeV8xieig7CNsAEXlQMg==", "dev": true, "requires": { "global": "^4.3.2", @@ -10133,35 +10716,36 @@ "integrity": "sha512-g8vHMKK2/JGorSfqAZQUmYYNnXmfec4MLhwtEFS+mMs2IDY398GLysy6BH6K+aS1KMNu/xWZ8Sue/X/mdQPliA==" }, "videojs-generate-karma-config": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/videojs-generate-karma-config/-/videojs-generate-karma-config-5.3.1.tgz", - "integrity": "sha512-UmcqyLPD7z/f1JeRxd52VK46Pwyd2McbLLhWfdHzSzWPW5f1Y5ATguiHMSO5WD5dFij02Gg2JN7r9vhSKvTDcA==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/videojs-generate-karma-config/-/videojs-generate-karma-config-7.0.0.tgz", + "integrity": "sha512-nC3SZeVx3OtNiCtdjkC+GT4imfuDhGhpaxr/sfNJv2QmvzKhAhGkySRrh01+SLF85e+yAaCeitDYkXP5QlqtJg==", "dev": true, "requires": { + "is-ci": "^2.0.0", "karma-browserstack-launcher": "~1.4.0", - "karma-chrome-launcher": "^2.2.0", + "karma-chrome-launcher": "^3.1.0", "karma-coverage": "^1.1.2", "karma-detect-browsers": "^2.2.6", - "karma-firefox-launcher": "^1.1.0", + "karma-firefox-launcher": "^2.1.0", "karma-ie-launcher": "^1.0.0", - "karma-qunit": "^3.1.2", + "karma-qunit": "^4.1.1", "karma-safari-applescript-launcher": "~0.1.0", "karma-static-server": "^1.0.0", "karma-teamcity-reporter": "^1.1.0", - "qunit": "~2.9.1" + "qunit": "~2.12.0" } }, "videojs-generate-rollup-config": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/videojs-generate-rollup-config/-/videojs-generate-rollup-config-5.0.1.tgz", - "integrity": "sha512-u/bWEGjlBp3e8qvI3z0DB9mULzLZW+Y3ELF3+/unOZRmZn+CC7iksJXwxaJk0NmJvrd/n/iYCfMjgZS1PBA2rQ==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/videojs-generate-rollup-config/-/videojs-generate-rollup-config-5.0.2.tgz", + "integrity": "sha512-t+1SxvoJ8uqPwTMtZGE29FAM19slrchsbLCwrzCjT5xupbmvlGLwPMuHwoZN4GJcEyx0gYms3XFE3OpEcDEFXQ==", "dev": true, "requires": { - "@babel/core": "^7.0.0", - "@babel/plugin-transform-object-assign": "^7.0.0", - "@babel/plugin-transform-runtime": "^7.5.5", - "@babel/preset-env": "^7.0.0", - "rollup-plugin-babel": "^4.2.0", + "@babel/core": "^7.9.0", + "@babel/plugin-transform-object-assign": "^7.8.3", + "@babel/plugin-transform-runtime": "^7.9.0", + "@babel/preset-env": "^7.9.0", + "rollup-plugin-babel": "^4.4.0", "rollup-plugin-commonjs": "^10.0.1", "rollup-plugin-istanbul": "^2.0.1", "rollup-plugin-json": "^4.0.0", @@ -10195,9 +10779,9 @@ } }, "videojs-standard": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/videojs-standard/-/videojs-standard-8.0.4.tgz", - "integrity": "sha512-IGv4gXB8osXZDsPqYNpWfcmAue/udVEr/Lxa4ewo1aR8s4KY5L6+6IQ+X1Ut9qQUVTSdJZ6QTYvthZzwcHbrkQ==", + "version": "8.0.6", + "resolved": "https://registry.npmjs.org/videojs-standard/-/videojs-standard-8.0.6.tgz", + "integrity": "sha512-QA7kbInwDFaUa+zmJ93CxdC4Rzvt31eUg++jEmSaCzX/sER25LwkVnyY5eA1zBMLwMjLt/dn0yChLAuO+xvwQg==", "dev": true, "requires": { "commander": "^2.17.1", @@ -10233,10 +10817,16 @@ "isexe": "^2.0.0" } }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, "winston": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.4.tgz", - "integrity": "sha512-NBo2Pepn4hK4V01UfcWcDlmiVTs7VTB1h7bgnB0rgP146bYhMxX0ypCz3lBOfNxCO4Zuek7yeT+y/zM1OfMw4Q==", + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.5.tgz", + "integrity": "sha512-TWoamHt5yYvsMarGlGEQE59SbJHqGsZV8/lwC+iCcGeAe0vUaOh+Lv6SYM17ouzC/a/LB1/hz/7sxFBtlu1l4A==", "dev": true, "requires": { "async": "~1.0.0", @@ -10268,9 +10858,9 @@ "dev": true }, "wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", "dev": true }, "wrap-ansi": { @@ -10332,23 +10922,10 @@ } }, "ws": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", - "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", - "dev": true, - "requires": { - "async-limiter": "~1.0.0", - "safe-buffer": "~5.1.0", - "ultron": "~1.1.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.0.tgz", + "integrity": "sha512-kyFwXuV/5ymf+IXhS6f0+eAFvydbaBW3zjpT6hUdAh/hbVjTIB5EHBGi0bPoCLSK2wcuz3BrEkB9LrYv1Nm4NQ==", + "dev": true }, "x-is-string": { "version": "0.1.0", @@ -10379,21 +10956,93 @@ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", "dev": true }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", "dev": true }, - "yargs-parser": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", - "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", - "dev": true, - "requires": { - "camelcase": "^4.1.0" + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } } }, + "yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true + }, "yeast": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", diff --git a/package.json b/package.json index 066bc9877..497afbcd1 100644 --- a/package.json +++ b/package.json @@ -73,7 +73,7 @@ "es5-shim": "^4.5.13", "es6-shim": "^0.35.5", "jsdoc": "BrandonOCasey/jsdoc#feat/plugin-from-cli", - "karma": "^4.0.0", + "karma": "^5.2.3", "lodash": "^4.17.4", "lodash-compat": "^3.10.0", "nomnoml": "^0.3.0", @@ -83,7 +83,7 @@ "url-toolkit": "^2.1.3", "videojs-contrib-eme": "^3.2.0", "videojs-contrib-quality-levels": "^2.0.4", - "videojs-generate-karma-config": "~5.3.1", + "videojs-generate-karma-config": "~7.0.0", "videojs-generate-rollup-config": "~5.0.1", "videojs-generator-verify": "~2.0.0", "videojs-http-source-selector": "^1.1.6", diff --git a/test/playback.test.js b/test/playback.test.js index 8a19ab526..31b9d4063 100644 --- a/test/playback.test.js +++ b/test/playback.test.js @@ -19,7 +19,7 @@ const playFor = function(player, time, cb) { const checkPlayerTime = function() { window.setTimeout(() => { - if (player.currentTime() <= targetTime) { + if (player.tech_ && player.tech_.el_ && player.currentTime() <= targetTime) { return checkPlayerTime(); } cb(); From e7cb63af010779108336eddb5c8fd138d6390e95 Mon Sep 17 00:00:00 2001 From: Brandon Casey <2381475+brandonocasey@users.noreply.github.com> Date: Tue, 17 Nov 2020 16:51:52 -0500 Subject: [PATCH 026/399] fix: abort all loaders on earlyabort (#965) --- src/config.js | 2 +- src/master-playlist-controller.js | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/config.js b/src/config.js index 6ccb0adc3..6a0a00716 100644 --- a/src/config.js +++ b/src/config.js @@ -12,7 +12,7 @@ export default { BUFFER_LOW_WATER_LINE: 0, MAX_BUFFER_LOW_WATER_LINE: 30, - // TODO: Remove this when useBufferWaterLines is removed + // TODO: Remove this when experimentalBufferBasedABR is removed EXPERIMENTAL_MAX_BUFFER_LOW_WATER_LINE: 16, BUFFER_LOW_WATER_LINE_RATE: 1, diff --git a/src/master-playlist-controller.js b/src/master-playlist-controller.js index 9486ce127..36ec729af 100644 --- a/src/master-playlist-controller.js +++ b/src/master-playlist-controller.js @@ -643,6 +643,8 @@ export class MasterPlaylistController extends videojs.EventTarget { return; } + this.delegateLoaders_('all', ['abort']); + this.blacklistCurrentPlaylist({ message: 'Aborted early because there isn\'t enough bandwidth to complete the ' + 'request without rebuffering.' From 56592bc93b6be3ea94e9de65dbef51f557c1df4a Mon Sep 17 00:00:00 2001 From: Brandon Casey <2381475+brandonocasey@users.noreply.github.com> Date: Thu, 19 Nov 2020 10:56:28 -0500 Subject: [PATCH 027/399] refactor: Add a better distinction between master and child dash loaders (#992) --- src/dash-playlist-loader.js | 131 ++++++++++++------------------ test/dash-playlist-loader.test.js | 37 +-------- 2 files changed, 56 insertions(+), 112 deletions(-) diff --git a/src/dash-playlist-loader.js b/src/dash-playlist-loader.js index 39550cb7a..64c513fec 100644 --- a/src/dash-playlist-loader.js +++ b/src/dash-playlist-loader.js @@ -252,6 +252,11 @@ export default class DashPlaylistLoader extends EventTarget { constructor(srcUrlOrPlaylist, vhs, options = { }, masterPlaylistLoader) { super(); + if (!masterPlaylistLoader) { + this.masterPlaylistLoader_ = this; + this.isMaster_ = true; + } + const { withCredentials = false, handleManifestRedirects = false } = options; this.vhs_ = vhs; @@ -277,20 +282,15 @@ export default class DashPlaylistLoader extends EventTarget { // initialize the loader state // The masterPlaylistLoader will be created with a string - if (typeof srcUrlOrPlaylist === 'string') { + if (this.isMaster_) { this.srcUrl = srcUrlOrPlaylist; // TODO: reset sidxMapping between period changes // once multi-period is refactored - this.sidxMapping_ = {}; - return; + this.masterPlaylistLoader_.sidxMapping_ = {}; + } else { + this.masterPlaylistLoader_ = masterPlaylistLoader; + this.childPlaylist_ = srcUrlOrPlaylist; } - - this.setupChildLoader(masterPlaylistLoader, srcUrlOrPlaylist); - } - - setupChildLoader(masterPlaylistLoader, playlist) { - this.masterPlaylistLoader_ = masterPlaylistLoader; - this.childPlaylist_ = playlist; } dispose() { @@ -414,20 +414,10 @@ export default class DashPlaylistLoader extends EventTarget { return; } - // we have sidx mappings - let oldMaster; - let sidxMapping; - // sidxMapping is used when parsing the masterXml, so store // it on the masterPlaylistLoader - if (this.masterPlaylistLoader_) { - oldMaster = this.masterPlaylistLoader_.master; - sidxMapping = this.masterPlaylistLoader_.sidxMapping_; - } else { - oldMaster = this.master; - sidxMapping = this.sidxMapping_; - } - + const oldMaster = this.masterPlaylistLoader_.master; + const sidxMapping = this.masterPlaylistLoader_.sidxMapping_; const sidxKey = generateSidxKey(playlist.sidx); sidxMapping[sidxKey] = { @@ -518,7 +508,7 @@ export default class DashPlaylistLoader extends EventTarget { // We don't need to request the master manifest again // Call this asynchronously to match the xhr request behavior below - if (this.masterPlaylistLoader_) { + if (!this.isMaster_) { this.mediaRequest_ = window.setTimeout( this.haveMaster_.bind(this), 0 @@ -528,7 +518,7 @@ export default class DashPlaylistLoader extends EventTarget { // request the specified URL this.request = this.vhs_.xhr({ - uri: this.srcUrl, + uri: this.masterPlaylistLoader_.srcUrl, withCredentials: this.withCredentials }, (error, req) => { // disposed @@ -542,7 +532,7 @@ export default class DashPlaylistLoader extends EventTarget { if (error) { this.error = { status: req.status, - message: 'DASH playlist request error at URL: ' + this.srcUrl, + message: 'DASH playlist request error at URL: ' + this.masterPlaylistLoader_.srcUrl, responseText: req.responseText, // MEDIA_ERR_NETWORK code: 2 @@ -553,7 +543,7 @@ export default class DashPlaylistLoader extends EventTarget { return this.trigger('error'); } - this.masterXml_ = req.responseText; + this.masterPlaylistLoader_.masterXml_ = req.responseText; if (req.responseHeaders && req.responseHeaders.date) { this.masterLoaded_ = Date.parse(req.responseHeaders.date); @@ -561,7 +551,7 @@ export default class DashPlaylistLoader extends EventTarget { this.masterLoaded_ = Date.now(); } - this.srcUrl = resolveManifestRedirect(this.handleManifestRedirects, this.srcUrl, req); + this.masterPlaylistLoader_.srcUrl = resolveManifestRedirect(this.handleManifestRedirects, this.masterPlaylistLoader_.srcUrl, req); this.syncClientServerClock_(this.onClientServerClockSync_.bind(this)); }); @@ -575,22 +565,22 @@ export default class DashPlaylistLoader extends EventTarget { * Function to call when clock sync has completed */ syncClientServerClock_(done) { - const utcTiming = parseUTCTiming(this.masterXml_); + const utcTiming = parseUTCTiming(this.masterPlaylistLoader_.masterXml_); // No UTCTiming element found in the mpd. Use Date header from mpd request as the // server clock if (utcTiming === null) { - this.clientOffset_ = this.masterLoaded_ - Date.now(); + this.masterPlaylistLoader_.clientOffset_ = this.masterLoaded_ - Date.now(); return done(); } if (utcTiming.method === 'DIRECT') { - this.clientOffset_ = utcTiming.value - Date.now(); + this.masterPlaylistLoader_.clientOffset_ = utcTiming.value - Date.now(); return done(); } this.request = this.vhs_.xhr({ - uri: resolveUrl(this.srcUrl, utcTiming.value), + uri: resolveUrl(this.masterPlaylistLoader_.srcUrl, utcTiming.value), method: utcTiming.method, withCredentials: this.withCredentials }, (error, req) => { @@ -602,7 +592,7 @@ export default class DashPlaylistLoader extends EventTarget { if (error) { // sync request failed, fall back to using date header from mpd // TODO: log warning - this.clientOffset_ = this.masterLoaded_ - Date.now(); + this.masterPlaylistLoader_.clientOffset_ = this.masterLoaded_ - Date.now(); return done(); } @@ -620,7 +610,7 @@ export default class DashPlaylistLoader extends EventTarget { serverTime = Date.parse(req.responseText); } - this.clientOffset_ = serverTime - Date.now(); + this.masterPlaylistLoader_.clientOffset_ = serverTime - Date.now(); done(); }); @@ -631,12 +621,12 @@ export default class DashPlaylistLoader extends EventTarget { // clear media request this.mediaRequest_ = null; - if (!this.masterPlaylistLoader_) { + if (this.isMaster_) { this.updateMainManifest_(parseMasterXml({ - masterXml: this.masterXml_, - srcUrl: this.srcUrl, - clientOffset: this.clientOffset_, - sidxMapping: this.sidxMapping_ + masterXml: this.masterPlaylistLoader_.masterXml_, + srcUrl: this.masterPlaylistLoader_.srcUrl, + clientOffset: this.masterPlaylistLoader_.clientOffset_, + sidxMapping: this.masterPlaylistLoader_.sidxMapping_ })); // We have the master playlist at this point, so // trigger this to allow MasterPlaylistController @@ -710,8 +700,8 @@ export default class DashPlaylistLoader extends EventTarget { const location = this.master.locations[0]; - if (location !== this.srcUrl) { - this.srcUrl = location; + if (location !== this.masterPlaylistLoader_.srcUrl) { + this.masterPlaylistLoader_.srcUrl = location; } } @@ -723,7 +713,7 @@ export default class DashPlaylistLoader extends EventTarget { // The srcUrl here *may* need to pass through handleManifestsRedirects when // sidx is implemented this.request = this.vhs_.xhr({ - uri: this.srcUrl, + uri: this.masterPlaylistLoader_.srcUrl, withCredentials: this.withCredentials }, (error, req) => { // disposed @@ -737,7 +727,7 @@ export default class DashPlaylistLoader extends EventTarget { if (error) { this.error = { status: req.status, - message: 'DASH playlist request error at URL: ' + this.srcUrl, + message: 'DASH playlist request error at URL: ' + this.masterPlaylistLoader_.srcUrl, responseText: req.responseText, // MEDIA_ERR_NETWORK code: 2 @@ -748,21 +738,21 @@ export default class DashPlaylistLoader extends EventTarget { return this.trigger('error'); } - this.masterXml_ = req.responseText; + this.masterPlaylistLoader_.masterXml_ = req.responseText; // This will filter out updated sidx info from the mapping - this.sidxMapping_ = filterChangedSidxMappings( - this.masterXml_, - this.srcUrl, - this.clientOffset_, - this.sidxMapping_ + this.masterPlaylistLoader_.sidxMapping_ = filterChangedSidxMappings( + this.masterPlaylistLoader_.masterXml_, + this.masterPlaylistLoader_.srcUrl, + this.masterPlaylistLoader_.clientOffset_, + this.masterPlaylistLoader_.sidxMapping_ ); const master = parseMasterXml({ - masterXml: this.masterXml_, - srcUrl: this.srcUrl, - clientOffset: this.clientOffset_, - sidxMapping: this.sidxMapping_ + masterXml: this.masterPlaylistLoader_.masterXml_, + srcUrl: this.masterPlaylistLoader_.srcUrl, + clientOffset: this.masterPlaylistLoader_.clientOffset_, + sidxMapping: this.masterPlaylistLoader_.sidxMapping_ }); const updatedMaster = updateMaster(this.master, master); const currentSidxInfo = this.media().sidx; @@ -772,7 +762,7 @@ export default class DashPlaylistLoader extends EventTarget { const sidxKey = generateSidxKey(currentSidxInfo); // the sidx was updated, so the previous mapping was removed - if (!this.sidxMapping_[sidxKey]) { + if (!this.masterPlaylistLoader_.sidxMapping_[sidxKey]) { const playlist = this.media(); this.request = requestSidx_( @@ -787,7 +777,7 @@ export default class DashPlaylistLoader extends EventTarget { } // update loader's sidxMapping with parsed sidx box - this.sidxMapping_[sidxKey].sidx = sidx; + this.masterPlaylistLoader_.sidxMapping_[sidxKey].sidx = sidx; this.updateMinimumUpdatePeriodTimeout_(); @@ -820,35 +810,18 @@ export default class DashPlaylistLoader extends EventTarget { throw new Error('refreshMedia_ must take a media id'); } - let oldMaster; - let newMaster; - - if (this.masterPlaylistLoader_) { - oldMaster = this.masterPlaylistLoader_.master; - newMaster = parseMasterXml({ - masterXml: this.masterPlaylistLoader_.masterXml_, - srcUrl: this.masterPlaylistLoader_.srcUrl, - clientOffset: this.masterPlaylistLoader_.clientOffset_, - sidxMapping: this.masterPlaylistLoader_.sidxMapping_ - }); - } else { - oldMaster = this.master; - newMaster = parseMasterXml({ - masterXml: this.masterXml_, - srcUrl: this.srcUrl, - clientOffset: this.clientOffset_, - sidxMapping: this.sidxMapping_ - }); - } + const oldMaster = this.masterPlaylistLoader_.master; + const newMaster = parseMasterXml({ + masterXml: this.masterPlaylistLoader_.masterXml_, + srcUrl: this.masterPlaylistLoader_.srcUrl, + clientOffset: this.masterPlaylistLoader_.clientOffset_, + sidxMapping: this.masterPlaylistLoader_.sidxMapping_ + }); const updatedMaster = updateMaster(oldMaster, newMaster); if (updatedMaster) { - if (this.masterPlaylistLoader_) { - this.masterPlaylistLoader_.master = updatedMaster; - } else { - this.master = updatedMaster; - } + this.masterPlaylistLoader_.master = updatedMaster; this.media_ = updatedMaster.playlists[mediaID]; } else { this.media_ = oldMaster.playlists[mediaID]; diff --git a/test/dash-playlist-loader.test.js b/test/dash-playlist-loader.test.js index bf53eae5a..9551f5d52 100644 --- a/test/dash-playlist-loader.test.js +++ b/test/dash-playlist-loader.test.js @@ -658,7 +658,8 @@ QUnit.test('constructor sets srcUrl and other properties', function(assert) { assert.strictEqual(loader.state, 'HAVE_NOTHING', 'correct state'); assert.deepEqual(loader.loadedPlaylists_, {}, 'correct loadedPlaylist state'); - assert.notOk(loader.masterPlaylistLoader_, 'should be no masterPlaylistLoader'); + assert.equal(loader.masterPlaylistLoader_, loader, 'masterPlaylistLoader should be self'); + assert.ok(loader.isMaster_, 'should be set as master'); assert.notOk(loader.childPlaylist_, 'should be no childPlaylist_'); assert.strictEqual(loader.srcUrl, 'dash.mpd', 'set the srcUrl'); @@ -667,6 +668,8 @@ QUnit.test('constructor sets srcUrl and other properties', function(assert) { assert.strictEqual(childLoader.state, 'HAVE_NOTHING', 'correct state'); assert.deepEqual(childLoader.loadedPlaylists_, {}, 'correct loadedPlaylist state'); assert.ok(childLoader.masterPlaylistLoader_, 'should be a masterPlaylistLoader'); + assert.notEqual(childLoader.masterPlaylistLoader_, childLoader, 'should not be a masterPlaylistLoader'); + assert.notOk(childLoader.isMaster_, 'should not be master'); assert.deepEqual( childLoader.childPlaylist_, {}, 'should be a childPlaylist_' @@ -1842,38 +1845,6 @@ QUnit.test('sidxRequestFinished_: uses given error object', function(assert) { assert.strictEqual(errors, 1, 'triggered an error event'); }); -QUnit.test('setupChildLoader: sets masterPlaylistLoader and ' + - 'playlist on child loader', function(assert) { - const fakePlaylist = { uri: 'fakeplaylist1', id: 'fakeplaylist1' }; - const newPlaylist = { uri: 'fakeplaylist2', id: 'fakeplaylist2' }; - const loader = new DashPlaylistLoader('dash.mpd', this.fakeVhs); - const newLoader = new DashPlaylistLoader('dash-sidx.mpd', this.fakeVhs); - const childLoader = new DashPlaylistLoader(fakePlaylist, this.fakeVhs, false, loader); - - assert.deepEqual( - childLoader.masterPlaylistLoader_, - loader, - 'starts with loader passed into constructor' - ); - assert.deepEqual( - childLoader.childPlaylist_, - fakePlaylist, - 'starts with playlist passed in constructor' - ); - - childLoader.setupChildLoader(newLoader, newPlaylist); - assert.deepEqual( - childLoader.masterPlaylistLoader_, - newLoader, - 'masterPlaylistLoader correctly set' - ); - assert.deepEqual( - childLoader.childPlaylist_, - newPlaylist, - 'child playlist correctly set' - ); -}); - QUnit.test('hasPendingRequest: returns true if async code is running in master loader', function(assert) { const loader = new DashPlaylistLoader('dash.mpd', this.fakeVhs); From 6db2b6a9e5a55294b8bf242cf74ea57c3207c24e Mon Sep 17 00:00:00 2001 From: Alex Barstow Date: Thu, 19 Nov 2020 14:59:54 -0500 Subject: [PATCH 028/399] fix: remove duplicate cues with same time interval and text (#1005) --- src/util/text-tracks.js | 40 ++++++++++++++++++- src/vtt-segment-loader.js | 12 ++++-- test/text-tracks.test.js | 84 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 131 insertions(+), 5 deletions(-) diff --git a/src/util/text-tracks.js b/src/util/text-tracks.js index be57deecb..f130e7b1a 100644 --- a/src/util/text-tracks.js +++ b/src/util/text-tracks.js @@ -240,9 +240,47 @@ export const removeCuesFromTrack = function(start, end, track) { while (i--) { cue = track.cues[i]; - // Remove any overlapping cue + // Remove any cue within the provided start and end time if (cue.startTime >= start && cue.endTime <= end) { track.removeCue(cue); } } }; + +/** + * Remove duplicate cues from a track on video.js (a cue is considered a + * duplicate if it has the same time interval and text as another) + * + * @param {Object} track the text track to remove the duplicate cues from + * @private + */ +export const removeDuplicateCuesFromTrack = function(track) { + const cues = track.cues; + + if (!cues) { + return; + } + + for (let i = 0; i < cues.length; i++) { + const duplicates = []; + let occurrences = 0; + + for (let j = 0; j < cues.length; j++) { + if ( + cues[i].startTime === cues[j].startTime && + cues[i].endTime === cues[j].endTime && + cues[i].text === cues[j].text + ) { + occurrences++; + + if (occurrences > 1) { + duplicates.push(cues[j]); + } + } + } + + if (duplicates.length) { + duplicates.forEach(dupe => track.removeCue(dupe)); + } + } +}; diff --git a/src/vtt-segment-loader.js b/src/vtt-segment-loader.js index 933b7805c..8edca0a57 100644 --- a/src/vtt-segment-loader.js +++ b/src/vtt-segment-loader.js @@ -4,7 +4,7 @@ import SegmentLoader from './segment-loader'; import videojs from 'video.js'; import window from 'global/window'; -import { removeCuesFromTrack } from './util/text-tracks'; +import { removeCuesFromTrack, removeDuplicateCuesFromTrack } from './util/text-tracks'; import { initSegmentId } from './bin-utils'; import { uint8ToUtf8 } from './util/string'; import { REQUEST_ERRORS } from './media-segment-request'; @@ -364,14 +364,20 @@ export default class VTTSegmentLoader extends SegmentLoader { this.mediaSecondsLoaded += segment.duration; + // Create VTTCue instances for each cue in the new segment and add them to + // the subtitle track segmentInfo.cues.forEach((cue) => { - // remove any overlapping cues to prevent doubling - this.remove(cue.startTime, cue.endTime); this.subtitlesTrack_.addCue(this.featuresNativeTextTracks_ ? new window.VTTCue(cue.startTime, cue.endTime, cue.text) : cue); }); + // Remove any duplicate cues from the subtitle track. The WebVTT spec allows + // cues to have identical time-intervals, but if the text is also identical + // we can safely assume it is a duplicate that can be removed (ex. when a cue + // "overlaps" VTT segments) + removeDuplicateCuesFromTrack(this.subtitlesTrack_); + this.handleAppendsDone_(); } diff --git a/test/text-tracks.test.js b/test/text-tracks.test.js index 1500db70a..97ab0cbc2 100644 --- a/test/text-tracks.test.js +++ b/test/text-tracks.test.js @@ -4,7 +4,8 @@ import { createCaptionsTrackIfNotExists, addCaptionData, createMetadataTrackIfNotExists, - addMetadata + addMetadata, + removeDuplicateCuesFromTrack } from '../src/util/text-tracks'; const { module, test } = Qunit; @@ -16,6 +17,11 @@ class MockTextTrack { addCue(cue) { this.cues.push(cue); } + removeCue(cue) { + const cueIndex = this.cues.map(c => c.text).indexOf(cue.text); + + this.cues.splice(cueIndex, 1); + } } class MockTech { @@ -302,3 +308,79 @@ test('adds cues for each metadata frame seen', function(assert) { 'ended at duration 20' ); }); + +test('removeDuplicateCuesFromTrack removes all but one cue with identical startTime, endTime, and text', function(assert) { + const track = new MockTextTrack(); + + [{ + startTime: 0, + endTime: 1, + text: 'CC1 text' + }, { + startTime: 1, + endTime: 2, + text: 'Identical' + }, { + startTime: 1, + endTime: 2, + text: 'Identical' + }, { + startTime: 1, + endTime: 2, + text: 'Identical' + }, { + startTime: 1, + endTime: 2, + text: 'Identical' + }, { + startTime: 2, + endTime: 3, + text: 'CC3 text' + }].forEach((mockCue) => { + track.addCue(mockCue); + }); + + assert.equal(track.cues.length, 6, '6 cues present initially'); + + removeDuplicateCuesFromTrack(track); + + assert.equal(track.cues.length, 3, '3 cue remains after duplicates removed'); +}); + +test('removeDuplicateCuesFromTrack leaves in cues with the same startTime and endTime, but different text-- or vice-versa', function(assert) { + const track = new MockTextTrack(); + + [{ + startTime: 0, + endTime: 1, + text: 'Identical' + }, { + startTime: 0, + endTime: 1, + text: 'Identical' + }, { + startTime: 0, + endTime: 1, + text: 'CC2 text' + }, { + startTime: 0, + endTime: 1, + text: 'CC3 text' + }, { + startTime: 1, + endTime: 2, + text: 'Also identical' + }, { + startTime: 1, + endTime: 2, + text: 'Also identical' + }].forEach((mockCue) => { + track.addCue(mockCue); + }); + + assert.equal(track.cues.length, 6, '6 cues present initially'); + + removeDuplicateCuesFromTrack(track); + + assert.equal(track.cues.length, 4, '4 cues remain after duplicates removed'); +}); From d13b7376946d513800d2dc79e889aa46c61f18c5 Mon Sep 17 00:00:00 2001 From: Gary Katsevman Date: Thu, 19 Nov 2020 15:27:41 -0500 Subject: [PATCH 029/399] chore: don't run tests on release (#1006) --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 497afbcd1..ba4bbf1ca 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,6 @@ "start": "npm-run-all -p server watch", "server": "karma start scripts/karma.conf.js --singleRun=false --auto-watch", "test": "npm-run-all lint build-test && karma start scripts/karma.conf.js", - "preversion": "npm test", "version": "is-prerelease || npm run update-changelog && git add CHANGELOG.md", "update-changelog": "conventional-changelog -p videojs -i CHANGELOG.md -s", "watch": "npm-run-all -p watch:*", From e41f8562845ffdc7f80b219d44930590dd7c79b4 Mon Sep 17 00:00:00 2001 From: Brandon Casey <2381475+brandonocasey@users.noreply.github.com> Date: Fri, 20 Nov 2020 12:31:17 -0500 Subject: [PATCH 030/399] refactor: add sidx segments to playlist object instead of re-parsing xml (#994) --- package-lock.json | 19 ++- package.json | 2 +- src/dash-playlist-loader.js | 233 +++++++++++++++--------------- test/dash-playlist-loader.test.js | 28 ++-- 4 files changed, 150 insertions(+), 132 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7f613a542..2ee6d8f3d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1284,6 +1284,19 @@ "mpd-parser": "0.14.0", "mux.js": "5.6.7", "video.js": "^6 || ^7" + }, + "dependencies": { + "mpd-parser": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/mpd-parser/-/mpd-parser-0.14.0.tgz", + "integrity": "sha512-HqXQS3WLofcnYFcxv5oWdlciddUaEnN3NasXLVQ793mdnZRrinjz2Yk1DsUYPDYOUWf6ZBBqbFhaJT5LiT2ouA==", + "requires": { + "@babel/runtime": "^7.5.5", + "@videojs/vhs-utils": "^2.2.1", + "global": "^4.3.2", + "xmldom": "^0.1.27" + } + } } }, "@videojs/vhs-utils": { @@ -7131,9 +7144,9 @@ "dev": true }, "mpd-parser": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/mpd-parser/-/mpd-parser-0.14.0.tgz", - "integrity": "sha512-HqXQS3WLofcnYFcxv5oWdlciddUaEnN3NasXLVQ793mdnZRrinjz2Yk1DsUYPDYOUWf6ZBBqbFhaJT5LiT2ouA==", + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/mpd-parser/-/mpd-parser-0.15.0.tgz", + "integrity": "sha512-GfspJVaEnVbWKZQASvh9nsJkvxWh3M/c5Kb2RPnN5ZXPZ7jWWfarWkNKTEuqvoaAKIT8IB/r6PFTWA1GY4fzGg==", "requires": { "@babel/runtime": "^7.5.5", "@videojs/vhs-utils": "^2.2.1", diff --git a/package.json b/package.json index ba4bbf1ca..0a5a9451b 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "aes-decrypter": "3.1.0", "global": "^4.3.2", "m3u8-parser": "4.5.0", - "mpd-parser": "0.14.0", + "mpd-parser": "0.15.0", "mux.js": "5.6.7", "video.js": "^6 || ^7" }, diff --git a/src/dash-playlist-loader.js b/src/dash-playlist-loader.js index 64c513fec..4fef31e62 100644 --- a/src/dash-playlist-loader.js +++ b/src/dash-playlist-loader.js @@ -1,6 +1,7 @@ import videojs from 'video.js'; import { parse as parseMpd, + addSidxSegmentsToPlaylist, parseUTCTiming } from 'mpd-parser'; import { @@ -48,6 +49,18 @@ export const parseMasterXml = ({ masterXml, srcUrl, clientOffset, sidxMapping }) return master; }; +export const generateSidxKey = (sidxInfo) => { + // should be non-inclusive + const sidxByteRangeEnd = + sidxInfo.byterange.offset + + sidxInfo.byterange.length - + 1; + + return sidxInfo.uri + '-' + + sidxInfo.byterange.offset + '-' + + sidxByteRangeEnd; +}; + /** * Returns a new master manifest that is the result of merging an updated master manifest * into the original version. @@ -60,7 +73,7 @@ export const parseMasterXml = ({ masterXml, srcUrl, clientOffset, sidxMapping }) * A new object representing the original master manifest with the updated media * playlists merged in */ -export const updateMaster = (oldMaster, newMaster) => { +export const updateMaster = (oldMaster, newMaster, sidxMapping) => { let noChanges = true; let update = mergeOptions(oldMaster, { // These are top level properties that can be updated @@ -70,7 +83,16 @@ export const updateMaster = (oldMaster, newMaster) => { // First update the playlists in playlist list for (let i = 0; i < newMaster.playlists.length; i++) { - const playlistUpdate = updatePlaylist(update, newMaster.playlists[i]); + const playlist = newMaster.playlists[i]; + + if (playlist.sidx) { + const sidxKey = generateSidxKey(playlist.sidx); + + if (sidxMapping && sidxMapping[sidxKey]) { + addSidxSegmentsToPlaylist(playlist, sidxMapping[sidxKey].sidx, playlist.sidx.resolvedUri); + } + } + const playlistUpdate = updatePlaylist(update, playlist); if (playlistUpdate) { update = playlistUpdate; @@ -104,18 +126,6 @@ export const updateMaster = (oldMaster, newMaster) => { return update; }; -export const generateSidxKey = (sidxInfo) => { - // should be non-inclusive - const sidxByteRangeEnd = - sidxInfo.byterange.offset + - sidxInfo.byterange.length - - 1; - - return sidxInfo.uri + '-' + - sidxInfo.byterange.offset + '-' + - sidxByteRangeEnd; -}; - // SIDX should be equivalent if the URI and byteranges of the SIDX match. // If the SIDXs have maps, the two maps should match, // both `a` and `b` missing SIDXs is considered matching. @@ -164,18 +174,10 @@ export const compareSidxEntry = (playlists, oldSidxMapping) => { * * The method is exported for testing * - * @param {Object} masterXml the mpd XML - * @param {string} srcUrl the mpd url - * @param {Date} clientOffset a time difference between server and client (passed through and not used) + * @param {Object} master the parsed mpd XML returned via mpd-parser * @param {Object} oldSidxMapping the SIDX to compare against */ -export const filterChangedSidxMappings = (masterXml, srcUrl, clientOffset, oldSidxMapping) => { - // Don't pass current sidx mapping - const master = parseMpd(masterXml, { - manifestUri: srcUrl, - clientOffset - }); - +export const filterChangedSidxMappings = (master, oldSidxMapping) => { const videoSidx = compareSidxEntry(master.playlists, oldSidxMapping); let mediaGroupSidx = videoSidx; @@ -438,10 +440,12 @@ export default class DashPlaylistLoader extends EventTarget { // update loader's sidxMapping with parsed sidx box sidxMapping[sidxKey].sidx = sidx; + addSidxSegmentsToPlaylist(playlist, sidx, playlist.sidx.resolvedUri); + // everything is ready just continue to haveMetadata this.haveMetadata({ startingState, - playlist: newMaster.playlists[playlist.id] + playlist }); }) ); @@ -509,10 +513,7 @@ export default class DashPlaylistLoader extends EventTarget { // We don't need to request the master manifest again // Call this asynchronously to match the xhr request behavior below if (!this.isMaster_) { - this.mediaRequest_ = window.setTimeout( - this.haveMaster_.bind(this), - 0 - ); + this.mediaRequest_ = window.setTimeout(() => this.haveMaster_(false), 0); return; } @@ -543,6 +544,10 @@ export default class DashPlaylistLoader extends EventTarget { return this.trigger('error'); } + if (req.responseText === this.masterPlaylistLoader_.masterXml_) { + return this.haveMaster_(false); + } + this.masterPlaylistLoader_.masterXml_ = req.responseText; if (req.responseHeaders && req.responseHeaders.date) { @@ -616,18 +621,12 @@ export default class DashPlaylistLoader extends EventTarget { }); } - haveMaster_() { + haveMaster_(masterChanged = true) { this.state = 'HAVE_MASTER'; - // clear media request - this.mediaRequest_ = null; - if (this.isMaster_) { - this.updateMainManifest_(parseMasterXml({ - masterXml: this.masterPlaylistLoader_.masterXml_, - srcUrl: this.masterPlaylistLoader_.srcUrl, - clientOffset: this.masterPlaylistLoader_.clientOffset_, - sidxMapping: this.masterPlaylistLoader_.sidxMapping_ - })); + if (masterChanged) { + this.handleMaster_(); + } // We have the master playlist at this point, so // trigger this to allow MasterPlaylistController // to make an initial playlist selection @@ -639,6 +638,37 @@ export default class DashPlaylistLoader extends EventTarget { } } + handleMaster_() { + // clear media request + this.mediaRequest_ = null; + + let newMaster = parseMasterXml({ + masterXml: this.masterPlaylistLoader_.masterXml_, + srcUrl: this.masterPlaylistLoader_.srcUrl, + clientOffset: this.masterPlaylistLoader_.clientOffset_, + sidxMapping: this.masterPlaylistLoader_.sidxMapping_ + }); + + // if we have an old master to compare the new master against + if (this.masterPlaylistLoader_.master) { + newMaster = updateMaster( + this.masterPlaylistLoader_.master, + newMaster, + this.masterPlaylistLoader_.sidxMapping_ + ); + } + + // only update master if we have a new master + this.masterPlaylistLoader_.master = newMaster ? newMaster : this.masterPlaylistLoader_.master; + const location = this.masterPlaylistLoader_.master.locations && this.masterPlaylistLoader_.master.locations[0]; + + if (location && location !== this.masterPlaylistLoader_.srcUrl) { + this.masterPlaylistLoader_.srcUrl = location; + } + + return Boolean(newMaster); + } + updateMinimumUpdatePeriodTimeout_() { // Clear existing timeout window.clearTimeout(this.minimumUpdatePeriodTimeout_); @@ -685,26 +715,6 @@ export default class DashPlaylistLoader extends EventTarget { this.updateMinimumUpdatePeriodTimeout_(); } - /** - * Given a new manifest, update our pointer to it and update the srcUrl based on the location elements of the manifest, if they exist. - * - * @param {Object} updatedManifest the manifest to update to - */ - updateMainManifest_(updatedManifest) { - this.master = updatedManifest; - - // if locations isn't set or is an empty array, exit early - if (!this.master.locations || !this.master.locations.length) { - return; - } - - const location = this.master.locations[0]; - - if (location !== this.masterPlaylistLoader_.srcUrl) { - this.masterPlaylistLoader_.srcUrl = location; - } - } - /** * Sends request to refresh the master xml and updates the parsed master manifest * TODO: Does the client offset need to be recalculated when the xml is refreshed? @@ -738,65 +748,63 @@ export default class DashPlaylistLoader extends EventTarget { return this.trigger('error'); } + // xml is the same do nothing. + if (req.responseText === this.masterPlaylistLoader_.masterXml_) { + return; + } + this.masterPlaylistLoader_.masterXml_ = req.responseText; + this.handleMaster_(); // This will filter out updated sidx info from the mapping this.masterPlaylistLoader_.sidxMapping_ = filterChangedSidxMappings( - this.masterPlaylistLoader_.masterXml_, - this.masterPlaylistLoader_.srcUrl, - this.masterPlaylistLoader_.clientOffset_, + this.masterPlaylistLoader_.master, this.masterPlaylistLoader_.sidxMapping_ ); - - const master = parseMasterXml({ - masterXml: this.masterPlaylistLoader_.masterXml_, - srcUrl: this.masterPlaylistLoader_.srcUrl, - clientOffset: this.masterPlaylistLoader_.clientOffset_, - sidxMapping: this.masterPlaylistLoader_.sidxMapping_ - }); - const updatedMaster = updateMaster(this.master, master); const currentSidxInfo = this.media().sidx; - if (updatedMaster) { - if (currentSidxInfo) { - const sidxKey = generateSidxKey(currentSidxInfo); + if (this.media_) { + this.media_ = this.master.playlists[this.media_.id]; + } - // the sidx was updated, so the previous mapping was removed - if (!this.masterPlaylistLoader_.sidxMapping_[sidxKey]) { - const playlist = this.media(); + this.updateMinimumUpdatePeriodTimeout_(); + // current sidx not updated + if (!currentSidxInfo) { + return; + } + const sidxKey = generateSidxKey(currentSidxInfo); - this.request = requestSidx_( - this, - playlist.sidx, - playlist, - this.vhs_.xhr, - { handleManifestRedirects: this.handleManifestRedirects }, - this.sidxRequestFinished_(playlist, master, this.state, (newMaster, sidx) => { - if (!newMaster || !sidx) { - throw new Error('failed to request sidx on minimumUpdatePeriod'); - } + // sidxKey already exists + if (this.masterPlaylistLoader_.sidxMapping_[sidxKey]) { + return; + } + const playlist = this.media(); - // update loader's sidxMapping with parsed sidx box - this.masterPlaylistLoader_.sidxMapping_[sidxKey].sidx = sidx; + this.request = requestSidx_( + this, + playlist.sidx, + playlist, + this.vhs_.xhr, + { handleManifestRedirects: this.handleManifestRedirects }, + this.sidxRequestFinished_(playlist, this.masterPlaylistLoader_.master, this.state, (newMaster, sidx) => { + if (!newMaster || !sidx) { + throw new Error('failed to request sidx on minimumUpdatePeriod'); + } - this.updateMinimumUpdatePeriodTimeout_(); + // update loader's sidxMapping with parsed sidx box + this.masterPlaylistLoader_.sidxMapping_[sidxKey].sidx = sidx; - // TODO: do we need to reload the current playlist? - this.refreshMedia_(this.media().id); + addSidxSegmentsToPlaylist(playlist, sidx, playlist.sidx.resolvedUri); - return; - }) - ); - } - } else { - this.updateMainManifest_(updatedMaster); - if (this.media_) { - this.media_ = this.master.playlists[this.media_.id]; - } - } - } + this.updateMinimumUpdatePeriodTimeout_(); + + // TODO: do we need to reload the current playlist? + this.refreshMedia_(this.media().id); + + return; + }) + ); - this.updateMinimumUpdatePeriodTimeout_(); }); } @@ -810,28 +818,21 @@ export default class DashPlaylistLoader extends EventTarget { throw new Error('refreshMedia_ must take a media id'); } - const oldMaster = this.masterPlaylistLoader_.master; - const newMaster = parseMasterXml({ - masterXml: this.masterPlaylistLoader_.masterXml_, - srcUrl: this.masterPlaylistLoader_.srcUrl, - clientOffset: this.masterPlaylistLoader_.clientOffset_, - sidxMapping: this.masterPlaylistLoader_.sidxMapping_ - }); + this.handleMaster_(); - const updatedMaster = updateMaster(oldMaster, newMaster); + const playlists = this.masterPlaylistLoader_.master.playlists; + const mediaChanged = !this.media_ || this.media_ !== playlists[mediaID]; - if (updatedMaster) { - this.masterPlaylistLoader_.master = updatedMaster; - this.media_ = updatedMaster.playlists[mediaID]; + if (mediaChanged) { + this.media_ = playlists[mediaID]; } else { - this.media_ = oldMaster.playlists[mediaID]; this.trigger('playlistunchanged'); } if (!this.media().endList) { this.mediaUpdateTimeout = window.setTimeout(() => { this.trigger('mediaupdatetimeout'); - }, refreshDelay(this.media(), !!updatedMaster)); + }, refreshDelay(this.media(), Boolean(mediaChanged))); } this.trigger('loadedplaylist'); diff --git a/test/dash-playlist-loader.test.js b/test/dash-playlist-loader.test.js index 9551f5d52..f9f85de15 100644 --- a/test/dash-playlist-loader.test.js +++ b/test/dash-playlist-loader.test.js @@ -467,7 +467,6 @@ QUnit.test('compareSidxEntry: will remove non-matching sidxes from a mapping', f QUnit.test('filterChangedSidxMappings: removes change sidx info from mapping', function(assert) { const loader = new DashPlaylistLoader('dash-sidx.mpd', this.fakeVhs); - let masterXml; loader.load(); this.standardXHRResponse(this.requests.shift()); @@ -482,9 +481,7 @@ QUnit.test('filterChangedSidxMappings: removes change sidx info from mapping', f const oldSidxMapping = loader.sidxMapping_; let newSidxMapping = filterChangedSidxMappings( - loader.masterXml_, - loader.srcUrl, - loader.clientOffset_, + loader.master, loader.sidxMapping_ ); @@ -497,12 +494,16 @@ QUnit.test('filterChangedSidxMappings: removes change sidx info from mapping', f const oldVideoKey = generateSidxKey(playlists['0-placeholder-uri-0'].sidx); const oldAudioEnKey = generateSidxKey(playlists['0-placeholder-uri-AUDIO-audio-en'].sidx); + let masterXml = loader.masterXml_.replace(/(indexRange)=\"\d+-\d+\"/, '$1="201-400"'); // should change the video playlist - masterXml = loader.masterXml_.replace(/(indexRange)=\"\d+-\d+\"/, '$1="201-400"'); - newSidxMapping = filterChangedSidxMappings( + let newMaster = parseMasterXml({ masterXml, - loader.srcUrl, - loader.clientOffset_, + srcUrl: loader.srcUrl, + clientOffset: loader.clientOffset_ + }); + + newSidxMapping = filterChangedSidxMappings( + newMaster, loader.sidxMapping_ ); const newVideoKey = `${playlists['0-placeholder-uri-0'].sidx.uri}-201-400`; @@ -521,11 +522,14 @@ QUnit.test('filterChangedSidxMappings: removes change sidx info from mapping', f ); // should change the English audio group - masterXml = masterXml.replace(/(indexRange)=\"\d+-\d+\"/g, '$1="201-400"'); - newSidxMapping = filterChangedSidxMappings( + masterXml = loader.masterXml_.replace(/(indexRange)=\"\d+-\d+\"/g, '$1="201-400"'); + newMaster = parseMasterXml({ masterXml, - loader.srcUrl, - loader.clientOffset_, + srcUrl: loader.srcUrl, + clientOffset: loader.clientOffset_ + }); + newSidxMapping = filterChangedSidxMappings( + newMaster, loader.sidxMapping_ ); assert.notOk( From 030469f876fe11e29015b0c2df0640be7476029e Mon Sep 17 00:00:00 2001 From: Brandon Casey <2381475+brandonocasey@users.noreply.github.com> Date: Mon, 23 Nov 2020 12:25:57 -0500 Subject: [PATCH 031/399] chore: add multiple soon-to-work sources (#1007) --- scripts/sources.json | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/scripts/sources.json b/scripts/sources.json index ae6c041d1..fde635c55 100644 --- a/scripts/sources.json +++ b/scripts/sources.json @@ -309,5 +309,35 @@ "uri": "https://d2zihajmogu5jn.cloudfront.net/demuxed-ts-with-audio-only-rendition/master.m3u8", "mimetype": "application/x-mpegurl", "features": [] + }, + { + "name": "(Not Working) sidx v1 dash", + "uri": "https://d2zihajmogu5jn.cloudfront.net/sidx-v1-dash/Dog.mpd", + "mimetype": "application/dash+xml", + "features": [] + }, + { + "name": "(Not Working) fmp4 x264/flac no manifest codecs", + "uri": "https://d2zihajmogu5jn.cloudfront.net/fmp4-flac-no-manifest-codecs/master.m3u8", + "mimetype": "application/x-mpegurl", + "features": [] + }, + { + "name": "(Not Working) fmp4 x264/opus no manifest codecs", + "uri": "https://d2zihajmogu5jn.cloudfront.net/fmp4-opus-no-manifest-codecs/master.m3u8", + "mimetype": "application/x-mpegurl", + "features": [] + }, + { + "name": "fmp4 h264/aac no manifest codecs", + "uri": "https://d2zihajmogu5jn.cloudfront.net/fmp4-muxed-no-playlist-codecs/index.m3u8", + "mimetype": "application/x-mpegurl", + "features": [] + }, + { + "name": "(Not Working) ts one valid codec among many invalid", + "uri": "https://d2zihajmogu5jn.cloudfront.net/ts-one-valid-many-invalid/master.m3u8", + "mimetype": "application/x-mpegurl", + "features": [] } ] From fe57e6017407ca33d3de6c465466fc68b037a999 Mon Sep 17 00:00:00 2001 From: Brandon Casey <2381475+brandonocasey@users.noreply.github.com> Date: Mon, 23 Nov 2020 13:59:45 -0500 Subject: [PATCH 032/399] refactor: unify sidx/master/error request logic (#998) --- src/dash-playlist-loader.js | 427 ++++++++++++------------------ test/dash-playlist-loader.test.js | 193 ++++---------- 2 files changed, 221 insertions(+), 399 deletions(-) diff --git a/src/dash-playlist-loader.js b/src/dash-playlist-loader.js index 4fef31e62..7a0772a12 100644 --- a/src/dash-playlist-loader.js +++ b/src/dash-playlist-loader.js @@ -195,58 +195,6 @@ export const filterChangedSidxMappings = (master, oldSidxMapping) => { return mediaGroupSidx; }; -// exported for testing -export const requestSidx_ = (loader, sidxRange, playlist, xhr, options, finishProcessingFn) => { - const sidxInfo = { - // resolve the segment URL relative to the playlist - uri: resolveManifestRedirect(options.handleManifestRedirects, sidxRange.resolvedUri), - // resolvedUri: sidxRange.resolvedUri, - byterange: sidxRange.byterange, - // the segment's playlist - playlist - }; - - const sidxRequestOptions = videojs.mergeOptions(sidxInfo, { - responseType: 'arraybuffer', - headers: segmentXhrHeaders(sidxInfo) - }); - - return containerRequest(sidxInfo.uri, xhr, (err, request, container, bytes) => { - if (err) { - return finishProcessingFn(err, request); - } - - if (!container || container !== 'mp4') { - return finishProcessingFn({ - status: request.status, - message: `Unsupported ${container || 'unknown'} container type for sidx segment at URL: ${sidxInfo.uri}`, - // response is just bytes in this case - // but we really don't want to return that. - response: '', - playlist, - internal: true, - blacklistDuration: Infinity, - // MEDIA_ERR_NETWORK - code: 2 - }, request); - } - - // if we already downloaded the sidx bytes in the container request, use them - const {offset, length} = sidxInfo.byterange; - - if (bytes.length >= (length + offset)) { - return finishProcessingFn(err, { - response: bytes.subarray(offset, offset + length), - status: request.status, - uri: request.uri - }); - } - - // otherwise request sidx bytes - loader.request = xhr(sidxRequestOptions, finishProcessingFn); - }); -}; - export default class DashPlaylistLoader extends EventTarget { // DashPlaylistLoader must accept either a src url or a playlist because subsequent // playlist loader setups from media groups will expect to be able to pass a playlist @@ -254,8 +202,8 @@ export default class DashPlaylistLoader extends EventTarget { constructor(srcUrlOrPlaylist, vhs, options = { }, masterPlaylistLoader) { super(); + this.masterPlaylistLoader_ = masterPlaylistLoader || this; if (!masterPlaylistLoader) { - this.masterPlaylistLoader_ = this; this.isMaster_ = true; } @@ -285,16 +233,119 @@ export default class DashPlaylistLoader extends EventTarget { // initialize the loader state // The masterPlaylistLoader will be created with a string if (this.isMaster_) { - this.srcUrl = srcUrlOrPlaylist; + this.masterPlaylistLoader_.srcUrl = srcUrlOrPlaylist; // TODO: reset sidxMapping between period changes // once multi-period is refactored this.masterPlaylistLoader_.sidxMapping_ = {}; } else { - this.masterPlaylistLoader_ = masterPlaylistLoader; this.childPlaylist_ = srcUrlOrPlaylist; } } + requestErrored_(err, request, startingState) { + // disposed + if (!this.request) { + return true; + } + + // pending request is cleared + this.request = null; + + if (err) { + // use the provided error object or create one + // based on the request/response + this.error = typeof err === 'object' && !(err instanceof Error) ? err : { + status: request.status, + message: 'DASH request error at URL: ' + request.uri, + response: request.response, + // MEDIA_ERR_NETWORK + code: 2 + }; + if (startingState) { + this.state = startingState; + } + + this.trigger('error'); + return true; + } + } + + /** + * Verify that the container of the sidx segment can be parsed + * and if it can, get and parse that segment. + */ + addSidxSegments_(playlist, startingState, cb) { + const sidxKey = playlist.sidx && generateSidxKey(playlist.sidx); + + // playlist lacks sidx or sidx segments were added to this playlist already. + if (!playlist.sidx || !sidxKey || this.masterPlaylistLoader_.sidxMapping_[sidxKey]) { + // keep this function async + this.mediaRequest_ = window.setTimeout(() => cb(false), 0); + return; + } + + // resolve the segment URL relative to the playlist + const uri = resolveManifestRedirect(this.handleManifestRedirects, playlist.sidx.resolvedUri); + const sidxMapping = this.masterPlaylistLoader_.sidxMapping_; + + sidxMapping[sidxKey] = { + sidxInfo: playlist.sidx + }; + + const fin = (err, request) => { + if (this.requestErrored_(err, request, startingState)) { + return; + } + + const sidx = parseSidx(toUint8(request.response).subarray(8)); + + sidxMapping[sidxKey].sidx = sidx; + + addSidxSegmentsToPlaylist(playlist, sidx, playlist.sidx.resolvedUri); + + return cb(true); + }; + + this.request = containerRequest(uri, this.vhs_.xhr, (err, request, container, bytes) => { + if (err) { + return fin(err, request); + } + + if (!container || container !== 'mp4') { + return fin({ + status: request.status, + message: `Unsupported ${container || 'unknown'} container type for sidx segment at URL: ${uri}`, + // response is just bytes in this case + // but we really don't want to return that. + response: '', + playlist, + internal: true, + blacklistDuration: Infinity, + // MEDIA_ERR_NETWORK + code: 2 + }, request); + } + + // if we already downloaded the sidx bytes in the container request, use them + const {offset, length} = playlist.sidx.byterange; + + if (bytes.length >= (length + offset)) { + return fin(err, { + response: bytes.subarray(offset, offset + length), + status: request.status, + uri: request.uri + }); + } + + // otherwise request sidx bytes + this.request = this.vhs_.xhr({ + uri, + responseType: 'arraybuffer', + headers: segmentXhrHeaders({byterange: playlist.sidx.byterange}) + }, fin); + }); + } + dispose() { this.trigger('dispose'); this.stopRequest(); @@ -320,42 +371,6 @@ export default class DashPlaylistLoader extends EventTarget { } } - sidxRequestFinished_(playlist, master, startingState, doneFn) { - return (err, request) => { - // disposed - if (!this.request) { - return; - } - - // pending request is cleared - this.request = null; - - if (err) { - // use the provided error or create one - // see requestSidx_ for the container request - // that can cause this. - this.error = typeof err === 'object' ? err : { - status: request.status, - message: 'DASH playlist request error at URL: ' + playlist.uri, - response: request.response, - // MEDIA_ERR_NETWORK - code: 2 - }; - if (startingState) { - this.state = startingState; - } - - this.trigger('error'); - return; - } - - const bytes = toUint8(request.response); - const sidx = parseSidx(bytes.subarray(8)); - - return doneFn(master, sidx); - }; - } - media(playlist) { // getter if (!playlist) { @@ -371,10 +386,10 @@ export default class DashPlaylistLoader extends EventTarget { // find the playlist object if the target playlist has been specified by URI if (typeof playlist === 'string') { - if (!this.master.playlists[playlist]) { + if (!this.masterPlaylistLoader_.master.playlists[playlist]) { throw new Error('Unknown playlist URI: ' + playlist); } - playlist = this.master.playlists[playlist]; + playlist = this.masterPlaylistLoader_.master.playlists[playlist]; } const mediaChange = !this.media_ || playlist.id !== this.media_.id; @@ -403,52 +418,10 @@ export default class DashPlaylistLoader extends EventTarget { if (this.media_) { this.trigger('mediachanging'); } - - if (!playlist.sidx) { - // Continue asynchronously if there is no sidx - // wait one tick to allow haveMaster to run first on a child loader - this.mediaRequest_ = window.setTimeout( - this.haveMetadata.bind(this, { startingState, playlist }), - 0 - ); - - // exit early and don't do sidx work - return; - } - - // sidxMapping is used when parsing the masterXml, so store - // it on the masterPlaylistLoader - const oldMaster = this.masterPlaylistLoader_.master; - const sidxMapping = this.masterPlaylistLoader_.sidxMapping_; - const sidxKey = generateSidxKey(playlist.sidx); - - sidxMapping[sidxKey] = { - sidxInfo: playlist.sidx - }; - - this.request = requestSidx_( - this, - playlist.sidx, - playlist, - this.vhs_.xhr, - { handleManifestRedirects: this.handleManifestRedirects }, - this.sidxRequestFinished_(playlist, oldMaster, startingState, (newMaster, sidx) => { - if (!newMaster || !sidx) { - throw new Error('failed to request sidx'); - } - - // update loader's sidxMapping with parsed sidx box - sidxMapping[sidxKey].sidx = sidx; - - addSidxSegmentsToPlaylist(playlist, sidx, playlist.sidx.resolvedUri); - - // everything is ready just continue to haveMetadata - this.haveMetadata({ - startingState, - playlist - }); - }) - ); + this.addSidxSegments_(playlist, startingState, (sidxChanged) => { + // everything is ready just continue to haveMetadata + this.haveMetadata({startingState, playlist}); + }); } haveMetadata({startingState, playlist}) { @@ -513,40 +486,32 @@ export default class DashPlaylistLoader extends EventTarget { // We don't need to request the master manifest again // Call this asynchronously to match the xhr request behavior below if (!this.isMaster_) { - this.mediaRequest_ = window.setTimeout(() => this.haveMaster_(false), 0); + this.mediaRequest_ = window.setTimeout(() => this.haveMaster_(), 0); return; } - // request the specified URL + this.requestMaster_((req, masterChanged) => { + this.haveMaster_(); + + if (!this.hasPendingRequest() && !this.media_) { + this.media(this.masterPlaylistLoader_.master.playlists[0]); + } + }); + } + + requestMaster_(cb) { this.request = this.vhs_.xhr({ uri: this.masterPlaylistLoader_.srcUrl, withCredentials: this.withCredentials }, (error, req) => { - // disposed - if (!this.request) { - return; - } - - // clear the loader's request reference - this.request = null; - - if (error) { - this.error = { - status: req.status, - message: 'DASH playlist request error at URL: ' + this.masterPlaylistLoader_.srcUrl, - responseText: req.responseText, - // MEDIA_ERR_NETWORK - code: 2 - }; + if (this.requestErrored_(error, req)) { if (this.state === 'HAVE_NOTHING') { this.started = false; } - return this.trigger('error'); + return; } - if (req.responseText === this.masterPlaylistLoader_.masterXml_) { - return this.haveMaster_(false); - } + const masterChanged = req.responseText !== this.masterPlaylistLoader_.masterXml_; this.masterPlaylistLoader_.masterXml_ = req.responseText; @@ -558,8 +523,17 @@ export default class DashPlaylistLoader extends EventTarget { this.masterPlaylistLoader_.srcUrl = resolveManifestRedirect(this.handleManifestRedirects, this.masterPlaylistLoader_.srcUrl, req); - this.syncClientServerClock_(this.onClientServerClockSync_.bind(this)); + if (masterChanged) { + this.handleMaster_(); + this.syncClientServerClock_(() => { + return cb(req, masterChanged); + }); + return; + } + + return cb(req, masterChanged); }); + } /** @@ -621,12 +595,9 @@ export default class DashPlaylistLoader extends EventTarget { }); } - haveMaster_(masterChanged = true) { + haveMaster_() { this.state = 'HAVE_MASTER'; if (this.isMaster_) { - if (masterChanged) { - this.handleMaster_(); - } // We have the master playlist at this point, so // trigger this to allow MasterPlaylistController // to make an initial playlist selection @@ -648,24 +619,26 @@ export default class DashPlaylistLoader extends EventTarget { clientOffset: this.masterPlaylistLoader_.clientOffset_, sidxMapping: this.masterPlaylistLoader_.sidxMapping_ }); + const oldMaster = this.masterPlaylistLoader_.master; // if we have an old master to compare the new master against - if (this.masterPlaylistLoader_.master) { - newMaster = updateMaster( - this.masterPlaylistLoader_.master, - newMaster, - this.masterPlaylistLoader_.sidxMapping_ - ); + if (oldMaster) { + newMaster = updateMaster(oldMaster, newMaster, this.masterPlaylistLoader_.sidxMapping_); } // only update master if we have a new master - this.masterPlaylistLoader_.master = newMaster ? newMaster : this.masterPlaylistLoader_.master; + this.masterPlaylistLoader_.master = newMaster ? newMaster : oldMaster; const location = this.masterPlaylistLoader_.master.locations && this.masterPlaylistLoader_.master.locations[0]; if (location && location !== this.masterPlaylistLoader_.srcUrl) { this.masterPlaylistLoader_.srcUrl = location; } + // if the minimumUpdatePeriod was changed, update the minimumUpdatePeriodTimeout_ + if (!oldMaster || (newMaster && oldMaster.minimumUpdatePeriod !== newMaster.minimumUpdatePeriod)) { + this.updateMinimumUpdatePeriodTimeout_(); + } + return Boolean(newMaster); } @@ -679,7 +652,7 @@ export default class DashPlaylistLoader extends EventTarget { }, mup); }; - const minimumUpdatePeriod = this.master && this.master.minimumUpdatePeriod; + const minimumUpdatePeriod = this.masterPlaylistLoader_.master && this.masterPlaylistLoader_.master.minimumUpdatePeriod; if (minimumUpdatePeriod > 0) { createMUPTimeout(minimumUpdatePeriod); @@ -701,110 +674,29 @@ export default class DashPlaylistLoader extends EventTarget { } } - /** - * Handler for after client/server clock synchronization has happened. Sets up - * xml refresh timer if specificed by the manifest. - */ - onClientServerClockSync_() { - this.haveMaster_(); - - if (!this.hasPendingRequest() && !this.media_) { - this.media(this.master.playlists[0]); - } - - this.updateMinimumUpdatePeriodTimeout_(); - } - /** * Sends request to refresh the master xml and updates the parsed master manifest - * TODO: Does the client offset need to be recalculated when the xml is refreshed? */ refreshXml_() { - // The srcUrl here *may* need to pass through handleManifestsRedirects when - // sidx is implemented - this.request = this.vhs_.xhr({ - uri: this.masterPlaylistLoader_.srcUrl, - withCredentials: this.withCredentials - }, (error, req) => { - // disposed - if (!this.request) { + this.requestMaster_((req, masterChanged) => { + if (!masterChanged) { return; } - // clear the loader's request reference - this.request = null; - - if (error) { - this.error = { - status: req.status, - message: 'DASH playlist request error at URL: ' + this.masterPlaylistLoader_.srcUrl, - responseText: req.responseText, - // MEDIA_ERR_NETWORK - code: 2 - }; - if (this.state === 'HAVE_NOTHING') { - this.started = false; - } - return this.trigger('error'); - } - - // xml is the same do nothing. - if (req.responseText === this.masterPlaylistLoader_.masterXml_) { - return; + if (this.media_) { + this.media_ = this.masterPlaylistLoader_.master.playlists[this.media_.id]; } - this.masterPlaylistLoader_.masterXml_ = req.responseText; - this.handleMaster_(); - // This will filter out updated sidx info from the mapping this.masterPlaylistLoader_.sidxMapping_ = filterChangedSidxMappings( this.masterPlaylistLoader_.master, this.masterPlaylistLoader_.sidxMapping_ ); - const currentSidxInfo = this.media().sidx; - - if (this.media_) { - this.media_ = this.master.playlists[this.media_.id]; - } - - this.updateMinimumUpdatePeriodTimeout_(); - // current sidx not updated - if (!currentSidxInfo) { - return; - } - const sidxKey = generateSidxKey(currentSidxInfo); - - // sidxKey already exists - if (this.masterPlaylistLoader_.sidxMapping_[sidxKey]) { - return; - } - const playlist = this.media(); - - this.request = requestSidx_( - this, - playlist.sidx, - playlist, - this.vhs_.xhr, - { handleManifestRedirects: this.handleManifestRedirects }, - this.sidxRequestFinished_(playlist, this.masterPlaylistLoader_.master, this.state, (newMaster, sidx) => { - if (!newMaster || !sidx) { - throw new Error('failed to request sidx on minimumUpdatePeriod'); - } - - // update loader's sidxMapping with parsed sidx box - this.masterPlaylistLoader_.sidxMapping_[sidxKey].sidx = sidx; - - addSidxSegmentsToPlaylist(playlist, sidx, playlist.sidx.resolvedUri); - - this.updateMinimumUpdatePeriodTimeout_(); - - // TODO: do we need to reload the current playlist? - this.refreshMedia_(this.media().id); - - return; - }) - ); + this.addSidxSegments_(this.media(), this.state, (sidxChanged) => { + // TODO: do we need to reload the current playlist? + this.refreshMedia_(this.media().id); + }); }); } @@ -818,7 +710,14 @@ export default class DashPlaylistLoader extends EventTarget { throw new Error('refreshMedia_ must take a media id'); } - this.handleMaster_(); + // for master we have to reparse the master xml + // to re-create segments based on current timing values + // which may change media. We only skip updating master + // if this is the first time this.media_ is being set. + // as master was just parsed in that case. + if (this.media_ && this.isMaster_) { + this.handleMaster_(); + } const playlists = this.masterPlaylistLoader_.master.playlists; const mediaChanged = !this.media_ || this.media_ !== playlists[mediaID]; diff --git a/test/dash-playlist-loader.test.js b/test/dash-playlist-loader.test.js index f9f85de15..0ec06922b 100644 --- a/test/dash-playlist-loader.test.js +++ b/test/dash-playlist-loader.test.js @@ -3,7 +3,6 @@ import sinon from 'sinon'; import { default as DashPlaylistLoader, updateMaster, - requestSidx_, generateSidxKey, compareSidxEntry, filterChangedSidxMappings, @@ -538,7 +537,8 @@ QUnit.test('filterChangedSidxMappings: removes change sidx info from mapping', f ); }); -QUnit.test('requestSidx_: creates an XHR request for a sidx range', function(assert) { +QUnit.test('addSidxSegments_: creates an XHR request for a sidx range', function(assert) { + const loader = new DashPlaylistLoader('dash.mpd', this.fakeVhs); const sidxInfo = { resolvedUri: 'sidx.mp4', byterange: { @@ -553,30 +553,24 @@ QUnit.test('requestSidx_: creates an XHR request for a sidx range', function(ass sidx: sidxInfo }; const callback = sinon.stub(); - const request = requestSidx_( - {}, - sidxInfo, - playlist, - this.fakeVhs.xhr, - { handleManifestRedirects: false }, - callback - ); - assert.ok(request, 'a request was returned'); - assert.strictEqual(request.uri, sidxInfo.resolvedUri, 'uri requested is correct'); - assert.strictEqual(this.requests.length, 1, 'one xhr request'); + loader.addSidxSegments_(playlist, loader.state, callback); + assert.strictEqual(this.requests[0].uri, sidxInfo.resolvedUri, 'uri requested is correct'); this.standardXHRResponse(this.requests.shift(), mp4VideoInitSegment().subarray(0, 10)); + + assert.strictEqual(this.requests[0].uri, sidxInfo.resolvedUri, 'uri requested is correct'); this.standardXHRResponse(this.requests.shift()); assert.strictEqual(callback.callCount, 1, 'callback was called'); }); -QUnit.test('requestSidx_: does not re-request bytes from container request', function(assert) { +QUnit.test('addSidxSegments_: does not re-request bytes from container request', function(assert) { + const loader = new DashPlaylistLoader('dash.mpd', this.fakeVhs); const sidxInfo = { resolvedUri: 'sidx.mp4', byterange: { offset: 0, - length: 10 + length: 600 } }; const playlist = { @@ -586,26 +580,23 @@ QUnit.test('requestSidx_: does not re-request bytes from container request', fun sidx: sidxInfo }; const callback = sinon.stub(); - const request = requestSidx_( - {}, - sidxInfo, - playlist, - this.fakeVhs.xhr, - { handleManifestRedirects: false }, - callback - ); - assert.ok(request, 'a request was returned'); - assert.strictEqual(request.uri, sidxInfo.resolvedUri, 'uri requested is correct'); + loader.addSidxSegments_(playlist, loader.state, callback); + assert.strictEqual(this.requests[0].uri, sidxInfo.resolvedUri, 'uri requested is correct'); assert.strictEqual(this.requests.length, 1, 'one xhr request'); - this.standardXHRResponse(this.requests.shift(), mp4VideoInitSegment().subarray(0, 10)); + const data = new Uint8Array(600); + + data.set(mp4VideoInitSegment().subarray(0, 10)); + + this.standardXHRResponse(this.requests.shift(), data); assert.equal(this.requests.length, 0, 'no more requests'); assert.strictEqual(callback.callCount, 1, 'callback was called'); }); -QUnit.test('requestSidx_: callsback with error on invalid container', function(assert) { +QUnit.test('addSidxSegments_: adds/triggers error on invalid container', function(assert) { + const loader = new DashPlaylistLoader('dash.mpd', this.fakeVhs); const sidxInfo = { resolvedUri: 'sidx.mp4', byterange: { @@ -619,25 +610,23 @@ QUnit.test('requestSidx_: callsback with error on invalid container', function(a segments: [sidxInfo], sidx: sidxInfo }; + let triggeredError = false; const callback = sinon.stub(); - const request = requestSidx_( - {}, - sidxInfo, - playlist, - this.fakeVhs.xhr, - { handleManifestRedirects: false }, - callback - ); - assert.ok(request, 'a request was returned'); - assert.strictEqual(request.uri, sidxInfo.resolvedUri, 'uri requested is correct'); + loader.on('error', () => { + triggeredError = true; + }); + loader.addSidxSegments_(playlist, loader.state, callback); + + assert.strictEqual(this.requests[0].uri, sidxInfo.resolvedUri, 'uri requested is correct'); assert.strictEqual(this.requests.length, 1, 'one xhr request'); this.standardXHRResponse(this.requests.shift()); assert.equal(this.requests.length, 0, 'no more requests'); - assert.strictEqual(callback.callCount, 1, 'callback was called'); - assert.deepEqual(callback.args[0][0], { + assert.ok(triggeredError, 'triggered an error'); + + assert.deepEqual(loader.error, { blacklistDuration: Infinity, code: 2, internal: true, @@ -1554,6 +1543,7 @@ QUnit.test('refreshMedia: updates master and media playlists for child loader', const newMasterXml = testDataManifests['dash-live']; loader.masterXml_ = newMasterXml; + loader.handleMaster_(); childLoader.refreshMedia_(loader.media().id); assert.notEqual(loader.master, oldMaster, 'new master set on master loader'); @@ -1694,52 +1684,51 @@ QUnit.test('refreshXml_: updates media playlist reference if master changed', fu ); }); -QUnit.test('sidxRequestFinished_: updates master with sidx information', function(assert) { +QUnit.test('addSidxSegments_: updates master with sidx information', function(assert) { const loader = new DashPlaylistLoader('dash.mpd', this.fakeVhs); + const sidxData = sidxResponse(); const fakePlaylist = { segments: [], id: 'fakeplaylist', uri: 'fakeplaylist', sidx: { + uri: 'sidx.mp4', byterange: { offset: 0, - length: sidxResponse().byteLength + length: sidxData.byteLength }, + duration: 1024, resolvedUri: 'sidx.mp4' } }; - const fakeMaster = { + + loader.masterPlaylistLoader_.master = { playlists: { 0: fakePlaylist, fakeplaylist: fakePlaylist } }; const stubDone = sinon.stub(); - const handleSidxResponse = loader.sidxRequestFinished_(fakePlaylist, fakeMaster, 'HAVE_MASTER', stubDone); - const fakeRequest = { - response: sidxResponse() - }; + const sidxMapping = loader.masterPlaylistLoader_.sidxMapping_; + + assert.deepEqual(sidxMapping, {}, 'no sidx mapping'); + loader.addSidxSegments_(fakePlaylist, 'HAVE_MASTER', stubDone); + + this.standardXHRResponse(this.requests.shift(), mp4VideoInitSegment().subarray(0, 10)); + this.standardXHRResponse(this.requests.shift(), sidxData); - // fake the loader active request for sidx - loader.request = true; - handleSidxResponse(null, fakeRequest); assert.strictEqual(stubDone.callCount, 1, 'callback was called'); - assert.ok( - stubDone.getCall(0).args[0].playlists, - 'returned master playlist object' - ); - assert.ok( - stubDone.getCall(0).args[1].references, - 'returned a parsed sidx box' - ); - assert.strictEqual( - stubDone.getCall(0).args[1].references[0].referencedSize, + assert.ok(stubDone.getCall(0).args[0], 'sidx segments were added'); + assert.ok(fakePlaylist.segments.length, 'added a parsed sidx segment to playlist'); + + assert.deepEqual( + sidxMapping['sidx.mp4-0-43'].sidx.references[0].referencedSize, 13001, 'sidx box returned has been parsed' ); }); -QUnit.test('sidxRequestFinished_: errors if request for sidx fails', function(assert) { +QUnit.test('addSidxSegments_: errors if request for sidx fails', function(assert) { const loader = new DashPlaylistLoader('dash.mpd', this.fakeVhs); const fakePlaylist = { segments: [{ @@ -1756,34 +1745,26 @@ QUnit.test('sidxRequestFinished_: errors if request for sidx fails', function(as resolvedUri: 'sidx.mp4' } }; - const fakeMaster = { - playlists: { - 0: fakePlaylist, - fakeplaylist: fakePlaylist - } - }; const stubDone = sinon.stub(); - const handleSidxResponse = loader.sidxRequestFinished_(fakePlaylist, fakeMaster, 'HAVE_MASTER', stubDone); - const fakeRequest = { - response: 'fake error msg', - status: 400 - }; + const sidxMapping = loader.masterPlaylistLoader_.sidxMapping_; let errors = 0; + assert.deepEqual(sidxMapping, {}, 'no sidx mapping'); + loader.addSidxSegments_(fakePlaylist, 'HAVE_MASTER', stubDone); + loader.on('error', () => { errors++; }); - // fake xhr request being active - loader.request = true; - handleSidxResponse(true, fakeRequest); + this.requests.shift().respond(500, null, 'bad request'); + assert.strictEqual(loader.state, 'HAVE_MASTER', 'state is returned to state passed in'); assert.deepEqual( loader.error, { - status: fakeRequest.status, - message: 'DASH playlist request error at URL: fakeplaylist', - response: fakeRequest.response, + status: 500, + message: 'DASH request error at URL: sidx.mp4', + response: '', code: 2 }, 'error object is filled out correctly' @@ -1791,64 +1772,6 @@ QUnit.test('sidxRequestFinished_: errors if request for sidx fails', function(as assert.strictEqual(errors, 1, 'triggered an error event'); }); -QUnit.test('sidxRequestFinished_: uses given error object', function(assert) { - const loader = new DashPlaylistLoader('dash.mpd', this.fakeVhs); - const fakePlaylist = { - segments: [{ - uri: 'fake-segment', - duration: 15360 - }], - id: 'fakeplaylist', - uri: 'fakeplaylist', - sidx: { - byterange: { - offset: 0, - length: sidxResponse().byteLength - }, - resolvedUri: 'sidx.mp4' - } - }; - const fakeMaster = { - playlists: { - 0: fakePlaylist, - fakeplaylist: fakePlaylist - } - }; - const stubDone = sinon.stub(); - const handleSidxResponse = loader.sidxRequestFinished_(fakePlaylist, fakeMaster, 'HAVE_MASTER', stubDone); - const fakeRequest = { - response: '', - status: 200 - }; - let errors = 0; - - loader.on('error', () => { - errors++; - }); - - // fake xhr request being active - loader.request = true; - const error = { - status: fakeRequest.status, - message: 'Unsupported webm container type for sidx segment at URL: sidx.mp4', - playlist: fakePlaylist, - internal: true, - response: '', - blacklistDuration: Infinity, - // MEDIA_ERR_NETWORK - code: 2 - }; - - handleSidxResponse(error, fakeRequest); - assert.strictEqual(loader.state, 'HAVE_MASTER', 'state is returned to state passed in'); - assert.deepEqual( - loader.error, - error, - 'error object is filled out correctly' - ); - assert.strictEqual(errors, 1, 'triggered an error event'); -}); - QUnit.test('hasPendingRequest: returns true if async code is running in master loader', function(assert) { const loader = new DashPlaylistLoader('dash.mpd', this.fakeVhs); From 00d9b1dd217302ce3110f243d3a408a1357a0aef Mon Sep 17 00:00:00 2001 From: Brandon Casey <2381475+brandonocasey@users.noreply.github.com> Date: Tue, 24 Nov 2020 16:55:16 -0500 Subject: [PATCH 033/399] test: fix tests on firefox 83 (#1004) --- .github/workflows/ci.yml | 9 ++ src/ad-cue-tags.js | 9 ++ src/bin-utils.js | 15 ++++ src/source-updater.js | 5 +- test/playback.test.js | 162 +++++++++++++++++++----------------- test/source-updater.test.js | 9 +- test/test-helpers.js | 40 ++++----- 7 files changed, 145 insertions(+), 104 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c8fe389ef..355a71156 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,6 +32,10 @@ jobs: shell: bash id: nvm + - name: update apt cache on linux w/o browserstack + run: sudo apt-get update + if: ${{ startsWith(matrix.os, 'ubuntu') && !env.BROWSER_STACK_USERNAME }} + - name: Install ffmpeg/pulseaudio for firefox on linux w/o browserstack run: sudo apt-get install ffmpeg pulseaudio if: ${{ startsWith(matrix.os, 'ubuntu') && !env.BROWSER_STACK_USERNAME }} @@ -44,6 +48,11 @@ jobs: uses: actions/setup-node@v1 with: node-version: '${{ steps.nvm.outputs.NVMRC }}' + # turn off the default setup-node problem watchers... + - run: echo "::remove-matcher owner=eslint-compact::" + - run: echo "::remove-matcher owner=eslint-stylish::" + - run: echo "::remove-matcher owner=tsc::" + - run: npm i --prefer-offline --no-audit # run safari on macos diff --git a/src/ad-cue-tags.js b/src/ad-cue-tags.js index 514e065c4..8710803dc 100644 --- a/src/ad-cue-tags.js +++ b/src/ad-cue-tags.js @@ -5,6 +5,15 @@ import window from 'global/window'; /** * Searches for an ad cue that overlaps with the given mediaTime + * + * @param {Object} track + * the track to find the cue for + * + * @param {number} mediaTime + * the time to find the cue at + * + * @return {Object|null} + * the found cue or null */ export const findAdCue = function(track, mediaTime) { const cues = track.cues; diff --git a/src/bin-utils.js b/src/bin-utils.js index fd33fa9f0..ae675bc0c 100644 --- a/src/bin-utils.js +++ b/src/bin-utils.js @@ -7,6 +7,7 @@ * * @param {TimeRange} range the timerange to use for conversion * @param {number} i the iterator on the range to convert + * @return {string} the range in string format */ const textRange = function(range, i) { return range.start(i) + '-' + range.end(i); @@ -17,6 +18,7 @@ const textRange = function(range, i) { * * @param {number} e The number * @param {number} i the iterator + * @return {string} the hex formatted number as a string */ const formatHexString = function(e, i) { const value = e.toString(16); @@ -63,6 +65,11 @@ export const createTransferableMessage = function(message) { /** * Returns a unique string identifier for a media initialization * segment. + * + * @param {Object} initSegment + * the init segment object. + * + * @return {string} the generated init segment id */ export const initSegmentId = function(initSegment) { const byterange = initSegment.byterange || { @@ -77,6 +84,9 @@ export const initSegmentId = function(initSegment) { /** * Returns a unique string identifier for a media segment key. + * + * @param {Object} key the encryption key + * @return {string} the unique id for the media segment key. */ export const segmentKeyId = function(key) { return key.resolvedUri; @@ -84,6 +94,11 @@ export const segmentKeyId = function(key) { /** * utils to help dump binary data to the console + * + * @param {Array|TypedArray} data + * data to dump to a string + * + * @return {string} the data as a hex string. */ export const hexDump = (data) => { const bytes = Array.prototype.slice.call(data); diff --git a/src/source-updater.js b/src/source-updater.js index 35d0a7f08..dcecd56d8 100644 --- a/src/source-updater.js +++ b/src/source-updater.js @@ -415,8 +415,9 @@ export default class SourceUpdater extends videojs.EventTarget { canRemoveSourceBuffer() { // IE reports that it supports removeSourceBuffer, but often throws // errors when attempting to use the function. So we report that it - // does not support removeSourceBuffer. - return !videojs.browser.IE_VERSION && window.MediaSource && + // does not support removeSourceBuffer. As of Firefox 83 removeSourceBuffer + // throws errors, so we report that it does not support this as well. + return !videojs.browser.IE_VERSION && !videojs.browser.IS_FIREFOX && window.MediaSource && window.MediaSource.prototype && typeof window.MediaSource.prototype.removeSourceBuffer === 'function'; } diff --git a/test/playback.test.js b/test/playback.test.js index 31b9d4063..9093bad62 100644 --- a/test/playback.test.js +++ b/test/playback.test.js @@ -6,15 +6,6 @@ import '../src/videojs-http-streaming'; import 'videojs-contrib-eme'; const playFor = function(player, time, cb) { - if (player.paused()) { - const playPromise = player.play(); - - // Catch/silence error when a pause interrupts a play request - // on browsers which return a promise - if (typeof playPromise !== 'undefined' && typeof playPromise.then === 'function') { - playPromise.then(null, (e) => {}); - } - } const targetTime = player.currentTime() + time; const checkPlayerTime = function() { @@ -23,9 +14,21 @@ const playFor = function(player, time, cb) { return checkPlayerTime(); } cb(); - }, 10); + }, 100); }; + if (player.paused()) { + const playPromise = player.play(); + + // assert an error on playback failure or check player time after play has started. + if (typeof playPromise !== 'undefined' && typeof playPromise.then === 'function') { + playPromise.then(checkPlayerTime).catch((e) => { + QUnit.assert.notOk(true, 'play promise failed with error', e); + }); + return; + } + } + checkPlayerTime(); }; @@ -218,7 +221,7 @@ QUnit[testFn]('Big Buck Bunny', function(assert) { }); }); -QUnit[testFn]('Big Buck Bunny audio only, groups & renditions same uri', function(assert) { +QUnit[testFn]('Live DASH', function(assert) { const done = assert.async(); assert.expect(2); @@ -232,101 +235,104 @@ QUnit[testFn]('Big Buck Bunny audio only, groups & renditions same uri', functio }); player.src({ - src: 'https://d2zihajmogu5jn.cloudfront.net/audio-only-dupe-groups/prog_index.m3u8', - type: 'application/x-mpegURL' + src: 'https://livesim.dashif.org/livesim/mup_30/testpic_2s/Manifest.mpd', + type: 'application/dash+xml' }); }); -QUnit[testFn]('Big Buck Bunny Demuxed av, audio only rendition same as group', function(assert) { - const done = assert.async(); +// These videos don't work on firefox consistenly. Seems like +// firefox has lower performance or more aggressive throttling than chrome +// which causes a variety of issues. +if (!videojs.browser.IS_FIREFOX) { + QUnit[testFn]('Big Buck Bunny audio only, groups & renditions same uri', function(assert) { + const done = assert.async(); - assert.expect(2); - const player = this.player; + assert.expect(2); + const player = this.player; - playFor(player, 25, function() { - assert.ok(true, 'played for at least 25 seconds'); - assert.equal(player.error(), null, 'has no player errors'); + playFor(player, 2, function() { + assert.ok(true, 'played for at least two seconds'); + assert.equal(player.error(), null, 'has no player errors'); - done(); - }); + done(); + }); - player.src({ - src: 'https://d2zihajmogu5jn.cloudfront.net/demuxed-ts-with-audio-only-rendition/master.m3u8', - type: 'application/x-mpegURL' + player.src({ + src: 'https://d2zihajmogu5jn.cloudfront.net/audio-only-dupe-groups/prog_index.m3u8', + type: 'application/x-mpegURL' + }); }); -}); -QUnit[testFn]('Live DASH', function(assert) { - const done = assert.async(); + QUnit[testFn]('Big Buck Bunny Demuxed av, audio only rendition same as group', function(assert) { + const done = assert.async(); - assert.expect(2); - const player = this.player; + assert.expect(2); + const player = this.player; - playFor(player, 2, function() { - assert.ok(true, 'played for at least two seconds'); - assert.equal(player.error(), null, 'has no player errors'); + playFor(player, 25, function() { + assert.ok(true, 'played for at least 25 seconds'); + assert.equal(player.error(), null, 'has no player errors'); - done(); - }); + done(); + }); - player.src({ - src: 'https://livesim.dashif.org/livesim/mup_30/testpic_2s/Manifest.mpd', - type: 'application/dash+xml' + player.src({ + src: 'https://d2zihajmogu5jn.cloudfront.net/demuxed-ts-with-audio-only-rendition/master.m3u8', + type: 'application/x-mpegURL' + }); }); -}); -QUnit[testFn]('DASH sidx', function(assert) { - const done = assert.async(); - const player = this.player; + QUnit[testFn]('DASH sidx', function(assert) { + const done = assert.async(); + const player = this.player; - playFor(player, 2, function() { - assert.ok(true, 'played for at least two seconds'); - assert.equal(player.error(), null, 'no errors'); + playFor(player, 2, function() { + assert.ok(true, 'played for at least two seconds'); + assert.equal(player.error(), null, 'no errors'); - player.one('ended', () => { - assert.ok(true, 'triggered ended event'); - done(); - }); + player.one('ended', () => { + assert.ok(true, 'triggered ended event'); + done(); + }); - // Firefox sometimes won't loop if seeking directly to the duration, or to too close - // to the duration (e.g., 10ms from duration). 100ms seems to work. - player.currentTime(player.duration() - 0.5); - }); + // Firefox sometimes won't loop if seeking directly to the duration, or to too close + // to the duration (e.g., 10ms from duration). 100ms seems to work. + player.currentTime(player.duration() - 0.5); + }); - player.src({ - src: 'https://dash.akamaized.net/dash264/TestCases/10a/1/iis_forest_short_poem_multi_lang_480p_single_adapt_aaclc_sidx.mpd', - type: 'application/dash+xml' + player.src({ + src: 'https://dash.akamaized.net/dash264/TestCases/10a/1/iis_forest_short_poem_multi_lang_480p_single_adapt_aaclc_sidx.mpd', + type: 'application/dash+xml' + }); }); -}); - -QUnit[testFn]('DASH sidx with alt audio should end', function(assert) { - const done = assert.async(); - const player = this.player; - player.one('ended', () => { - assert.ok(true, 'triggered ended'); - assert.equal(player.error(), null, 'no errors'); - done(); - }); + QUnit[testFn]('DASH sidx with alt audio should end', function(assert) { + const done = assert.async(); + const player = this.player; - /* eslint-disable max-nested-callbacks */ - playFor(player, 1, () => { - // switch audio playlist - player.audioTracks()[1].enabled = true; + player.one('ended', () => { + assert.ok(true, 'triggered ended'); + assert.equal(player.error(), null, 'no errors'); + done(); + }); + /* eslint-disable max-nested-callbacks */ playFor(player, 1, () => { - player.currentTime(player.duration() - 5); + // switch audio playlist + player.audioTracks()[1].enabled = true; + + playFor(player, 1, () => { + player.currentTime(player.duration() - 5); + }); }); - }); - /* eslint-enable max-nested-callbacks */ + /* eslint-enable max-nested-callbacks */ - player.src({ - src: 'https://dash.akamaized.net/dash264/TestCases/10a/1/iis_forest_short_poem_multi_lang_480p_single_adapt_aaclc_sidx.mpd', - type: 'application/dash+xml' + player.src({ + src: 'https://dash.akamaized.net/dash264/TestCases/10a/1/iis_forest_short_poem_multi_lang_480p_single_adapt_aaclc_sidx.mpd', + type: 'application/dash+xml' + }); }); -}); -if (!videojs.browser.IS_FIREFOX) { QUnit[testFn]('DRM Dash', function(assert) { const done = assert.async(); const player = this.player; diff --git a/test/source-updater.test.js b/test/source-updater.test.js index 00d32be4c..d20e1f2b1 100644 --- a/test/source-updater.test.js +++ b/test/source-updater.test.js @@ -44,13 +44,16 @@ const mp4AudioTotal = () => concatSegments(mp4AudioInit(), mp4Audio()); QUnit.module('Source Updater', { beforeEach() { - const video = document.createElement('video'); + this.fixture = document.getElementById('qunit-fixture'); + this.video = document.createElement('video'); + + this.fixture.appendChild(this.video); this.mediaSource = new window.MediaSource(); // need to attach the real media source to a video element for the media source to // change to an open ready state - video.src = URL.createObjectURL(this.mediaSource); + this.video.src = URL.createObjectURL(this.mediaSource); this.sourceUpdater = new SourceUpdater(this.mediaSource); // wait for the source to open (or error) before running through tests @@ -62,6 +65,8 @@ QUnit.module('Source Updater', { afterEach() { this.sourceUpdater.dispose(); + this.video.src = ''; + this.fixture.removeChild(this.video); } }); diff --git a/test/test-helpers.js b/test/test-helpers.js index b352662dc..3d8d52d82 100644 --- a/test/test-helpers.js +++ b/test/test-helpers.js @@ -9,6 +9,24 @@ import { muxed as muxedSegment } from 'create-test-data!segments'; import {bytesToString, isTypedArray} from '@videojs/vhs-utils/dist/byte-helpers'; import {isLikelyFmp4MediaSegment} from '@videojs/vhs-utils/dist/containers'; +// return an absolute version of a page-relative URL +export const absoluteUrl = function(relativeUrl) { + return URLToolkit.buildAbsoluteURL(window.location.href, relativeUrl); +}; + +const origOpen = sinon.FakeXMLHttpRequest.prototype.open; + +sinon.FakeXMLHttpRequest.prototype.open = function() { + this.responseURL = absoluteUrl(arguments[1]); + return origOpen.apply(this, arguments); +}; + +// used for treating the response however we want, instead of the browser deciding +// responses we don't have to worry about the browser changing responses +sinon.FakeXMLHttpRequest.prototype.overrideMimeType = function overrideMimeType(mimeType) { + this.mimeTypeOverride = mimeType; +}; + const RealMediaSource = window.MediaSource; const realCreateObjectURL = window.URL.createObjectURL; @@ -136,11 +154,6 @@ export class MockTextTrack { } } -// return an absolute version of a page-relative URL -export const absoluteUrl = function(relativeUrl) { - return URLToolkit.buildAbsoluteURL(window.location.href, relativeUrl); -}; - export const useFakeMediaSource = function() { window.MediaSource = MockMediaSource; window.URL.createObjectURL = (object) => realCreateObjectURL(object instanceof MockMediaSource ? object.nativeMediaSource_ : object); @@ -227,23 +240,6 @@ export const useFakeEnvironment = function(assert) { fakeEnvironment.clock = sinon.useFakeTimers(); fakeEnvironment.xhr = sinon.useFakeXMLHttpRequest(); - window.XMLHttpRequest.prototype = Object.create(window.XMLHttpRequest.prototype); - - // used for treating the response however we want, instead of the browser deciding - // responses we don't have to worry about the browser changing responses - window.XMLHttpRequest.prototype.overrideMimeType = function overrideMimeType(mimeType) { - this.mimeTypeOverride = mimeType; - }; - - // add support for xhr.responseURL - window.XMLHttpRequest.prototype.open = (function(origFn) { - return function() { - this.responseURL = absoluteUrl(arguments[1]); - - return origFn.apply(this, arguments); - }; - }(window.XMLHttpRequest.prototype.open)); - fakeEnvironment.requests.length = 0; fakeEnvironment.xhr.onCreate = function(xhr) { fakeEnvironment.requests.push(xhr); From 93132b75a2e547e936b4fe5189db6ea6b1fac05d Mon Sep 17 00:00:00 2001 From: Garrett Singer Date: Tue, 1 Dec 2020 16:34:59 -0500 Subject: [PATCH 034/399] fix: Wait for EME initialization before appending content (#1002) This is particularly important for Chrome, where, if unencrypted content is appended before encrypted content and the key session has not been created, a MEDIA_ERR_DECODE will be thrown once the encrypted content is reached during playback. --- package-lock.json | 6 +- package.json | 2 +- src/master-playlist-controller.js | 12 +- src/segment-loader.js | 1 - src/source-updater.js | 39 +- src/videojs-http-streaming.js | 186 ++++++-- test/master-playlist-controller.test.js | 12 +- test/source-updater.test.js | 24 +- test/test-helpers.js | 6 + test/videojs-http-streaming.test.js | 560 +++++++++++++++--------- 10 files changed, 586 insertions(+), 262 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2ee6d8f3d..f3f857ac4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10704,9 +10704,9 @@ } }, "videojs-contrib-eme": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/videojs-contrib-eme/-/videojs-contrib-eme-3.7.1.tgz", - "integrity": "sha512-zWUT2TFZ1zJ0gILZIx9KQELwHQmtaQzmlPJ36pWHh3IogMcWOeWIGBmrIc6leSGN7ZCeV8xieig7CNsAEXlQMg==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/videojs-contrib-eme/-/videojs-contrib-eme-3.8.0.tgz", + "integrity": "sha512-ZSNqMviFdzZfAWJyyt8xSak7SR+ZFdwb0Fs30LCmp0qKgqM5EgNF/blhPjkiz7NzXD+VO6TmhsRlZJ7qaQ811g==", "dev": true, "requires": { "global": "^4.3.2", diff --git a/package.json b/package.json index 0a5a9451b..35f5231db 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "shelljs": "^0.8.2", "sinon": "^8.1.1", "url-toolkit": "^2.1.3", - "videojs-contrib-eme": "^3.2.0", + "videojs-contrib-eme": "^3.8.0", "videojs-contrib-quality-levels": "^2.0.4", "videojs-generate-karma-config": "~7.0.0", "videojs-generate-rollup-config": "~5.0.1", diff --git a/src/master-playlist-controller.js b/src/master-playlist-controller.js index 36ec729af..e36f0b922 100644 --- a/src/master-playlist-controller.js +++ b/src/master-playlist-controller.js @@ -652,7 +652,7 @@ export class MasterPlaylistController extends videojs.EventTarget { }); const updateCodecs = () => { - if (!this.sourceUpdater_.ready()) { + if (!this.sourceUpdater_.hasCreatedSourceBuffers()) { return this.tryToCreateSourceBuffers_(); } @@ -1549,7 +1549,10 @@ export class MasterPlaylistController extends videojs.EventTarget { return; } // check if codec switching is happening - if (this.sourceUpdater_.ready() && !this.sourceUpdater_.canChangeType()) { + if ( + this.sourceUpdater_.hasCreatedSourceBuffers() && + !this.sourceUpdater_.canChangeType() + ) { const switchMessages = []; ['video', 'audio'].forEach((type) => { @@ -1585,7 +1588,10 @@ export class MasterPlaylistController extends videojs.EventTarget { tryToCreateSourceBuffers_() { // media source is not ready yet or sourceBuffers are already // created. - if (this.mediaSource.readyState !== 'open' || this.sourceUpdater_.ready()) { + if ( + this.mediaSource.readyState !== 'open' || + this.sourceUpdater_.hasCreatedSourceBuffers() + ) { return; } diff --git a/src/segment-loader.js b/src/segment-loader.js index 056a817d9..47db87df8 100644 --- a/src/segment-loader.js +++ b/src/segment-loader.js @@ -1713,7 +1713,6 @@ export default class SegmentLoader extends videojs.EventTarget { hasEnoughInfoToAppend_() { if (!this.sourceUpdater_.ready()) { - // waiting on one of the segment loaders to get enough data to create source buffers return false; } diff --git a/src/source-updater.js b/src/source-updater.js index dcecd56d8..d8b14dd16 100644 --- a/src/source-updater.js +++ b/src/source-updater.js @@ -79,7 +79,11 @@ const shiftQueue = (type, sourceUpdater) => { // Media source queue entries don't need to consider whether the source updater is // started (i.e., source buffers are created) as they don't need the source buffers, but // source buffer queue entries do. - if (!sourceUpdater.started_ || sourceUpdater.mediaSource.readyState === 'closed' || updating(type, sourceUpdater)) { + if ( + !sourceUpdater.ready() || + sourceUpdater.mediaSource.readyState === 'closed' || + updating(type, sourceUpdater) + ) { return; } @@ -331,15 +335,33 @@ export default class SourceUpdater extends videojs.EventTarget { // used for debugging this.audioError_ = e; }; - this.started_ = false; + this.createdSourceBuffers_ = false; + this.initializedEme_ = false; + } + + initializedEme() { + this.initializedEme_ = true; + if (this.ready()) { + this.trigger('ready'); + } + } + + hasCreatedSourceBuffers() { + // if false, likely waiting on one of the segment loaders to get enough data to create + // source buffers + return this.createdSourceBuffers_; + } + + hasInitializedAnyEme() { + return this.initializedEme_; } ready() { - return this.started_; + return this.hasCreatedSourceBuffers() && this.hasInitializedAnyEme(); } createSourceBuffers(codecs) { - if (this.ready()) { + if (this.hasCreatedSourceBuffers()) { // already created them before return; } @@ -347,8 +369,11 @@ export default class SourceUpdater extends videojs.EventTarget { // the intial addOrChangeSourceBuffers will always be // two add buffers. this.addOrChangeSourceBuffers(codecs); - this.started_ = true; - this.trigger('ready'); + this.createdSourceBuffers_ = true; + this.trigger('createdsourcebuffers'); + if (this.ready()) { + this.trigger('ready'); + } } /** @@ -484,7 +509,7 @@ export default class SourceUpdater extends videojs.EventTarget { Object.keys(codecs).forEach((type) => { const codec = codecs[type]; - if (!this.ready()) { + if (!this.hasCreatedSourceBuffers()) { return this.addSourceBuffer(type, codec); } diff --git a/src/videojs-http-streaming.js b/src/videojs-http-streaming.js index ef403bd2e..e05d6e351 100644 --- a/src/videojs-http-streaming.js +++ b/src/videojs-http-streaming.js @@ -31,6 +31,7 @@ import { comparePlaylistResolution } from './playlist-selectors.js'; import {isAudioCodec, isVideoCodec, browserSupportsCodec} from '@videojs/vhs-utils/dist/codecs.js'; +import logger from './util/logger'; // IMPORTANT: // keep these at the bottom they are replaced at build time @@ -165,6 +166,12 @@ const emeKeySystems = (keySystemOptions, videoPlaylist, audioPlaylist) => { for (const keySystem in keySystemOptions) { keySystemContentTypes[keySystem] = {audioContentType, videoContentType}; + // Default to using the video playlist's PSSH even though they may be different, as + // videojs-contrib-eme will only accept one in the options. + // + // This shouldn't be an issue for most cases as early intialization will handle all + // unique PSSH values, and if they aren't, then encrypted events should have the + // specific information needed for the unique license. if (videoPlaylist.contentProtection && videoPlaylist.contentProtection[keySystem] && videoPlaylist.contentProtection[keySystem].pssh) { @@ -230,47 +237,37 @@ const getAllPsshKeySystemsOptions = (playlists, keySystems) => { }; /** - * If the [eme](https://github.com/videojs/videojs-contrib-eme) plugin is available, and - * there are keySystems on the source, sets up source options to prepare the source for - * eme and tries to initialize it early via eme's initializeMediaKeys API (if available). + * Returns a promise that waits for the + * [eme plugin](https://github.com/videojs/videojs-contrib-eme) to create a key session. + * + * Works around https://bugs.chromium.org/p/chromium/issues/detail?id=895449 in non-IE11 + * browsers. + * + * As per the above ticket, this is particularly important for Chrome, where, if + * unencrypted content is appended before encrypted content and the key session has not + * been created, a MEDIA_ERR_DECODE will be thrown once the encrypted content is reached + * during playback. * * @param {Object} player * The player instance * @param {Object[]} sourceKeySystems * The key systems options from the player source - * @param {Object} media - * The active media playlist * @param {Object} [audioMedia] * The active audio media playlist (optional) * @param {Object[]} mainPlaylists * The playlists found on the master playlist object + * + * @return {Object} + * Promise that resolves when the key session has been created */ -const setupEmeOptions = ({ +export const waitForKeySessionCreation = ({ player, sourceKeySystems, - media, audioMedia, mainPlaylists }) => { - const sourceOptions = emeKeySystems(sourceKeySystems, media, audioMedia); - - if (!sourceOptions) { - return; - } - - player.currentSource().keySystems = sourceOptions; - - // eme handles the rest of the setup, so if it is missing - // do nothing. - if (sourceOptions && !player.eme) { - videojs.log.warn('DRM encrypted source cannot be decrypted without a DRM plugin'); - return; - } - - // works around https://bugs.chromium.org/p/chromium/issues/detail?id=895449 - // in non-IE11 browsers. In IE11 this is too early to initialize media keys - if (videojs.browser.IE_VERSION === 11 || !player.eme.initializeMediaKeys) { - return; + if (!player.eme.initializeMediaKeys) { + return Promise.resolve(); } // TODO should all audio PSSH values be initialized for DRM? @@ -288,16 +285,87 @@ const setupEmeOptions = ({ Object.keys(sourceKeySystems) ); + const initializationFinishedPromises = []; + const keySessionCreatedPromises = []; + // Since PSSH values are interpreted as initData, EME will dedupe any duplicates. The // only place where it should not be deduped is for ms-prefixed APIs, but the early // return for IE11 above, and the existence of modern EME APIs in addition to // ms-prefixed APIs on Edge should prevent this from being a concern. // initializeMediaKeys also won't use the webkit-prefixed APIs. keySystemsOptionsArr.forEach((keySystemsOptions) => { - player.eme.initializeMediaKeys({ - keySystems: keySystemsOptions - }); + keySessionCreatedPromises.push(new Promise((resolve, reject) => { + player.tech_.one('keysessioncreated', resolve); + })); + + initializationFinishedPromises.push(new Promise((resolve, reject) => { + player.eme.initializeMediaKeys({ + keySystems: keySystemsOptions + }, (err) => { + if (err) { + reject(err); + return; + } + resolve(); + }); + })); }); + + // The reasons Promise.race is chosen over Promise.any: + // + // * Promise.any is only available in Safari 14+. + // * None of these promises are expected to reject. If they do reject, it might be + // better here for the race to surface the rejection, rather than mask it by using + // Promise.any. + return Promise.race([ + // If a session was previously created, these will all finish resolving without + // creating a new session, otherwise it will take until the end of all license + // requests, which is why the key session check is used (to make setup much faster). + Promise.all(initializationFinishedPromises), + // Once a single session is created, the browser knows DRM will be used. + Promise.race(keySessionCreatedPromises) + ]); +}; + +/** + * If the [eme](https://github.com/videojs/videojs-contrib-eme) plugin is available, and + * there are keySystems on the source, sets up source options to prepare the source for + * eme. + * + * @param {Object} player + * The player instance + * @param {Object[]} sourceKeySystems + * The key systems options from the player source + * @param {Object} media + * The active media playlist + * @param {Object} [audioMedia] + * The active audio media playlist (optional) + * + * @return {boolean} + * Whether or not options were configured and EME is available + */ +const setupEmeOptions = ({ + player, + sourceKeySystems, + media, + audioMedia +}) => { + const sourceOptions = emeKeySystems(sourceKeySystems, media, audioMedia); + + if (!sourceOptions) { + return false; + } + + player.currentSource().keySystems = sourceOptions; + + // eme handles the rest of the setup, so if it is missing + // do nothing. + if (sourceOptions && !player.eme) { + videojs.log.warn('DRM encrypted source cannot be decrypted without a DRM plugin'); + return false; + } + + return true; }; const getVhsLocalStorage = () => { @@ -446,6 +514,8 @@ class VhsHandler extends Component { videojs.log.warn('Using hls options is deprecated. Use vhs instead.'); } + this.logger_ = logger('VhsHandler'); + // tech.player() is deprecated but setup a reference to HLS for // backwards-compatibility if (tech.options_ && tech.options_.playerId) { @@ -840,17 +910,8 @@ class VhsHandler extends Component { renditionSelectionMixin(this); }); - this.masterPlaylistController_.sourceUpdater_.on('ready', () => { - const audioPlaylistLoader = - this.masterPlaylistController_.mediaTypes_.AUDIO.activePlaylistLoader; - - setupEmeOptions({ - player: this.player_, - sourceKeySystems: this.source_.keySystems, - media: this.playlists.media(), - audioMedia: audioPlaylistLoader && audioPlaylistLoader.media(), - mainPlaylists: this.playlists.master.playlists - }); + this.masterPlaylistController_.sourceUpdater_.on('createdsourcebuffers', () => { + this.setupEme_(); }); // the bandwidth of the primary segment loader is our best @@ -878,6 +939,51 @@ class VhsHandler extends Component { this.tech_.src(this.mediaSourceUrl_); } + /** + * If necessary and EME is available, sets up EME options and waits for key session + * creation. + * + * This function also updates the source updater so taht it can be used, as for some + * browsers, EME must be configured before content is appended (if appending unencrypted + * content before encrypted content). + */ + setupEme_() { + const audioPlaylistLoader = + this.masterPlaylistController_.mediaTypes_.AUDIO.activePlaylistLoader; + + const didSetupEmeOptions = setupEmeOptions({ + player: this.player_, + sourceKeySystems: this.source_.keySystems, + media: this.playlists.media(), + audioMedia: audioPlaylistLoader && audioPlaylistLoader.media() + }); + + // In IE11 this is too early to initialize media keys, and IE11 does not support + // promises. + if (videojs.browser.IE_VERSION === 11 || !didSetupEmeOptions) { + // If EME options were not set up, we've done all we could to initialize EME. + this.masterPlaylistController_.sourceUpdater_.initializedEme(); + return; + } + + this.logger_('waiting for EME key session creation'); + waitForKeySessionCreation({ + player: this.player_, + sourceKeySystems: this.source_.keySystems, + audioMedia: audioPlaylistLoader && audioPlaylistLoader.media(), + mainPlaylists: this.playlists.master.playlists + }).then(() => { + this.logger_('created EME key session'); + this.masterPlaylistController_.sourceUpdater_.initializedEme(); + }).catch((err) => { + this.logger_('error while creating EME key session', err); + this.player_.error({ + message: 'Failed to initialize media keys for EME', + code: 3 + }); + }); + } + /** * Initializes the quality levels and sets listeners to update them. * diff --git a/test/master-playlist-controller.test.js b/test/master-playlist-controller.test.js index 919c80e22..daaa5684c 100644 --- a/test/master-playlist-controller.test.js +++ b/test/master-playlist-controller.test.js @@ -5021,7 +5021,8 @@ QUnit.test('excludes on codec switch if codec switching not supported', function }); // sourceUpdater_ already setup - this.mpc.sourceUpdater_.ready = () => true; + this.mpc.sourceUpdater_.initializedEme(); + this.mpc.sourceUpdater_.createdSourceBuffers_ = () => true; this.mpc.sourceUpdater_.canChangeType = () => false; this.mpc.sourceUpdater_.codecs = { audio: 'mp4a.40.2', @@ -5061,7 +5062,8 @@ QUnit.test('does not exclude on codec switch between the same base codec', funct }); // sourceUpdater_ already setup - this.mpc.sourceUpdater_.ready = () => true; + this.mpc.sourceUpdater_.initializedEme(); + this.mpc.sourceUpdater_.createdSourceBuffers_ = () => true; this.mpc.sourceUpdater_.canChangeType = () => false; this.mpc.sourceUpdater_.codecs = { audio: 'mp4a.40.2', @@ -5111,7 +5113,8 @@ QUnit.test('main loader only trackinfo works as expected', function(assert) { assert.equal(createBuffers, 1, 'createSourceBuffers called'); assert.equal(switchBuffers, 0, 'addOrChangeSourceBuffers not called'); - this.mpc.sourceUpdater_.ready = () => true; + this.mpc.sourceUpdater_.initializedEme(); + this.mpc.sourceUpdater_.createdSourceBuffers_ = () => true; this.mpc.sourceUpdater_.canChangeType = () => true; this.contentSetup({ @@ -5181,7 +5184,8 @@ QUnit.test('main & audio loader only trackinfo works as expected', function(asse assert.equal(createBuffers, 1, 'createSourceBuffers called'); assert.equal(switchBuffers, 0, 'addOrChangeSourceBuffers not called'); - this.mpc.sourceUpdater_.ready = () => true; + this.mpc.sourceUpdater_.initializedEme(); + this.mpc.sourceUpdater_.createdSourceBuffers_ = () => true; this.mpc.sourceUpdater_.canChangeType = () => true; this.mpc.mainSegmentLoader_.currentMediaInfo_ = { diff --git a/test/source-updater.test.js b/test/source-updater.test.js index d20e1f2b1..cad857a73 100644 --- a/test/source-updater.test.js +++ b/test/source-updater.test.js @@ -56,6 +56,10 @@ QUnit.module('Source Updater', { this.video.src = URL.createObjectURL(this.mediaSource); this.sourceUpdater = new SourceUpdater(this.mediaSource); + // This is normally done at the top level of the plugin, but will not happen in + // an isolated module. + this.sourceUpdater.initializedEme(); + // wait for the source to open (or error) before running through tests return new Promise((accept, reject) => { this.mediaSource.addEventListener('sourceopen', accept); @@ -167,6 +171,7 @@ QUnit.test('verifies that sourcebuffer is in source buffers list before attempti }; this.sourceUpdater = new SourceUpdater(createMediaSource()); + this.sourceUpdater.initializedEme(); this.sourceUpdater.createSourceBuffers({ audio: 'mp4a.40.2', video: 'avc1.4d400d' @@ -184,6 +189,7 @@ QUnit.test('verifies that sourcebuffer is in source buffers list before attempti this.sourceUpdater.dispose(); this.sourceUpdater = new SourceUpdater(createMediaSource()); + this.sourceUpdater.initializedEme(); this.sourceUpdater.createSourceBuffers({ audio: 'mp4a.40.2', video: 'avc1.4d400d' @@ -340,13 +346,15 @@ QUnit.test('setting audio timestamp offset without buffer is a noop', function(a }); QUnit.test('ready with a video buffer', function(assert) { + this.sourceUpdater.initializedEme(); this.sourceUpdater.createSourceBuffers({ video: 'avc1.4d400d' }); - assert.ok(this.sourceUpdater.ready(), 'source updater is ready'); + assert.ok(this.sourceUpdater.ready(), 'source updater has started'); }); QUnit.test('ready with an audio buffer', function(assert) { + this.sourceUpdater.initializedEme(); this.sourceUpdater.createSourceBuffers({ audio: 'mp4a.40.2' }); @@ -354,10 +362,24 @@ QUnit.test('ready with an audio buffer', function(assert) { }); QUnit.test('ready with both an audio and video buffer', function(assert) { + this.sourceUpdater.initializedEme(); + this.sourceUpdater.createSourceBuffers({ + video: 'avc1.4d400d', + audio: 'mp4a.40.2' + }); + assert.ok(this.sourceUpdater.ready(), 'source updater is ready'); +}); + +QUnit.test('ready once source buffers created and eme initialized', function(assert) { + // the module initializes by default + this.sourceUpdater.initializedEme_ = false; + assert.notOk(this.sourceUpdater.ready(), 'source updater is not ready'); this.sourceUpdater.createSourceBuffers({ video: 'avc1.4d400d', audio: 'mp4a.40.2' }); + assert.notOk(this.sourceUpdater.ready(), 'source updater is not ready'); + this.sourceUpdater.initializedEme(); assert.ok(this.sourceUpdater.ready(), 'source updater is ready'); }); diff --git a/test/test-helpers.js b/test/test-helpers.js index 3d8d52d82..3b1044f01 100644 --- a/test/test-helpers.js +++ b/test/test-helpers.js @@ -592,6 +592,12 @@ export const setupMediaSource = (mediaSource, sourceUpdater, options) => { videoEl.src = window.URL.createObjectURL(mediaSource); + // With the addition of the initialized EME requirement for source-updater start, a lot + // of tests which use the media source, but don't start at the top level of the plugin + // (where the EME initialization is done) faileddue to the source updatel never + // reporting as ready. This direct initialization works around the issue. + sourceUpdater.initializedEme(); + return new Promise((resolve, reject) => { mediaSource.addEventListener('sourceopen', () => { const codecs = {}; diff --git a/test/videojs-http-streaming.test.js b/test/videojs-http-streaming.test.js index 664225400..06398180e 100644 --- a/test/videojs-http-streaming.test.js +++ b/test/videojs-http-streaming.test.js @@ -38,7 +38,8 @@ import { LOCAL_STORAGE_KEY, expandDataUri, setupEmeOptions, - getAllPsshKeySystemsOptions + getAllPsshKeySystemsOptions, + waitForKeySessionCreation } from '../src/videojs-http-streaming'; import window from 'global/window'; // we need this so the plugin registers itself @@ -4376,7 +4377,7 @@ QUnit.test('populates quality levels list when available', function(assert) { ); }); -QUnit.test('configures eme for DASH if present on sourceUpdater ready', function(assert) { +QUnit.test('configures eme for DASH on source buffer creation', function(assert) { this.player.eme = { options: { previousSetting: 1 @@ -4425,7 +4426,7 @@ QUnit.test('configures eme for DASH if present on sourceUpdater ready', function } }; - this.player.tech_.vhs.masterPlaylistController_.sourceUpdater_.trigger('ready'); + this.player.tech_.vhs.masterPlaylistController_.sourceUpdater_.trigger('createdsourcebuffers'); assert.deepEqual(this.player.eme.options, { previousSetting: 1 @@ -4445,7 +4446,7 @@ QUnit.test('configures eme for DASH if present on sourceUpdater ready', function }, 'set source eme options'); }); -QUnit.test('configures eme for HLS if present on sourceUpdater ready', function(assert) { +QUnit.test('configures eme for HLS on source buffer creation', function(assert) { this.player.eme = { options: { previousSetting: 1 @@ -4479,7 +4480,7 @@ QUnit.test('configures eme for HLS if present on sourceUpdater ready', function( media: () => media }; - this.player.tech_.vhs.masterPlaylistController_.sourceUpdater_.trigger('ready'); + this.player.tech_.vhs.masterPlaylistController_.sourceUpdater_.trigger('createdsourcebuffers'); assert.deepEqual(this.player.eme.options, { previousSetting: 1 @@ -4499,7 +4500,7 @@ QUnit.test('configures eme for HLS if present on sourceUpdater ready', function( }, 'set source eme options'); }); -QUnit.test('integration: configures eme for DASH if present on sourceUpdater ready', function(assert) { +QUnit.test('integration: configures eme for DASH on source buffer creation', function(assert) { assert.timeout(3000); const done = assert.async(); @@ -4519,25 +4520,28 @@ QUnit.test('integration: configures eme for DASH if present on sourceUpdater rea }); openMediaSource(this.player, this.clock); - this.player.tech_.vhs.masterPlaylistController_.sourceUpdater_.on('ready', () => { - assert.deepEqual(this.player.eme.options, { - previousSetting: 1 - }, 'did not modify plugin options'); - - assert.deepEqual(this.player.currentSource(), { - src: 'dash.mpd', - type: 'application/dash+xml', - keySystems: { - keySystem1: { - url: 'url1', - audioContentType: 'audio/mp4;codecs="mp4a.40.2"', - videoContentType: 'video/mp4;codecs="avc1.420015"' + this.player.tech_.vhs.masterPlaylistController_.sourceUpdater_.on( + 'createdsourcebuffers', + () => { + assert.deepEqual(this.player.eme.options, { + previousSetting: 1 + }, 'did not modify plugin options'); + + assert.deepEqual(this.player.currentSource(), { + src: 'dash.mpd', + type: 'application/dash+xml', + keySystems: { + keySystem1: { + url: 'url1', + audioContentType: 'audio/mp4;codecs="mp4a.40.2"', + videoContentType: 'video/mp4;codecs="avc1.420015"' + } } - } - }, 'set source eme options'); + }, 'set source eme options'); - done(); - }); + done(); + } + ); this.standardXHRResponse(this.requests[0]); // this allows the audio playlist loader to load @@ -4550,7 +4554,7 @@ QUnit.test('integration: configures eme for DASH if present on sourceUpdater rea this.standardXHRResponse(this.requests[4], mp4AudioSegment()); }); -QUnit.test('integration: configures eme for HLS if present on sourceUpdater ready', function(assert) { +QUnit.test('integration: configures eme for HLS on source buffer creation', function(assert) { assert.timeout(3000); const done = assert.async(); @@ -4570,26 +4574,76 @@ QUnit.test('integration: configures eme for HLS if present on sourceUpdater read }); openMediaSource(this.player, this.clock); - this.player.tech_.vhs.masterPlaylistController_.sourceUpdater_.on('ready', () => { - assert.deepEqual(this.player.eme.options, { - previousSetting: 1 - }, 'did not modify plugin options'); - - assert.deepEqual(this.player.currentSource(), { - src: 'demuxed-two.m3u8', - type: 'application/x-mpegURL', - keySystems: { - keySystem1: { - url: 'url1', - audioContentType: 'audio/mp4;codecs="mp4a.40.2"', - videoContentType: 'video/mp4;codecs="avc1.420015"' + this.player.tech_.vhs.masterPlaylistController_.sourceUpdater_.on( + 'createdsourcebuffers', + () => { + assert.deepEqual(this.player.eme.options, { + previousSetting: 1 + }, 'did not modify plugin options'); + + assert.deepEqual(this.player.currentSource(), { + src: 'demuxed-two.m3u8', + type: 'application/x-mpegURL', + keySystems: { + keySystem1: { + url: 'url1', + audioContentType: 'audio/mp4;codecs="mp4a.40.2"', + videoContentType: 'video/mp4;codecs="avc1.420015"' + } } + }, 'set source eme options'); + + done(); + } + ); + + // master manifest + this.standardXHRResponse(this.requests.shift()); + + // video manifest + this.standardXHRResponse(this.requests.shift()); + + // audio manifest + this.standardXHRResponse(this.requests.shift()); + + // this allows the audio playlist loader to load + this.clock.tick(1); + + // respond to segement request to get trackinfo + this.standardXHRResponse(this.requests.shift(), videoSegment()); + this.standardXHRResponse(this.requests.shift(), audioSegment()); +}); + +QUnit.test('integration: updates source updater after eme init', function(assert) { + assert.expect(4); + assert.timeout(3000); + const done = assert.async(); + + this.player.src({ + src: 'demuxed-two.m3u8', + type: 'application/x-mpegURL', + keySystems: { + keySystem1: { + url: 'url1' } - }, 'set source eme options'); + } + }); + openMediaSource(this.player, this.clock); + const sourceUpdater = this.player.tech_.vhs.masterPlaylistController_.sourceUpdater_; + + sourceUpdater.on('ready', () => { + assert.ok(sourceUpdater.hasInitializedAnyEme(), 'updated source updater'); done(); }); + sourceUpdater.on( + 'createdsourcebuffers', + () => { + assert.notOk(sourceUpdater.hasInitializedAnyEme(), 'has not initialized eme yet'); + } + ); + // master manifest this.standardXHRResponse(this.requests.shift()); @@ -4607,6 +4661,64 @@ QUnit.test('integration: configures eme for HLS if present on sourceUpdater read this.standardXHRResponse(this.requests.shift(), audioSegment()); }); +QUnit.test('player error when key session creation rejects promise', function(assert) { + const done = assert.async(); + + this.player.error = (errorObject) => { + assert.deepEqual( + errorObject, + { + code: 3, + message: 'Failed to initialize media keys for EME' + }, + 'called player error with correct error' + ); + done(); + }; + this.player.eme = { + initializeMediaKeys: (keySystems, callback) => { + // calling back with an error should lead to promise rejection + callback({ + message: 'this is the error message' + }); + } + }; + this.player.src({ + src: 'manifest/master.mpd', + type: 'application/dash+xml', + keySystems: { + keySystem1: { + url: 'url1' + } + } + }); + + this.clock.tick(1); + + const media = { + attributes: { + CODECS: 'avc1.420015' + }, + contentProtection: { + keySystem1: { + pssh: 'test' + } + } + }; + + this.player.tech_.vhs.playlists = { + master: { playlists: [media] }, + media: () => media + }; + + this.player.tech_.vhs.masterPlaylistController_.mediaTypes_ = { + SUBTITLES: {}, + AUDIO: {} + }; + + this.player.tech_.vhs.masterPlaylistController_.sourceUpdater_.trigger('createdsourcebuffers'); +}); + QUnit.test( 'does not set source keySystems if keySystems not provided by source', function(assert) { @@ -5784,25 +5896,18 @@ QUnit.test('expandDataUri requires comma to parse', function(assert) { ); }); -QUnit.module('setupEmeOptions', { - beforeEach() { - this.origBrowser = videojs.browser; - // IE11 is a special case and should be tested separately - videojs.browser = videojs.mergeOptions(videojs.browser, { IE_VERSION: null }); - }, - afterEach() { - videojs.browser = this.origBrowser; - } -}); +QUnit.module('setupEmeOptions'); QUnit.test('no error if no eme and no key systems', function(assert) { const player = {}; const sourceKeySystems = null; const media = {}; const audioMedia = {}; - const mainPlaylists = []; - setupEmeOptions({ player, sourceKeySystems, media, audioMedia, mainPlaylists }); + assert.notOk( + setupEmeOptions({ player, sourceKeySystems, media, audioMedia }), + 'did not configure EME options' + ); assert.ok(true, 'no exception'); }); @@ -5811,7 +5916,6 @@ QUnit.test('log error if no eme and we have key systems', function(assert) { const sourceKeySystems = {}; const media = {}; const audioMedia = {}; - const mainPlaylists = []; const src = {}; const player = {currentSource: () => src}; @@ -5822,7 +5926,10 @@ QUnit.test('log error if no eme and we have key systems', function(assert) { logWarn = line; }; - setupEmeOptions({ player, sourceKeySystems, media, audioMedia, mainPlaylists }); + assert.notOk( + setupEmeOptions({ player, sourceKeySystems, media, audioMedia }), + 'did not configure EME options' + ); assert.equal(logWarn, 'DRM encrypted source cannot be decrypted without a DRM plugin', 'logs expected error'); assert.ok(src.hasOwnProperty('keySystems'), 'source key systems was set'); @@ -5830,29 +5937,11 @@ QUnit.test('log error if no eme and we have key systems', function(assert) { videojs.log.warn = origWarn; }); -QUnit.test('no initialize calls if no source key systems', function(assert) { - let numInitializeCalls = 0; - const player = { eme: { initializeMediaKeys: () => numInitializeCalls++ } }; - const sourceKeySystems = null; - const media = { - attributes: { CODECS: 'avc1.4d400d,mp4a.40.2' }, - contentProtection: { 'com.widevine.alpha': { pssh: new Uint8Array() } } - }; - const audioMedia = null; - const mainPlaylists = [media]; - - setupEmeOptions({ player, sourceKeySystems, media, audioMedia, mainPlaylists }); - - assert.equal(numInitializeCalls, 0, 'no initialize calls'); -}); - -QUnit.test('initializes for muxed playlist', function(assert) { - let numInitializeCalls = 0; +QUnit.test('converts options for muxed playlist', function(assert) { + const currentSource = {}; const player = { - eme: { initializeMediaKeys: () => numInitializeCalls++ }, - currentSource: () => { - return {}; - } + eme: {}, + currentSource: () => currentSource }; const sourceKeySystems = { 'com.widevine.alpha': { @@ -5864,159 +5953,68 @@ QUnit.test('initializes for muxed playlist', function(assert) { contentProtection: { 'com.widevine.alpha': { pssh: new Uint8Array() } } }; const audioMedia = null; - const mainPlaylists = [media]; - - setupEmeOptions({ player, sourceKeySystems, media, audioMedia, mainPlaylists }); - - assert.equal(numInitializeCalls, 1, 'one initialize call'); -}); -QUnit.test('initializes for each playlist for demuxed playlist', function(assert) { - let numInitializeCalls = 0; - const player = { - eme: { initializeMediaKeys: () => numInitializeCalls++ }, - currentSource: () => { - return {}; - } - }; - const sourceKeySystems = { - 'com.widevine.alpha': { - url: 'license-url' - } - }; - const media = { - attributes: { CODECS: 'avc1.4d400d,mp4a.40.2' }, - contentProtection: { 'com.widevine.alpha': { pssh: new Uint8Array() } } - }; - const audioMedia = { - attributes: {}, - contentProtection: { 'com.widevine.alpha': { pssh: new Uint8Array() } } - }; - const mainPlaylists = [media]; - - setupEmeOptions({ player, sourceKeySystems, media, audioMedia, mainPlaylists }); - - assert.equal(numInitializeCalls, 2, 'two initialize calls'); -}); - -QUnit.test('does not initialize if IE11', function(assert) { - videojs.browser.IE_VERSION = 11; - let numInitializeCalls = 0; - const player = { - eme: { initializeMediaKeys: () => numInitializeCalls++ }, - currentSource: () => { - return {}; - } - }; - const sourceKeySystems = { - 'com.widevine.alpha': { - url: 'license-url' - } - }; - const media = { - attributes: { CODECS: 'avc1.4d400d,mp4a.40.2' }, - contentProtection: { 'com.widevine.alpha': { pssh: new Uint8Array() } } - }; - const audioMedia = { - attributes: {}, - contentProtection: { 'com.widevine.alpha': { pssh: new Uint8Array() } } - }; - const mainPlaylists = [media]; - - setupEmeOptions({ player, sourceKeySystems, media, audioMedia, mainPlaylists }); - - assert.equal(numInitializeCalls, 0, 'no initialize calls'); -}); - -QUnit.test('initializes for each playlist', function(assert) { - let numInitializeCalls = 0; - const player = { - eme: { initializeMediaKeys: () => numInitializeCalls++ }, - currentSource: () => { - return {}; - } - }; - const sourceKeySystems = { - 'com.widevine.alpha': { - url: 'license-url' - } - }; - const media = { - attributes: { CODECS: 'avc1.4d400d,mp4a.40.2' }, - contentProtection: { 'com.widevine.alpha': { pssh: new Uint8Array() } } - }; - const media1 = { - attributes: { CODECS: 'avc1.4d400d,mp4a.40.2' }, - contentProtection: { 'com.widevine.alpha': { pssh: new Uint8Array() } } - }; - const audioMedia = { - attributes: {}, - contentProtection: { 'com.widevine.alpha': { pssh: new Uint8Array() } } - }; - const mainPlaylists = [media, media1]; - - setupEmeOptions({ player, sourceKeySystems, media, audioMedia, mainPlaylists }); + assert.ok( + setupEmeOptions({ player, sourceKeySystems, media, audioMedia }), + 'configured EME options' + ); - assert.equal(numInitializeCalls, 3, 'three initialize calls'); + assert.deepEqual( + currentSource.keySystems, + { + 'com.widevine.alpha': { + audioContentType: 'audio/mp4;codecs="mp4a.40.2"', + videoContentType: 'video/mp4;codecs="avc1.4d400d"', + pssh: new Uint8Array(), + url: 'license-url' + } + }, + 'eme keySystems options are corect' + ); }); -QUnit.test('initializes with correct options for each playlist', function(assert) { - const initializeCallOptions = []; +QUnit.test('converts options for demuxed playlists', function(assert) { + const currentSource = {}; const player = { - eme: { initializeMediaKeys: (options) => initializeCallOptions.push(options) }, - currentSource: () => { - return {}; - } + eme: {}, + currentSource: () => currentSource }; const sourceKeySystems = { 'com.widevine.alpha': { url: 'license-url' - }, - 'com.microsoft.playready': { - url: 'license-url' } }; const media = { attributes: { CODECS: 'avc1.4d400d,mp4a.40.2' }, - contentProtection: { - 'com.widevine.alpha': { pssh: new Uint8Array([0]) }, - 'com.microsoft.playready': { pssh: new Uint8Array([1]) } - } - }; - const media1 = { - attributes: { CODECS: 'avc1.4d400d,mp4a.40.2' }, - contentProtection: { - 'com.widevine.alpha': { pssh: new Uint8Array([2]) }, - 'com.microsoft.playready': { pssh: new Uint8Array([3]) } - } + contentProtection: { 'com.widevine.alpha': { pssh: new Uint8Array([1, 2, 3]) } } }; const audioMedia = { attributes: {}, - contentProtection: { - 'com.widevine.alpha': { pssh: new Uint8Array([4]) }, - 'com.microsoft.playready': { pssh: new Uint8Array([5]) } - } + contentProtection: { 'com.widevine.alpha': { pssh: new Uint8Array([4, 5, 6]) } } }; - const mainPlaylists = [media, media1]; - setupEmeOptions({ player, sourceKeySystems, media, audioMedia, mainPlaylists }); + assert.ok( + setupEmeOptions({ player, sourceKeySystems, media, audioMedia }), + 'configured eme options' + ); assert.deepEqual( - initializeCallOptions, - [{ - keySystems: media.contentProtection - }, { - keySystems: media1.contentProtection - }, { - keySystems: audioMedia.contentProtection - }], - 'called with correct values' + currentSource.keySystems, + { + 'com.widevine.alpha': { + audioContentType: 'audio/mp4;codecs="mp4a.40.2"', + videoContentType: 'video/mp4;codecs="avc1.4d400d"', + pssh: new Uint8Array([1, 2, 3]), + url: 'license-url' + } + }, + 'eme keySystems options are correct' ); }); QUnit.module('getAllPsshKeySystemsOptions'); -QUnit.test('empty array if no content proteciton in playlists', function(assert) { +QUnit.test('empty array if no content protection in playlists', function(assert) { assert.deepEqual( getAllPsshKeySystemsOptions( [{}, {}], @@ -6101,3 +6099,161 @@ QUnit.test('returns all key systems and pssh values', function(assert) { 'returned key systems and pssh values without other properties' ); }); + +QUnit.module('waitForKeySessionCreation', { + beforeEach(assert) { + const listeners = []; + + this.player = { + eme: { + initializeMediaKeys(options, callback) { + callback(); + } + }, + tech_: { + one(eventName, callback) { + listeners.push({ eventName, callback }); + }, + listeners + } + }; + this.completeOptions = { + player: this.player, + sourceKeySystems: { + 'com.widevine.alpha': { + url: 'license-url' + } + }, + audioMedia: null, + mainPlaylists: [{ + contentProtection: { + 'com.widevine.alpha': { pssh: new Uint8Array() } + } + }] + }; + } +}); + +QUnit.test('resolves on initializeMediaKeys', function(assert) { + const done = assert.async(); + + return waitForKeySessionCreation(this.completeOptions).then(() => { + assert.ok(true, 'resolved promise'); + done(); + }); +}); + +QUnit.test('resolves on all initializeMediaKeys', function(assert) { + const done = assert.async(); + const initializeCalls = []; + const initializeCallbacks = []; + + this.completeOptions.mainPlaylists = [{ + contentProtection: { + 'com.widevine.alpha': { pssh: new Uint8Array([0, 0, 0]) } + } + }, { + contentProtection: { + 'com.widevine.alpha': { pssh: new Uint8Array([1, 2, 3]) } + } + }]; + this.player.eme.initializeMediaKeys = (options, callback) => { + initializeCalls.push(options); + initializeCallbacks.push(callback); + }; + + waitForKeySessionCreation(this.completeOptions).then(() => { + assert.deepEqual( + initializeCalls, + [ + { keySystems: { 'com.widevine.alpha': { pssh: new Uint8Array([0, 0, 0]) } } }, + { keySystems: { 'com.widevine.alpha': { pssh: new Uint8Array([1, 2, 3]) } } } + ], + 'waited for both initialize calls to resolve' + ); + done(); + }); + + assert.equal(initializeCallbacks.length, 2, 'two initialize calls'); + initializeCallbacks[0](); + setTimeout(() => { + // call the second callback async to ensure the promise waits for all + initializeCallbacks[1](); + }, 1); +}); + +QUnit.test('resolves on all initializeMediaKeys when demuxed', function(assert) { + const done = assert.async(); + const initializeCalls = []; + const initializeCallbacks = []; + + this.completeOptions.mainPlaylists = [{ + contentProtection: { + 'com.widevine.alpha': { pssh: new Uint8Array([0, 0, 0]) } + } + }, { + contentProtection: { + 'com.widevine.alpha': { pssh: new Uint8Array([1, 2, 3]) } + } + }]; + this.completeOptions.audioMedia = { + contentProtection: { + 'com.widevine.alpha': { pssh: new Uint8Array([4, 5, 6]) } + } + }; + + this.player.eme.initializeMediaKeys = (options, callback) => { + initializeCalls.push(options); + initializeCallbacks.push(callback); + }; + + waitForKeySessionCreation(this.completeOptions).then(() => { + assert.deepEqual( + initializeCalls, + [ + { keySystems: { 'com.widevine.alpha': { pssh: new Uint8Array([0, 0, 0]) } } }, + { keySystems: { 'com.widevine.alpha': { pssh: new Uint8Array([1, 2, 3]) } } }, + { keySystems: { 'com.widevine.alpha': { pssh: new Uint8Array([4, 5, 6]) } } } + ], + 'waited for all video and audio initialize calls to resolve' + ); + done(); + }); + + assert.equal(initializeCallbacks.length, 3, 'three initialize calls'); + initializeCallbacks[0](); + setTimeout(() => { + // call the second callback async to ensure the promise waits for all + initializeCallbacks[1](); + setTimeout(() => { + // call the third callback async to ensure the promise waits for all + initializeCallbacks[2](); + }, 1); + }, 1); +}); + +QUnit.test('resolves on keysessioncreated', function(assert) { + const done = assert.async(); + + // never allow initializeMediaKeys to finish + this.player.eme.initializeMediaKeys = (options, callback) => {}; + + waitForKeySessionCreation(this.completeOptions).then(() => { + done(); + }); + + assert.equal(this.player.tech_.listeners.length, 1, 'one listener'); + assert.equal(this.player.tech_.listeners[0].eventName, 'keysessioncreated'); + this.player.tech_.listeners[0].callback(); +}); + +QUnit.test('resolves if no initializeMediaKeys', function(assert) { + const done = assert.async(); + + delete this.player.eme.initializeMediaKeys; + + return waitForKeySessionCreation(this.completeOptions).then(() => { + assert.ok(true, 'resolved promise'); + done(); + }); +}); From 5f1490952d058ef7cadc46d6de40241069d26afb Mon Sep 17 00:00:00 2001 From: Gary Katsevman Date: Tue, 1 Dec 2020 16:36:46 -0500 Subject: [PATCH 035/399] feat: update to mux.js 5.7.0 (#1014) - Fixes issue with baseTime 0 - Initial support for CEA 708 captions - Support for SIDX v1 boxes - opus/flac support in fmp4 playlists Closes #1001, fixes #909 --- package-lock.json | 11 ++++++++--- package.json | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index f3f857ac4..a7ece8e3d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1296,6 +1296,11 @@ "global": "^4.3.2", "xmldom": "^0.1.27" } + }, + "mux.js": { + "version": "5.6.7", + "resolved": "https://registry.npmjs.org/mux.js/-/mux.js-5.6.7.tgz", + "integrity": "sha512-YSr6B8MUgE4S18MptbY2XM+JKGbw9JDkgs7YkuE/T2fpDKjOhZfb/nD6vmsVxvLYOExWNaQn1UGBp6PGsnTtew==" } } }, @@ -7167,9 +7172,9 @@ "dev": true }, "mux.js": { - "version": "5.6.7", - "resolved": "https://registry.npmjs.org/mux.js/-/mux.js-5.6.7.tgz", - "integrity": "sha512-YSr6B8MUgE4S18MptbY2XM+JKGbw9JDkgs7YkuE/T2fpDKjOhZfb/nD6vmsVxvLYOExWNaQn1UGBp6PGsnTtew==" + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/mux.js/-/mux.js-5.7.0.tgz", + "integrity": "sha512-SINb/qE0iN7YdpbGHtcj8JoHAJWXITUcN9ZCmakThZ8pVGvWukBMCDfJbEVmY2+GqmmrUkLkwUN9Ec2YLUSbuA==" }, "nanomatch": { "version": "1.2.13", diff --git a/package.json b/package.json index 35f5231db..cb5d611b8 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "global": "^4.3.2", "m3u8-parser": "4.5.0", "mpd-parser": "0.15.0", - "mux.js": "5.6.7", + "mux.js": "5.7.0", "video.js": "^6 || ^7" }, "devDependencies": { From b1c2969a17e39fa174994a699927f17b23dc33fd Mon Sep 17 00:00:00 2001 From: Brandon Casey <2381475+brandonocasey@users.noreply.github.com> Date: Wed, 2 Dec 2020 13:42:59 -0500 Subject: [PATCH 036/399] fix: prevent double source buffer ready on IE11 (#1015) --- src/source-updater.js | 18 ++++++++++++++---- test/videojs-http-streaming.test.js | 11 +++++++++-- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/source-updater.js b/src/source-updater.js index d8b14dd16..68a8a175a 100644 --- a/src/source-updater.js +++ b/src/source-updater.js @@ -337,13 +337,12 @@ export default class SourceUpdater extends videojs.EventTarget { }; this.createdSourceBuffers_ = false; this.initializedEme_ = false; + this.triggeredReady_ = false; } initializedEme() { this.initializedEme_ = true; - if (this.ready()) { - this.trigger('ready'); - } + this.triggerReady(); } hasCreatedSourceBuffers() { @@ -371,7 +370,18 @@ export default class SourceUpdater extends videojs.EventTarget { this.addOrChangeSourceBuffers(codecs); this.createdSourceBuffers_ = true; this.trigger('createdsourcebuffers'); - if (this.ready()) { + this.triggerReady(); + } + + triggerReady() { + // only allow ready to be triggered once, this prevents the case + // where: + // 1. we trigger createdsourcebuffers + // 2. ie 11 synchronously initializates eme + // 3. the synchronous initialization causes us to trigger ready + // 4. We go back to the ready check in createSourceBuffers and ready is triggered again. + if (this.ready() && !this.triggeredReady_) { + this.triggeredReady_ = true; this.trigger('ready'); } } diff --git a/test/videojs-http-streaming.test.js b/test/videojs-http-streaming.test.js index 06398180e..22033fab5 100644 --- a/test/videojs-http-streaming.test.js +++ b/test/videojs-http-streaming.test.js @@ -4640,7 +4640,14 @@ QUnit.test('integration: updates source updater after eme init', function(assert sourceUpdater.on( 'createdsourcebuffers', () => { - assert.notOk(sourceUpdater.hasInitializedAnyEme(), 'has not initialized eme yet'); + let expected = false; + + // IE initializes eme syncronously directly after source buffer + // creation + if (videojs.browser.IE_VERSION) { + expected = true; + } + assert.equal(sourceUpdater.hasInitializedAnyEme(), expected, 'correct eme state'); } ); @@ -4661,7 +4668,7 @@ QUnit.test('integration: updates source updater after eme init', function(assert this.standardXHRResponse(this.requests.shift(), audioSegment()); }); -QUnit.test('player error when key session creation rejects promise', function(assert) { +QUnit[testOrSkip]('player error when key session creation rejects promise', function(assert) { const done = assert.async(); this.player.error = (errorObject) => { From f7b528cf7f8c1c2391e264472d8c375be18e35b8 Mon Sep 17 00:00:00 2001 From: Brandon Casey <2381475+brandonocasey@users.noreply.github.com> Date: Wed, 2 Dec 2020 14:07:53 -0500 Subject: [PATCH 037/399] fix: keep running the minimumUpdatePeriod unless cancelled or changed (#1016) --- src/dash-playlist-loader.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dash-playlist-loader.js b/src/dash-playlist-loader.js index 7a0772a12..9ae3f8263 100644 --- a/src/dash-playlist-loader.js +++ b/src/dash-playlist-loader.js @@ -649,6 +649,7 @@ export default class DashPlaylistLoader extends EventTarget { const createMUPTimeout = (mup) => { this.minimumUpdatePeriodTimeout_ = window.setTimeout(() => { this.trigger('minimumUpdatePeriod'); + createMUPTimeout(mup); }, mup); }; From ad5c2704319d29971c5d50db04b16f3970df547a Mon Sep 17 00:00:00 2001 From: dario-fiore <32436485+dario-fiore@users.noreply.github.com> Date: Wed, 2 Dec 2020 21:55:32 +0100 Subject: [PATCH 038/399] feat(playback watcher): Configurable live seekable window (#997) --- README.md | 6 ++++++ src/playback-watcher.js | 3 ++- src/videojs-http-streaming.js | 23 +++++++++++++++++------ test/playback-watcher.test.js | 20 ++++++++++++++++++++ 4 files changed, 45 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 8aa7229f2..66742f91d 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,7 @@ Video.js Compatibility: 6.0, 7.0 - [customTagMappers](#customtagmappers) - [cacheEncryptionKeys](#cacheencryptionkeys) - [handlePartialData](#handlepartialdata) + - [liveRangeSafeTimeDelta](#liverangesafetimedelta) - [Runtime Properties](#runtime-properties) - [vhs.playlists.master](#vhsplaylistsmaster) - [vhs.playlists.media](#vhsplaylistsmedia) @@ -451,6 +452,11 @@ This option defaults to `false`. * Default: `false` * Use partial appends in the transmuxer and segment loader +##### liveRangeSafeTimeDelta +* Type: `number`, +* Default: [`SAFE_TIME_DELTA`](https://github.com/videojs/http-streaming/blob/e7cb63af010779108336eddb5c8fd138d6390e95/src/ranges.js#L17) +* Allow to re-define length (in seconds) of time delta when you compare current time and the end of the buffered range. + ### Runtime Properties Runtime properties are attached to the tech object when HLS is in use. You can get a reference to the VHS source handler like this: diff --git a/src/playback-watcher.js b/src/playback-watcher.js index 6ebb7ed55..33cac2552 100644 --- a/src/playback-watcher.js +++ b/src/playback-watcher.js @@ -75,6 +75,7 @@ export default class PlaybackWatcher { this.tech_ = options.tech; this.seekable = options.seekable; this.allowSeeksWithinUnsafeLiveWindow = options.allowSeeksWithinUnsafeLiveWindow; + this.liveRangeSafeTimeDelta = options.liveRangeSafeTimeDelta; this.media = options.media; this.consecutiveUpdates = 0; @@ -502,7 +503,7 @@ export default class PlaybackWatcher { if (seekable.length && // can't fall before 0 and 0 seekable start identifies VOD stream seekable.start(0) > 0 && - currentTime < seekable.start(0) - Ranges.SAFE_TIME_DELTA) { + currentTime < seekable.start(0) - this.liveRangeSafeTimeDelta) { return true; } diff --git a/src/videojs-http-streaming.js b/src/videojs-http-streaming.js index e05d6e351..9ec9b12ec 100644 --- a/src/videojs-http-streaming.js +++ b/src/videojs-http-streaming.js @@ -32,6 +32,7 @@ import { } from './playlist-selectors.js'; import {isAudioCodec, isVideoCodec, browserSupportsCodec} from '@videojs/vhs-utils/dist/codecs.js'; import logger from './util/logger'; +import {SAFE_TIME_DELTA} from './ranges'; // IMPORTANT: // keep these at the bottom they are replaced at build time @@ -673,7 +674,8 @@ class VhsHandler extends Component { 'handlePartialData', 'playlistSelector', 'initialPlaylistSelector', - 'experimentalBufferBasedABR' + 'experimentalBufferBasedABR', + 'liveRangeSafeTimeDelta' ].forEach((option) => { if (typeof this.source_[option] !== 'undefined') { this.options_[option] = this.source_[option]; @@ -706,11 +708,20 @@ class VhsHandler extends Component { }; this.masterPlaylistController_ = new MasterPlaylistController(this.options_); - this.playbackWatcher_ = new PlaybackWatcher(videojs.mergeOptions(this.options_, { - seekable: () => this.seekable(), - media: () => this.masterPlaylistController_.media(), - masterPlaylistController: this.masterPlaylistController_ - })); + + const playbackWatcherOptions = videojs.mergeOptions( + { + liveRangeSafeTimeDelta: SAFE_TIME_DELTA + }, + this.options_, + { + seekable: () => this.seekable(), + media: () => this.masterPlaylistController_.media(), + masterPlaylistController: this.masterPlaylistController_ + } + ); + + this.playbackWatcher_ = new PlaybackWatcher(playbackWatcherOptions); this.masterPlaylistController_.on('error', () => { const player = videojs.players[this.tech_.options_.playerId]; diff --git a/test/playback-watcher.test.js b/test/playback-watcher.test.js index ab127f359..2cd511419 100644 --- a/test/playback-watcher.test.js +++ b/test/playback-watcher.test.js @@ -13,6 +13,7 @@ import { } from '../src/playback-watcher'; // needed for plugin registration import '../src/videojs-http-streaming'; +import { SAFE_TIME_DELTA } from '../src/ranges'; let monitorCurrentTime_; @@ -1184,6 +1185,8 @@ QUnit.test('skips gap from muxed video underflow', function(assert) { }); QUnit.test('detects live window falloff', function(assert) { + this.playbackWatcher.liveRangeSafeTimeDelta = SAFE_TIME_DELTA; + const beforeSeekableWindow_ = this.playbackWatcher.beforeSeekableWindow_.bind(this.playbackWatcher); @@ -1222,6 +1225,23 @@ QUnit.test('detects live window falloff', function(assert) { ); }); +QUnit.test('respects liveRangeSafeTimeDelta flag', function(assert) { + this.playbackWatcher.liveRangeSafeTimeDelta = 1; + + const beforeSeekableWindow_ = + this.playbackWatcher.beforeSeekableWindow_.bind(this.playbackWatcher); + + assert.ok( + beforeSeekableWindow_(videojs.createTimeRanges([[12, 20]]), 10), + 'true if playlist live and current time before seekable' + ); + + assert.ok( + !beforeSeekableWindow_(videojs.createTimeRanges([]), 10), + 'false if no seekable range' + ); +}); + QUnit.test('detects beyond seekable window for VOD', function(assert) { const playlist = { endList: true, From bf6369266ce6030acd503a6cde0a6f6e67cb7141 Mon Sep 17 00:00:00 2001 From: Brandon Casey <2381475+brandonocasey@users.noreply.github.com> Date: Wed, 2 Dec 2020 17:34:22 -0500 Subject: [PATCH 039/399] fix: support tracks with id 0 for fmp4 playlists (#1018) --- src/media-segment-request.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/media-segment-request.js b/src/media-segment-request.js index 041f7b948..71ab09952 100644 --- a/src/media-segment-request.js +++ b/src/media-segment-request.js @@ -194,7 +194,7 @@ const handleInitSegmentResponse = segment.map.tracks[track.type] = track; - if (track.id && track.timescale) { + if (typeof track.id === 'number' && track.timescale) { segment.map.timescales = segment.map.timescales || {}; segment.map.timescales[track.id] = track.timescale; } From 20cc4a386b9b73eb22c49c9a0c842a317b3c188d Mon Sep 17 00:00:00 2001 From: Brandon Casey <2381475+brandonocasey@users.noreply.github.com> Date: Fri, 4 Dec 2020 10:41:10 -0500 Subject: [PATCH 040/399] chore: skip duplicate ci workflows (#1021) --- .github/workflows/ci.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 355a71156..d931702ba 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,7 +3,21 @@ name: ci on: [push, pull_request] jobs: + should-skip: + continue-on-error: true + runs-on: ubuntu-latest + # Map a step output to a job output + outputs: + should-skip-job: ${{ steps.skip-check.outputs.should_skip }} + steps: + - id: skip-check + uses: fkirc/skip-duplicate-actions@v2.1.0 + with: + github_token: ${{ github.token }} + ci: + needs: should-skip + if: ${{ needs.should-skip.outputs.should-skip-job != 'true'}} env: BROWSER_STACK_USERNAME: ${{ secrets.BROWSER_STACK_USERNAME }} BROWSER_STACK_ACCESS_KEY: ${{ secrets.BROWSER_STACK_ACCESS_KEY }} From 124834a2c219fbab2d9568bb9ad31f7003444353 Mon Sep 17 00:00:00 2001 From: Brandon Casey <2381475+brandonocasey@users.noreply.github.com> Date: Fri, 4 Dec 2020 11:41:57 -0500 Subject: [PATCH 041/399] fix: filter out unsupported subtitles for dash (#962) --- package-lock.json | 462 ++++++++++++------------ package.json | 2 +- src/master-playlist-controller.js | 28 +- src/media-groups.js | 5 + src/util/codecs.js | 8 + test/master-playlist-controller.test.js | 20 +- 6 files changed, 284 insertions(+), 241 deletions(-) diff --git a/package-lock.json b/package-lock.json index a7ece8e3d..b44130e20 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,25 +14,25 @@ } }, "@babel/compat-data": { - "version": "7.12.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.12.5.tgz", - "integrity": "sha512-DTsS7cxrsH3by8nqQSpFSyjSfSYl57D6Cf4q8dW3LK83tBKBDCkfcay1nYkXq1nIHXnpX8WMMb/O25HOy3h1zg==", + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.12.7.tgz", + "integrity": "sha512-YaxPMGs/XIWtYqrdEOZOCPsVWfEoriXopnsz3/i7apYPXQ3698UFhS6dVT1KN5qOsWmVgw/FOrmQgpRaZayGsw==", "dev": true }, "@babel/core": { - "version": "7.12.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.3.tgz", - "integrity": "sha512-0qXcZYKZp3/6N2jKYVxZv0aNCsxTSVCiK72DTiTYZAu7sjg73W0/aynWjMbiGd87EQL4WyA8reiJVh92AVla9g==", + "version": "7.12.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.9.tgz", + "integrity": "sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ==", "dev": true, "requires": { "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.12.1", + "@babel/generator": "^7.12.5", "@babel/helper-module-transforms": "^7.12.1", - "@babel/helpers": "^7.12.1", - "@babel/parser": "^7.12.3", - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.12.1", - "@babel/types": "^7.12.1", + "@babel/helpers": "^7.12.5", + "@babel/parser": "^7.12.7", + "@babel/template": "^7.12.7", + "@babel/traverse": "^7.12.9", + "@babel/types": "^7.12.7", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.1", @@ -44,15 +44,15 @@ }, "dependencies": { "@babel/parser": { - "version": "7.12.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.5.tgz", - "integrity": "sha512-FVM6RZQ0mn2KCf1VUED7KepYeUWoVShczewOCfm3nzoBybaih51h+sYVVGthW9M6lPByEPTQf+xm27PBdlpwmQ==", + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.7.tgz", + "integrity": "sha512-oWR02Ubp4xTLCAqPRiNIuMVgNO5Aif/xpXtabhzW2HWUD47XJsAB4Zd/Rg30+XeQA3juXigV7hlquOTmwqLiwg==", "dev": true }, "debug": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.0.tgz", - "integrity": "sha512-jjO6JD2rKfiZQnBoRzhRTbXjHLGLfH+UtGkWLc/UXAh/rzZMyjbgn0NcfFpqT8nd1kTtFnDiJcrIFkq4UKeJVg==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", "dev": true, "requires": { "ms": "2.1.2" @@ -150,13 +150,12 @@ } }, "@babel/helper-create-regexp-features-plugin": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.1.tgz", - "integrity": "sha512-rsZ4LGvFTZnzdNZR5HZdmJVuXK8834R5QkF3WvcnBhrlVtF0HSIUC6zbreL9MgjTywhKokn8RIYRiq99+DLAxA==", + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.7.tgz", + "integrity": "sha512-idnutvQPdpbduutvi3JVfEgcVIHooQnhvhx0Nk9isOINOIGYkZea1Pk2JlJRiUnMefrlvr0vkByATBY/mB4vjQ==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.10.4", - "@babel/helper-regex": "^7.10.4", "regexpu-core": "^4.7.1" } }, @@ -210,12 +209,12 @@ } }, "@babel/helper-member-expression-to-functions": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.1.tgz", - "integrity": "sha512-k0CIe3tXUKTRSoEx1LQEPFU9vRQfqHtl+kf8eNnDqb4AUJEy5pz6aIiog+YWtVm2jpggjS1laH68bPsR+KWWPQ==", + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.7.tgz", + "integrity": "sha512-DCsuPyeWxeHgh1Dus7APn7iza42i/qXqiFPWyBDdOFtvS581JQePsc1F/nD+fHrcswhLlRc2UpYS1NwERxZhHw==", "dev": true, "requires": { - "@babel/types": "^7.12.1" + "@babel/types": "^7.12.7" } }, "@babel/helper-module-imports": { @@ -245,12 +244,12 @@ } }, "@babel/helper-optimise-call-expression": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz", - "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==", + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.7.tgz", + "integrity": "sha512-I5xc9oSJ2h59OwyUqjv95HRyzxj53DAubUERgQMrpcCEYQyToeHA+NEcUEsVWB4j53RDeskeBJ0SgRAYHDBckw==", "dev": true, "requires": { - "@babel/types": "^7.10.4" + "@babel/types": "^7.12.7" } }, "@babel/helper-plugin-utils": { @@ -259,15 +258,6 @@ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", "dev": true }, - "@babel/helper-regex": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.10.5.tgz", - "integrity": "sha512-68kdUAzDrljqBrio7DYAEgCoJHxppJOERHOgOrDN7WjOzP0ZQ1LsSDRXcemzVZaLvjaJsJEESb6qt+znNuENDg==", - "dev": true, - "requires": { - "lodash": "^4.17.19" - } - }, "@babel/helper-remap-async-to-generator": { "version": "7.12.1", "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.12.1.tgz", @@ -442,9 +432,9 @@ } }, "@babel/plugin-proposal-numeric-separator": { - "version": "7.12.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.5.tgz", - "integrity": "sha512-UiAnkKuOrCyjZ3sYNHlRlfuZJbBHknMQ9VMwVeX97Ofwx7RpD6gS2HfqTCh8KNUQgcOm8IKt103oR4KIjh7Q8g==", + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.7.tgz", + "integrity": "sha512-8c+uy0qmnRTeukiGsjLGy6uVs/TFjJchGXUeBqlG4VWYOdJWkhhVPdQ3uHwbmalfJwv2JsV0qffXP4asRfL2SQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.10.4", @@ -473,9 +463,9 @@ } }, "@babel/plugin-proposal-optional-chaining": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.1.tgz", - "integrity": "sha512-c2uRpY6WzaVDzynVY9liyykS+kVU+WRZPMPYpkelXH8KBt1oXoI89kPbZKKG/jDT5UK92FTW2fZkZaJhdiBabw==", + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.7.tgz", + "integrity": "sha512-4ovylXZ0PWmwoOvhU2vhnzVNnm88/Sm9nx7V8BPgMvAzn5zDou3/Awy0EjglyubVHasJj+XCEkr/r1X3P5elCA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.10.4", @@ -908,13 +898,12 @@ } }, "@babel/plugin-transform-sticky-regex": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.12.1.tgz", - "integrity": "sha512-CiUgKQ3AGVk7kveIaPEET1jNDhZZEl1RPMWdTBE1799bdz++SwqDHStmxfCtDfBhQgCl38YRiSnrMuUMZIWSUQ==", + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.12.7.tgz", + "integrity": "sha512-VEiqZL5N/QvDbdjfYQBhruN0HYjSPjC4XkeqW4ny/jNtH9gcbgaqBIXYEZCNnESMAGs0/K/R7oFGMhOyu/eIxg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-regex": "^7.10.4" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-template-literals": { @@ -955,14 +944,14 @@ } }, "@babel/preset-env": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.12.1.tgz", - "integrity": "sha512-H8kxXmtPaAGT7TyBvSSkoSTUK6RHh61So05SyEbpmr0MCZrsNYn7mGMzzeYoOUCdHzww61k8XBft2TaES+xPLg==", + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.12.7.tgz", + "integrity": "sha512-OnNdfAr1FUQg7ksb7bmbKoby4qFOHw6DKWWUNB9KqnnCldxhxJlP+21dpyaWFmf2h0rTbOkXJtAGevY3XW1eew==", "dev": true, "requires": { - "@babel/compat-data": "^7.12.1", - "@babel/helper-compilation-targets": "^7.12.1", - "@babel/helper-module-imports": "^7.12.1", + "@babel/compat-data": "^7.12.7", + "@babel/helper-compilation-targets": "^7.12.5", + "@babel/helper-module-imports": "^7.12.5", "@babel/helper-plugin-utils": "^7.10.4", "@babel/helper-validator-option": "^7.12.1", "@babel/plugin-proposal-async-generator-functions": "^7.12.1", @@ -972,10 +961,10 @@ "@babel/plugin-proposal-json-strings": "^7.12.1", "@babel/plugin-proposal-logical-assignment-operators": "^7.12.1", "@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.1", - "@babel/plugin-proposal-numeric-separator": "^7.12.1", + "@babel/plugin-proposal-numeric-separator": "^7.12.7", "@babel/plugin-proposal-object-rest-spread": "^7.12.1", "@babel/plugin-proposal-optional-catch-binding": "^7.12.1", - "@babel/plugin-proposal-optional-chaining": "^7.12.1", + "@babel/plugin-proposal-optional-chaining": "^7.12.7", "@babel/plugin-proposal-private-methods": "^7.12.1", "@babel/plugin-proposal-unicode-property-regex": "^7.12.1", "@babel/plugin-syntax-async-generators": "^7.8.0", @@ -1017,14 +1006,14 @@ "@babel/plugin-transform-reserved-words": "^7.12.1", "@babel/plugin-transform-shorthand-properties": "^7.12.1", "@babel/plugin-transform-spread": "^7.12.1", - "@babel/plugin-transform-sticky-regex": "^7.12.1", + "@babel/plugin-transform-sticky-regex": "^7.12.7", "@babel/plugin-transform-template-literals": "^7.12.1", "@babel/plugin-transform-typeof-symbol": "^7.12.1", "@babel/plugin-transform-unicode-escapes": "^7.12.1", "@babel/plugin-transform-unicode-regex": "^7.12.1", "@babel/preset-modules": "^0.1.3", - "@babel/types": "^7.12.1", - "core-js-compat": "^3.6.2", + "@babel/types": "^7.12.7", + "core-js-compat": "^3.7.0", "semver": "^5.5.0" }, "dependencies": { @@ -1058,51 +1047,51 @@ } }, "@babel/template": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", - "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.7.tgz", + "integrity": "sha512-GkDzmHS6GV7ZeXfJZ0tLRBhZcMcY0/Lnb+eEbXDBfCAcZCjrZKe6p3J4we/D24O9Y8enxWAg1cWwof59yLh2ow==", "dev": true, "requires": { "@babel/code-frame": "^7.10.4", - "@babel/parser": "^7.10.4", - "@babel/types": "^7.10.4" + "@babel/parser": "^7.12.7", + "@babel/types": "^7.12.7" }, "dependencies": { "@babel/parser": { - "version": "7.12.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.5.tgz", - "integrity": "sha512-FVM6RZQ0mn2KCf1VUED7KepYeUWoVShczewOCfm3nzoBybaih51h+sYVVGthW9M6lPByEPTQf+xm27PBdlpwmQ==", + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.7.tgz", + "integrity": "sha512-oWR02Ubp4xTLCAqPRiNIuMVgNO5Aif/xpXtabhzW2HWUD47XJsAB4Zd/Rg30+XeQA3juXigV7hlquOTmwqLiwg==", "dev": true } } }, "@babel/traverse": { - "version": "7.12.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.5.tgz", - "integrity": "sha512-xa15FbQnias7z9a62LwYAA5SZZPkHIXpd42C6uW68o8uTuua96FHZy1y61Va5P/i83FAAcMpW8+A/QayntzuqA==", + "version": "7.12.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.9.tgz", + "integrity": "sha512-iX9ajqnLdoU1s1nHt36JDI9KG4k+vmI8WgjK5d+aDTwQbL2fUnzedNedssA645Ede3PM2ma1n8Q4h2ohwXgMXw==", "dev": true, "requires": { "@babel/code-frame": "^7.10.4", "@babel/generator": "^7.12.5", "@babel/helper-function-name": "^7.10.4", "@babel/helper-split-export-declaration": "^7.11.0", - "@babel/parser": "^7.12.5", - "@babel/types": "^7.12.5", + "@babel/parser": "^7.12.7", + "@babel/types": "^7.12.7", "debug": "^4.1.0", "globals": "^11.1.0", "lodash": "^4.17.19" }, "dependencies": { "@babel/parser": { - "version": "7.12.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.5.tgz", - "integrity": "sha512-FVM6RZQ0mn2KCf1VUED7KepYeUWoVShczewOCfm3nzoBybaih51h+sYVVGthW9M6lPByEPTQf+xm27PBdlpwmQ==", + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.7.tgz", + "integrity": "sha512-oWR02Ubp4xTLCAqPRiNIuMVgNO5Aif/xpXtabhzW2HWUD47XJsAB4Zd/Rg30+XeQA3juXigV7hlquOTmwqLiwg==", "dev": true }, "debug": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.0.tgz", - "integrity": "sha512-jjO6JD2rKfiZQnBoRzhRTbXjHLGLfH+UtGkWLc/UXAh/rzZMyjbgn0NcfFpqT8nd1kTtFnDiJcrIFkq4UKeJVg==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", "dev": true, "requires": { "ms": "2.1.2" @@ -1117,9 +1106,9 @@ } }, "@babel/types": { - "version": "7.12.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.6.tgz", - "integrity": "sha512-hwyjw6GvjBLiyy3W0YQf0Z5Zf4NpYejUnKFcfcUhZCSffoBBp30w6wP2Wn6pk31jMYZvcOrB/1b7cGXvEoKogA==", + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.7.tgz", + "integrity": "sha512-MNyI92qZq6jrQkXvtIiykvl4WtoRrVV9MPn+ZfsoEENjiWcBQ3ZSHrkxnJWgWtLX3XXqX5hrSQ+X69wkmesXuQ==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.10.4", @@ -1233,9 +1222,9 @@ "dev": true }, "@types/node": { - "version": "14.14.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.7.tgz", - "integrity": "sha512-Zw1vhUSQZYw+7u5dAwNbIA9TuTotpzY/OF7sJM9FqPOF3SPjKnxrjoTktXDZgUjybf4cWVBP7O8wvKdSaGHweg==", + "version": "14.14.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.10.tgz", + "integrity": "sha512-J32dgx2hw8vXrSbu4ZlVhn1Nm3GbeCFNw2FWL8S5QKucHGY0cyNwjdQdO+KMBZ4wpmC7KhLCiNsdk1RFRIYUQQ==", "dev": true }, "@types/normalize-package-data": { @@ -1272,9 +1261,9 @@ } }, "@videojs/http-streaming": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/@videojs/http-streaming/-/http-streaming-2.2.4.tgz", - "integrity": "sha512-gzT46RpAEegOhMId/zZ6uXCVGDMPOv8qmoTykBuvd6/4lVM3lZ1ZJCq0kytAkisDuDKipy93gP46oZEtonlc/Q==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@videojs/http-streaming/-/http-streaming-2.3.0.tgz", + "integrity": "sha512-nMEnku3BSGIrB4dpo4LWCbDH9NqnGhY1cop0bn9Kwy63VJKG5B3d2mnS4N0OibNpY6I+mJKTqJLSRW9KYBs2TA==", "requires": { "@babel/runtime": "^7.5.5", "@videojs/vhs-utils": "^2.2.1", @@ -1286,6 +1275,16 @@ "video.js": "^6 || ^7" }, "dependencies": { + "@videojs/vhs-utils": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@videojs/vhs-utils/-/vhs-utils-2.2.1.tgz", + "integrity": "sha512-9Qbwx3LAdkG1jh2HKfninjXDxVZCeaoPcmct/bUcDRmLej68Z9XhLe5d2a9fy1qB+UuQwWg7YySASesWavYNjQ==", + "requires": { + "@babel/runtime": "^7.5.5", + "global": "^4.3.2", + "url-toolkit": "^2.1.6" + } + }, "mpd-parser": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/mpd-parser/-/mpd-parser-0.14.0.tgz", @@ -1305,9 +1304,9 @@ } }, "@videojs/vhs-utils": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@videojs/vhs-utils/-/vhs-utils-2.2.1.tgz", - "integrity": "sha512-9Qbwx3LAdkG1jh2HKfninjXDxVZCeaoPcmct/bUcDRmLej68Z9XhLe5d2a9fy1qB+UuQwWg7YySASesWavYNjQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@videojs/vhs-utils/-/vhs-utils-2.3.0.tgz", + "integrity": "sha512-ThSmm91S7tuIJ757ON50K4y7S/bvKN4+B0tu303gCOxaG57PoP1UvPfMQZ90XGhxwNgngexVojOqbBHhTvXVHQ==", "requires": { "@babel/runtime": "^7.5.5", "global": "^4.3.2", @@ -1383,6 +1382,18 @@ "@videojs/vhs-utils": "^2.2.1", "global": "^4.3.2", "pkcs7": "^1.0.4" + }, + "dependencies": { + "@videojs/vhs-utils": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@videojs/vhs-utils/-/vhs-utils-2.2.1.tgz", + "integrity": "sha512-9Qbwx3LAdkG1jh2HKfninjXDxVZCeaoPcmct/bUcDRmLej68Z9XhLe5d2a9fy1qB+UuQwWg7YySASesWavYNjQ==", + "requires": { + "@babel/runtime": "^7.5.5", + "global": "^4.3.2", + "url-toolkit": "^2.1.6" + } + } } }, "after": { @@ -1987,16 +1998,16 @@ } }, "browserslist": { - "version": "4.14.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.14.7.tgz", - "integrity": "sha512-BSVRLCeG3Xt/j/1cCGj1019Wbty0H+Yvu2AOuZSuoaUWn3RatbL33Cxk+Q4jRMRAbOm0p7SLravLjpnT6s0vzQ==", + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.15.0.tgz", + "integrity": "sha512-IJ1iysdMkGmjjYeRlDU8PQejVwxvVO5QOfXH7ylW31GO6LwNRSmm/SgRXtNsEXqMLl2e+2H5eEJ7sfynF8TCaQ==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001157", + "caniuse-lite": "^1.0.30001164", "colorette": "^1.2.1", - "electron-to-chromium": "^1.3.591", + "electron-to-chromium": "^1.3.612", "escalade": "^3.1.1", - "node-releases": "^1.1.66" + "node-releases": "^1.1.67" } }, "browserstack": { @@ -2123,15 +2134,15 @@ } }, "caniuse-lite": { - "version": "1.0.30001157", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001157.tgz", - "integrity": "sha512-gOerH9Wz2IRZ2ZPdMfBvyOi3cjaz4O4dgNwPGzx8EhqAs4+2IL/O+fJsbt+znSigujoZG8bVcIAUM/I/E5K3MA==", + "version": "1.0.30001164", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001164.tgz", + "integrity": "sha512-G+A/tkf4bu0dSp9+duNiXc7bGds35DioCyC6vgK2m/rjA4Krpy5WeZgZyfH2f0wj2kI6yAWWucyap6oOwmY1mg==", "dev": true }, "caporal": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/caporal/-/caporal-1.3.0.tgz", - "integrity": "sha512-4bj21UXbEu5cF+1gVjhwwRqMhY3lR7CUTlBr6YX3uzftL4l/sbu8EoHfOLZWHr+HeiosW9fTWkQCS2UZMAk5lw==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/caporal/-/caporal-1.4.0.tgz", + "integrity": "sha512-3pWfIwKVdIbB/gWmpLloO6iGAXTRi9mcTinPOwvHfzH3BYjOhLgq2XRG3hKtp+F6vBcBXxMgCobUzBAx1d8T4A==", "dev": true, "requires": { "bluebird": "^3.4.7", @@ -2828,18 +2839,18 @@ "dev": true }, "core-js": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", - "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==", + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", "dev": true }, "core-js-compat": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.7.0.tgz", - "integrity": "sha512-V8yBI3+ZLDVomoWICO6kq/CD28Y4r1M7CWeO4AGpMdMfseu8bkSubBmUPySMGKRTS+su4XQ07zUkAsiu9FCWTg==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.8.0.tgz", + "integrity": "sha512-o9QKelQSxQMYWHXc/Gc4L8bx/4F7TTraE5rhuN8I7mKBt5dBIUpXpIR3omv70ebr8ST5R3PqbDQr+ZI3+Tt1FQ==", "dev": true, "requires": { - "browserslist": "^4.14.6", + "browserslist": "^4.14.7", "semver": "7.0.0" }, "dependencies": { @@ -3189,9 +3200,9 @@ }, "dependencies": { "domelementtype": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.2.tgz", - "integrity": "sha512-wFwTwCVebUrMgGeAwRL/NhZtHAUyT9n9yg4IMDwf10+6iCMxSkVq9MGCVEH+QZWo1nNidy8kNvwmv4zWHDTqvA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.1.0.tgz", + "integrity": "sha512-LsTgx/L5VpD+Q8lmsXSHW2WpA+eBlZ9HPf3erD1IoPF00/3JKHZ3BknUVA2QGDNu69ZNmyFmCWBSO45XjYKC5w==", "dev": true }, "entities": { @@ -3289,9 +3300,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.591", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.591.tgz", - "integrity": "sha512-ol/0WzjL4NS4Kqy9VD6xXQON91xIihDT36sYCew/G/bnd1v0/4D+kahp26JauQhgFUjrdva3kRSo7URcUmQ+qw==", + "version": "1.3.614", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.614.tgz", + "integrity": "sha512-JMDl46mg4G+n6q/hAJkwy9eMTj5FJjsE+8f/irAGRMLM4yeRVbMuRrdZrbbGGOrGVcZc4vJPjUpEUWNb/fA6hg==", "dev": true }, "elegant-spinner": { @@ -3438,9 +3449,9 @@ } }, "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "version": "1.18.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", + "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", "dev": true, "requires": { "es-to-primitive": "^1.2.1", @@ -3448,6 +3459,7 @@ "has": "^1.0.3", "has-symbols": "^1.0.1", "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.0", "is-regex": "^1.1.1", "object-inspect": "^1.8.0", "object-keys": "^1.1.1", @@ -3457,13 +3469,13 @@ } }, "es-check": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/es-check/-/es-check-5.1.2.tgz", - "integrity": "sha512-uecftCFHR0ggaI3cKwqOu5b5j21z78NgoLlQitE0fDh+xATDZKrFdMoMM9L2ihiGq/d2L2sFPsgzWEsb4Vnr6Q==", + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/es-check/-/es-check-5.1.4.tgz", + "integrity": "sha512-mPfnJ4af0P0QQ8qODF05eumLJBCUldYwIpMkvu6QMVh6uA0l4C0EwE6eDL/EDrrK2hODzoBprE9zPwilLZiD7A==", "dev": true, "requires": { "acorn": "^6.4.1", - "caporal": "1.3.0", + "caporal": "1.4.0", "glob": "^7.1.2" }, "dependencies": { @@ -3613,9 +3625,9 @@ "dev": true }, "debug": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.0.tgz", - "integrity": "sha512-jjO6JD2rKfiZQnBoRzhRTbXjHLGLfH+UtGkWLc/UXAh/rzZMyjbgn0NcfFpqT8nd1kTtFnDiJcrIFkq4UKeJVg==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", "dev": true, "requires": { "ms": "2.1.2" @@ -5118,9 +5130,9 @@ }, "dependencies": { "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "requires": { "ms": "^2.1.1" @@ -5474,9 +5486,9 @@ } }, "is-core-module": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.1.0.tgz", - "integrity": "sha512-YcV7BgVMRFRua2FqQzKtTDMz8iCuLEyGKjr70q8Zm1yy2qKcurbFEd79PAdHV77oL3NrAaOVQIbMmiHQCHB7ZA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", + "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", "dev": true, "requires": { "has": "^1.0.3" @@ -6468,9 +6480,9 @@ }, "dependencies": { "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "requires": { "ms": "^2.1.1" @@ -6760,9 +6772,9 @@ }, "dependencies": { "debug": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.0.tgz", - "integrity": "sha512-jjO6JD2rKfiZQnBoRzhRTbXjHLGLfH+UtGkWLc/UXAh/rzZMyjbgn0NcfFpqT8nd1kTtFnDiJcrIFkq4UKeJVg==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", "dev": true, "requires": { "ms": "2.1.2" @@ -6821,6 +6833,18 @@ "@babel/runtime": "^7.5.5", "@videojs/vhs-utils": "^2.2.1", "global": "^4.3.2" + }, + "dependencies": { + "@videojs/vhs-utils": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@videojs/vhs-utils/-/vhs-utils-2.2.1.tgz", + "integrity": "sha512-9Qbwx3LAdkG1jh2HKfninjXDxVZCeaoPcmct/bUcDRmLej68Z9XhLe5d2a9fy1qB+UuQwWg7YySASesWavYNjQ==", + "requires": { + "@babel/runtime": "^7.5.5", + "global": "^4.3.2", + "url-toolkit": "^2.1.6" + } + } } }, "magic-string": { @@ -7157,6 +7181,18 @@ "@videojs/vhs-utils": "^2.2.1", "global": "^4.3.2", "xmldom": "^0.1.27" + }, + "dependencies": { + "@videojs/vhs-utils": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@videojs/vhs-utils/-/vhs-utils-2.2.1.tgz", + "integrity": "sha512-9Qbwx3LAdkG1jh2HKfninjXDxVZCeaoPcmct/bUcDRmLej68Z9XhLe5d2a9fy1qB+UuQwWg7YySASesWavYNjQ==", + "requires": { + "@babel/runtime": "^7.5.5", + "global": "^4.3.2", + "url-toolkit": "^2.1.6" + } + } } }, "ms": { @@ -7234,9 +7270,9 @@ } }, "node-releases": { - "version": "1.1.66", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.66.tgz", - "integrity": "sha512-JHEQ1iWPGK+38VLB2H9ef2otU4l8s3yAMt9Xf934r6+ojCYDMHPMqvCc9TnzfeFSP1QEOeU6YZEd3+De0LTCgg==", + "version": "1.1.67", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.67.tgz", + "integrity": "sha512-V5QF9noGFl3EymEwUYzO+3NTDpGfQB4ve6Qfnzf3UNydMhjQRVPR1DZTuvWiLzaFJYw2fmDwAfnRNEVb64hSIg==", "dev": true }, "node-watch": { @@ -7332,10 +7368,13 @@ }, "dependencies": { "semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", - "dev": true + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } } } }, @@ -7872,9 +7911,9 @@ } }, "object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz", + "integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==", "dev": true }, "object-keys": { @@ -8825,12 +8864,12 @@ } }, "resolve": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.18.1.tgz", - "integrity": "sha512-lDfCPaMKfOJXjy0dPayzPdF1phampNWr3qFCjAu+rw/qbQmr5jWH5xN2hwh9QKfw9E5v4hwV7A+jrCmL8yjjqA==", + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", "dev": true, "requires": { - "is-core-module": "^2.0.0", + "is-core-module": "^2.1.0", "path-parse": "^1.0.6" } }, @@ -9263,9 +9302,9 @@ }, "dependencies": { "debug": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.0.tgz", - "integrity": "sha512-jjO6JD2rKfiZQnBoRzhRTbXjHLGLfH+UtGkWLc/UXAh/rzZMyjbgn0NcfFpqT8nd1kTtFnDiJcrIFkq4UKeJVg==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", "dev": true, "requires": { "ms": "2.1.2" @@ -9682,9 +9721,9 @@ } }, "spdx-license-ids": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz", - "integrity": "sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw==", + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz", + "integrity": "sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==", "dev": true }, "split": { @@ -9825,9 +9864,9 @@ "dev": true }, "debug": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.0.tgz", - "integrity": "sha512-jjO6JD2rKfiZQnBoRzhRTbXjHLGLfH+UtGkWLc/UXAh/rzZMyjbgn0NcfFpqT8nd1kTtFnDiJcrIFkq4UKeJVg==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", "dev": true, "requires": { "ms": "2.1.2" @@ -9859,77 +9898,34 @@ } }, "string.prototype.padend": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.0.tgz", - "integrity": "sha512-3aIv8Ffdp8EZj8iLwREGpQaUZiPyrWrpzMBHvkiSW/bK/EGve9np07Vwy7IJ5waydpGXzQZu/F8Oze2/IWkBaA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.1.tgz", + "integrity": "sha512-eCzTASPnoCr5Ht+Vn1YXgm8SB015hHKgEIMu9Nr9bQmLhRBxKRfmzSj/IQsxDFc8JInJDDFA0qXwK+xxI7wDkg==", "dev": true, "requires": { + "call-bind": "^1.0.0", "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" + "es-abstract": "^1.18.0-next.1" } }, "string.prototype.trimend": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.2.tgz", - "integrity": "sha512-8oAG/hi14Z4nOVP0z6mdiVZ/wqjDtWSLygMigTzAb+7aPEDTleeFf+WrF+alzecxIRkckkJVn+dTlwzJXORATw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz", + "integrity": "sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw==", "dev": true, "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1" - }, - "dependencies": { - "es-abstract": { - "version": "1.18.0-next.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", - "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-negative-zero": "^2.0.0", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - } + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" } }, "string.prototype.trimstart": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.2.tgz", - "integrity": "sha512-7F6CdBTl5zyu30BJFdzSTlSlLPwODC23Od+iLoVH8X6+3fvDPPuBVVj9iaB1GOsSTSIgVfsfm27R2FGrAPznWg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz", + "integrity": "sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg==", "dev": true, "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1" - }, - "dependencies": { - "es-abstract": { - "version": "1.18.0-next.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", - "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-negative-zero": "^2.0.0", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - } + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" } }, "string_decoder": { @@ -10334,9 +10330,9 @@ "dev": true }, "type-fest": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.0.tgz", - "integrity": "sha512-fbDukFPnJBdn2eZ3RR+5mK2slHLFd6gYHY7jna1KWWy4Yr4XysHuCdXRzy+RiG/HwG4WJat00vdC2UHky5eKiQ==", + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", "dev": true }, "type-is": { @@ -10368,9 +10364,9 @@ "dev": true }, "uglify-js": { - "version": "3.11.5", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.11.5.tgz", - "integrity": "sha512-btvv/baMqe7HxP7zJSF7Uc16h1mSfuuSplT0/qdjxseesDU+yYzH33eHBH+eMdeRXwujXspaCTooWHQVVBh09w==", + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.12.1.tgz", + "integrity": "sha512-o8lHP20KjIiQe5b/67Rh68xEGRrc2SRsCuuoYclXXoC74AfSRGblU1HKzJWH3HxPZ+Ort85fWHpSX7KwBUC9CQ==", "dev": true, "optional": true }, @@ -10678,12 +10674,12 @@ } }, "video.js": { - "version": "7.10.2", - "resolved": "https://registry.npmjs.org/video.js/-/video.js-7.10.2.tgz", - "integrity": "sha512-kJTTrqcQn2MhPzWR8zQs6W3HPJWpowO/ZGZcKt2dcJeJdJT0dEDLYtiFdjV37SylCmu66V0flRnV8cipbthveQ==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/video.js/-/video.js-7.11.0.tgz", + "integrity": "sha512-N10MQilHvCsrFa1hkbmTiLeyTEaJe70aIHX+WyafHtv+skBStCRoAfr3PFW9pDKxsXoBAI5NrLpocK/MT/SQhw==", "requires": { "@babel/runtime": "^7.9.2", - "@videojs/http-streaming": "2.2.4", + "@videojs/http-streaming": "2.3.0", "@videojs/xhr": "2.5.1", "global": "4.3.2", "keycode": "^2.2.0", @@ -10975,9 +10971,9 @@ "dev": true }, "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", + "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", "dev": true }, "yallist": { diff --git a/package.json b/package.json index cb5d611b8..3bb5b7465 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ ], "dependencies": { "@babel/runtime": "^7.5.5", - "@videojs/vhs-utils": "^2.2.1", + "@videojs/vhs-utils": "^2.3.0", "aes-decrypter": "3.1.0", "global": "^4.3.2", "m3u8-parser": "4.5.0", diff --git a/src/master-playlist-controller.js b/src/master-playlist-controller.js index e36f0b922..87009a7ee 100644 --- a/src/master-playlist-controller.js +++ b/src/master-playlist-controller.js @@ -1617,15 +1617,41 @@ export class MasterPlaylistController extends videojs.EventTarget { * Excludes playlists with codecs that are unsupported by the muxer and browser. */ excludeUnsupportedVariants_() { - this.master().playlists.forEach(variant => { + const playlists = this.master().playlists; + const ids = []; + + // TODO: why don't we have a property to loop through all + // playlist? Why did we ever mix indexes and keys? + Object.keys(playlists).forEach(key => { + const variant = playlists[key]; + + // check if we already processed this playlist. + if (ids.indexOf(variant.id) !== -1) { + return; + } + + ids.push(variant.id); + const codecs = codecsForPlaylist(this.master, variant); + const unsupported = []; if (codecs.audio && !muxerSupportsCodec(codecs.audio) && !browserSupportsCodec(codecs.audio)) { variant.excludeUntil = Infinity; + unsupported.push(`audio codec ${codecs.audio}`); } if (codecs.video && !muxerSupportsCodec(codecs.video) && !browserSupportsCodec(codecs.video)) { variant.excludeUntil = Infinity; + unsupported.push(`video codec ${codecs.video}`); + } + + if (codecs.text && codecs.text === 'stpp.ttml.im1t') { + variant.excludeUntil = Infinity; + unsupported.push(`text codec ${codecs.text}`); + } + + if (unsupported.length) { + this.logger_(`excluding ${variant.id} as codecs ${unsupported.join(', ')} are unsupported`); } }); } diff --git a/src/media-groups.js b/src/media-groups.js index 3064337de..63de67aec 100644 --- a/src/media-groups.js +++ b/src/media-groups.js @@ -528,6 +528,11 @@ export const initialize = { playlistLoader = new PlaylistLoader(properties.resolvedUri, vhs, requestOptions); } else if (sourceType === 'dash') { + const playlists = properties.playlists.filter((p) => p.excludeUntil !== Infinity); + + if (!playlists.length) { + return; + } playlistLoader = new DashPlaylistLoader( properties.playlists[0], vhs, diff --git a/src/util/codecs.js b/src/util/codecs.js index 94791a17a..2b2cdb5c6 100644 --- a/src/util/codecs.js +++ b/src/util/codecs.js @@ -97,6 +97,14 @@ export const codecsForPlaylist = function(master, media) { codecs.audio = translateLegacyCodec(`${codecInfo.audio.type}${codecInfo.audio.details}`); } + if (codecInfo.text) { + codecs.text = codecInfo.text.type; + } + + if (codecInfo.unknown) { + codecs.unknown = codecInfo.unknown; + } + return codecs; }; diff --git a/test/master-playlist-controller.test.js b/test/master-playlist-controller.test.js index daaa5684c..dd503511c 100644 --- a/test/master-playlist-controller.test.js +++ b/test/master-playlist-controller.test.js @@ -898,12 +898,16 @@ QUnit.test( ); QUnit.test('excludes playlists with unsupported codecs before initial selection', function(assert) { + // only support mp4a/avc1 for testing, this is restored in afterEach + window.MediaSource.isTypeSupported = (type) => (/(mp4a|avc1)/).test(type); + this.masterPlaylistController.selectPlaylist = () => { - assert.equal( - this.masterPlaylistController.master().playlists[0].excludeUntil, - Infinity, - 'excludes unsupported playlist before initial selection' - ); + const playlists = this.masterPlaylistController.master().playlists; + + assert.equal(playlists[0].excludeUntil, Infinity, 'theora excluded'); + assert.equal(playlists[1].excludeUntil, undefined, 'avc/mp4a not excluded'); + assert.equal(playlists[2].excludeUntil, Infinity, 'ec-3 excluded'); + assert.equal(playlists[3].excludeUntil, Infinity, 'stpp.ttml.im1t excluded'); }; openMediaSource(this.player, this.clock); @@ -915,7 +919,11 @@ QUnit.test('excludes playlists with unsupported codecs before initial selection' '#EXT-X-STREAM-INF:BANDWIDTH=1,CODECS="theora,mp4a.40.5"\n' + 'media.m3u8\n' + '#EXT-X-STREAM-INF:BANDWIDTH=10000,CODECS="avc1.4d400d,mp4a.40.2"\n' + - 'media1.m3u8\n' + 'media1.m3u8\n' + + '#EXT-X-STREAM-INF:BANDWIDTH=10000,CODECS="avc1.4d400d,ec-3"\n' + + 'media2.m3u8\n' + + '#EXT-X-STREAM-INF:BANDWIDTH=10000,CODECS="stpp.ttml.im1t"\n' + + 'media3.m3u8\n' ); // media From 40caa45a88419ccdf32f4b21e36d84fe95c83fd0 Mon Sep 17 00:00:00 2001 From: Garrett Singer Date: Mon, 7 Dec 2020 15:05:04 -0500 Subject: [PATCH 042/399] fix: when changing renditions over a discontinuity, don't use buffered end as segment start (#1023) --- src/segment-loader.js | 28 ++++++++++++++++++++++++++++ test/segment-loader.test.js | 14 ++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/src/segment-loader.js b/src/segment-loader.js index 47db87df8..b0818f8d7 100644 --- a/src/segment-loader.js +++ b/src/segment-loader.js @@ -146,6 +146,34 @@ export const timestampOffsetForSegment = ({ return null; } + // When changing renditions, it's possible to request a segment on an older timeline. For + // instance, given two renditions with the following: + // + // #EXTINF:10 + // segment1 + // #EXT-X-DISCONTINUITY + // #EXTINF:10 + // segment2 + // #EXTINF:10 + // segment3 + // + // And the current player state: + // + // current time: 8 + // buffer: 0 => 20 + // + // The next segment on the current rendition would be segment3, filling the buffer from + // 20s onwards. However, if a rendition switch happens after segment2 was requested, + // then the next segment to be requested will be segment1 from the new rendition in + // order to fill time 8 and onwards. Using the buffered end would result in repeated + // content (since it would position segment1 of the new rendition starting at 20s). This + // case can be identified when the new segment's timeline is a prior value. Instead of + // using the buffered end, the startOfSegment can be used, which, hopefully, will be + // more accurate to the actual start time of the segment. + if (segmentTimeline < currentTimeline) { + return startOfSegment; + } + // segmentInfo.startOfSegment used to be used as the timestamp offset, however, that // value uses the end of the last segment if it is available. While this value // should often be correct, it's better to rely on the buffered end, as the new diff --git a/test/segment-loader.test.js b/test/segment-loader.test.js index 083c65e2e..aaa6bb391 100644 --- a/test/segment-loader.test.js +++ b/test/segment-loader.test.js @@ -217,6 +217,20 @@ QUnit.test('returns value when overrideCheck is true', function(assert) { ); }); +QUnit.test('uses startOfSegment when timeline is before current', function(assert) { + assert.equal( + timestampOffsetForSegment({ + segmentTimeline: 0, + currentTimeline: 1, + startOfSegment: 3, + buffered: videojs.createTimeRanges([[1, 5], [7, 8]]), + overrideCheck: true + }), + 3, + 'returned startOfSegment' + ); +}); + QUnit.module('shouldWaitForTimelineChange'); QUnit.test('should not wait if timelines are the same', function(assert) { From a29e241e6979ddd27ca6f7e2ff84bab1f4c7c450 Mon Sep 17 00:00:00 2001 From: Garrett Singer Date: Mon, 7 Dec 2020 15:05:25 -0500 Subject: [PATCH 043/399] fix: don't save bandwidth and throughput for really small segments (#1024) Really small segments can mess with our ABR algorithm by not reflecting our bandwidth and throughput accurately for the majority of segments. --- src/segment-loader.js | 30 +++++++++++++---- src/vtt-segment-loader.js | 5 +-- test/segment-loader.test.js | 67 +++++++++++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+), 9 deletions(-) diff --git a/src/segment-loader.js b/src/segment-loader.js index b0818f8d7..061c16363 100644 --- a/src/segment-loader.js +++ b/src/segment-loader.js @@ -26,6 +26,10 @@ import shallowEqual from './util/shallow-equal.js'; // in ms const CHECK_BUFFER_DELAY = 500; const finite = (num) => typeof num === 'number' && isFinite(num); +// With most content hovering around 30fps, if a segment has a duration less than a half +// frame at 30fps or one frame at 60fps, the bandwidth and throughput calculations will +// not accurately reflect the rest of the content. +const MIN_SEGMENT_DURATION_TO_SAVE_STATS = 1 / 60; export const illegalMediaSwitch = (loaderType, startingMedia, trackInfo) => { // Although these checks should most likely cover non 'main' types, for now it narrows @@ -2210,14 +2214,20 @@ export default class SegmentLoader extends videojs.EventTarget { } } - saveBandwidthRelatedStats_(stats) { - this.bandwidth = stats.bandwidth; - this.roundTrip = stats.roundTripTime; - + saveBandwidthRelatedStats_(duration, stats) { // byteLength will be used for throughput, and should be based on bytes receieved, // which we only know at the end of the request and should reflect total bytes // downloaded rather than just bytes processed from components of the segment this.pendingSegment_.byteLength = stats.bytesReceived; + + if (duration < MIN_SEGMENT_DURATION_TO_SAVE_STATS) { + this.logger_(`Ignoring segment's bandwidth because its duration of ${duration}` + + ` is less than the min to record ${MIN_SEGMENT_DURATION_TO_SAVE_STATS}`); + return; + } + + this.bandwidth = stats.bandwidth; + this.roundTrip = stats.roundTripTime; } handleTimeout_() { @@ -2289,11 +2299,11 @@ export default class SegmentLoader extends videojs.EventTarget { return; } + const segmentInfo = this.pendingSegment_; + // the response was a success so set any bandwidth stats the request // generated for ABR purposes - this.saveBandwidthRelatedStats_(simpleSegment.stats); - - const segmentInfo = this.pendingSegment_; + this.saveBandwidthRelatedStats_(segmentInfo.duration, simpleSegment.stats); segmentInfo.endOfAllRequests = simpleSegment.endOfAllRequests; @@ -2690,6 +2700,12 @@ export default class SegmentLoader extends videojs.EventTarget { * @param {Object} segmentInfo the object returned by loadSegment */ recordThroughput_(segmentInfo) { + if (segmentInfo.duration < MIN_SEGMENT_DURATION_TO_SAVE_STATS) { + this.logger_(`Ignoring segment's throughput because its duration of ${segmentInfo.duration}` + + ` is less than the min to record ${MIN_SEGMENT_DURATION_TO_SAVE_STATS}`); + return; + } + const rate = this.throughput.rate; // Add one to the time to ensure that we don't accidentally attempt to divide // by zero in the case where the throughput is ridiculously high diff --git a/src/vtt-segment-loader.js b/src/vtt-segment-loader.js index 8edca0a57..5097999bd 100644 --- a/src/vtt-segment-loader.js +++ b/src/vtt-segment-loader.js @@ -281,16 +281,17 @@ export default class VTTSegmentLoader extends SegmentLoader { return; } + const segmentInfo = this.pendingSegment_; + // although the VTT segment loader bandwidth isn't really used, it's good to // maintain functionality between segment loaders - this.saveBandwidthRelatedStats_(simpleSegment.stats); + this.saveBandwidthRelatedStats_(segmentInfo.duration, simpleSegment.stats); this.state = 'APPENDING'; // used for tests this.trigger('appending'); - const segmentInfo = this.pendingSegment_; const segment = segmentInfo.segment; if (segment.map) { diff --git a/test/segment-loader.test.js b/test/segment-loader.test.js index aaa6bb391..e964152e6 100644 --- a/test/segment-loader.test.js +++ b/test/segment-loader.test.js @@ -3300,6 +3300,73 @@ QUnit.module('SegmentLoader', function(hooks) { ); }); }); + + QUnit.test('saves bandwidth when segment duration is >= min to record', function(assert) { + const stats = { + bytesReceived: 100, + bandwidth: 101, + roundTrip: 102 + }; + + loader.bandwidth = 999; + // used for updating byte length + loader.pendingSegment_ = {}; + loader.saveBandwidthRelatedStats_(0.04, stats); + + assert.equal(loader.bandwidth, 101, 'saved bandwidth'); + }); + + QUnit.test('does not save bandwidth when segment duration is < min to record', function(assert) { + const stats = { + bytesReceived: 100, + bandwidth: 101, + roundTrip: 102 + }; + + loader.bandwidth = 999; + // used for updating byte length + loader.pendingSegment_ = {}; + loader.saveBandwidthRelatedStats_(0.01, stats); + + assert.equal(loader.bandwidth, 999, 'did not save bandwidth'); + }); + + QUnit.test('saves throughput when segment duration is >= min to record', function(assert) { + const segmentInfo = { + duration: 0.04, + rate: 101, + endOfAllRequests: Date.now(), + byteLength: 100 + }; + + loader.throughput = { + rate: 1000, + count: 1 + }; + loader.recordThroughput_(segmentInfo); + + // easier to assert not equal than deal with mocking dates + assert.notEqual(loader.throughput.rate, 1000, 'saved throughput'); + assert.equal(loader.throughput.count, 2, 'saved throughput'); + }); + + QUnit.test('does not save throughput when segment duration is < min to record', function(assert) { + const segmentInfo = { + duration: 0.01, + rate: 101, + endOfAllRequests: Date.now(), + byteLength: 100 + }; + + loader.throughput = { + rate: 1000, + count: 1 + }; + loader.recordThroughput_(segmentInfo); + + assert.equal(loader.throughput.rate, 1000, 'did not save throughput'); + assert.equal(loader.throughput.count, 1, 'did not save throughput'); + }); }); }); From 27de9a593ce0bd5ad78fa44cf2bcecaad86c347b Mon Sep 17 00:00:00 2001 From: Gary Katsevman Date: Mon, 7 Dec 2020 15:11:49 -0500 Subject: [PATCH 044/399] fix(experimentalBufferBasedABR): start ABR timer on main playlist load (#1026) Start the timer later, so we don't try to call simpleSelector without a playlist. However, we should add a null-check there just in case. Fixes #1025 --- src/master-playlist-controller.js | 2 +- src/playlist-selectors.js | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/master-playlist-controller.js b/src/master-playlist-controller.js index 87009a7ee..8ac13075d 100644 --- a/src/master-playlist-controller.js +++ b/src/master-playlist-controller.js @@ -259,7 +259,7 @@ export class MasterPlaylistController extends videojs.EventTarget { this.setupSegmentLoaderListeners_(); if (this.experimentalBufferBasedABR) { - this.startABRTimer_(); + this.masterPlaylistLoader_.one('loadedplaylist', () => this.startABRTimer_()); this.tech_.on('pause', () => this.stopABRTimer_()); this.tech_.on('play', () => this.startABRTimer_()); } diff --git a/src/playlist-selectors.js b/src/playlist-selectors.js index a328eeb11..70d339949 100644 --- a/src/playlist-selectors.js +++ b/src/playlist-selectors.js @@ -155,6 +155,11 @@ export const simpleSelector = function( limitRenditionByPlayerDimensions ) { + // If we end up getting called before `master` is available, exit early + if (!master) { + return; + } + const options = { bandwidth: playerBandwidth, width: playerWidth, From 197daab5f4539f6a78e0ca19388c0da9c81324d2 Mon Sep 17 00:00:00 2001 From: Gary Katsevman Date: Mon, 7 Dec 2020 15:53:13 -0500 Subject: [PATCH 045/399] chore(demo page): add an overrideNative button (default on) (#1027) --- index.html | 4 ++++ scripts/index-demo-page.js | 14 +++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/index.html b/index.html index 13e6f5f05..03497569a 100644 --- a/index.html +++ b/index.html @@ -77,6 +77,10 @@

Options

[EXPERIMENTAL] Use Buffer Level for ABR (reloads player) +

Load a URL

diff --git a/scripts/index-demo-page.js b/scripts/index-demo-page.js index 85324c485..497230031 100644 --- a/scripts/index-demo-page.js +++ b/scripts/index-demo-page.js @@ -85,7 +85,8 @@ if (el.type === 'url' || el.type === 'text' || el.nodeName.toLowerCase() === 'textarea') { el.value = decodeURIComponent(value); } else { - el.checked = value === 'true' ? true : false; + // get the `value` into a Boolean. + el.checked = JSON.parse(value); } }; @@ -216,7 +217,7 @@ representationsEl.selectedIndex = selectedIndex; }; - ['debug', 'autoplay', 'muted', 'minified', 'liveui', 'partial', 'url', 'type', 'keysystems', 'buffer-water'].forEach(function(name) { + ['debug', 'autoplay', 'muted', 'minified', 'liveui', 'partial', 'url', 'type', 'keysystems', 'buffer-water', 'override-native'].forEach(function(name) { stateEls[name] = document.getElementById(name); }); @@ -262,6 +263,13 @@ stateEls.minified.dispatchEvent(newEvent('change')); }); + stateEls['override-native'].addEventListener('change', function(event) { + saveState(); + + // reload the player and scripts + stateEls.minified.dispatchEvent(newEvent('change')); + }); + stateEls.liveui.addEventListener('change', function(event) { saveState(); @@ -307,7 +315,7 @@ liveui: stateEls.liveui.checked, html5: { vhs: { - overrideNative: true, + overrideNative: getInputValue(stateEls['override-native']), handlePartialData: getInputValue(stateEls.partial), experimentalBufferBasedABR: getInputValue(stateEls['buffer-water']) } From 4109a7fb26bad03a6a940b04576a7b848276e166 Mon Sep 17 00:00:00 2001 From: Garrett Singer Date: Mon, 7 Dec 2020 16:04:05 -0500 Subject: [PATCH 046/399] feat: log on mislabeled segment durations for HLS (#1010) --- src/segment-loader.js | 98 +++++++++++++++ test/segment-loader.test.js | 238 +++++++++++++++++++++++++++++++++++- 2 files changed, 335 insertions(+), 1 deletion(-) diff --git a/src/segment-loader.js b/src/segment-loader.js index 061c16363..360c4c536 100644 --- a/src/segment-loader.js +++ b/src/segment-loader.js @@ -341,6 +341,93 @@ export const shouldWaitForTimelineChange = ({ return false; }; +export const mediaDuration = (audioTimingInfo, videoTimingInfo) => { + const audioDuration = + audioTimingInfo && + typeof audioTimingInfo.start === 'number' && + typeof audioTimingInfo.end === 'number' ? + audioTimingInfo.end - audioTimingInfo.start : 0; + const videoDuration = + videoTimingInfo && + typeof videoTimingInfo.start === 'number' && + typeof videoTimingInfo.end === 'number' ? + videoTimingInfo.end - videoTimingInfo.start : 0; + + return Math.max(audioDuration, videoDuration); +}; + +export const segmentTooLong = ({ segmentDuration, maxDuration }) => { + // 0 duration segments are most likely due to metadata only segments or a lack of + // information. + if (!segmentDuration) { + return false; + } + + // For HLS: + // + // https://tools.ietf.org/html/draft-pantos-http-live-streaming-23#section-4.3.3.1 + // The EXTINF duration of each Media Segment in the Playlist + // file, when rounded to the nearest integer, MUST be less than or equal + // to the target duration; longer segments can trigger playback stalls + // or other errors. + // + // For DASH, the mpd-parser uses the largest reported segment duration as the target + // duration. Although that reported duration is occasionally approximate (i.e., not + // exact), a strict check may report that a segment is too long more often in DASH. + return Math.round(segmentDuration) > maxDuration + TIME_FUDGE_FACTOR; +}; + +export const getTroublesomeSegmentDurationMessage = (segmentInfo, sourceType) => { + // Right now we aren't following DASH's timing model exactly, so only perform + // this check for HLS content. + if (sourceType !== 'hls') { + return null; + } + + const segmentDuration = mediaDuration( + segmentInfo.audioTimingInfo, + segmentInfo.videoTimingInfo + ); + + // Don't report if we lack information. + // + // If the segment has a duration of 0 it is either a lack of information or a + // metadata only segment and shouldn't be reported here. + if (!segmentDuration) { + return null; + } + + const targetDuration = segmentInfo.playlist.targetDuration; + + const isSegmentWayTooLong = segmentTooLong({ + segmentDuration, + maxDuration: targetDuration * 2 + }); + const isSegmentSlightlyTooLong = segmentTooLong({ + segmentDuration, + maxDuration: targetDuration + }); + + const segmentTooLongMessage = `Segment with index ${segmentInfo.mediaIndex} ` + + `from playlist ${segmentInfo.playlist.id} ` + + `has a duration of ${segmentDuration} ` + + `when the reported duration is ${segmentInfo.duration} ` + + `and the target duration is ${targetDuration}. ` + + 'For HLS content, a duration in excess of the target duration may result in ' + + 'playback issues. See the HLS specification section on EXT-X-TARGETDURATION for ' + + 'more details: ' + + 'https://tools.ietf.org/html/draft-pantos-http-live-streaming-23#section-4.3.3.1'; + + if (isSegmentWayTooLong || isSegmentSlightlyTooLong) { + return { + severity: isSegmentWayTooLong ? 'warn' : 'info', + message: segmentTooLongMessage + }; + } + + return null; +}; + /** * An object that manages segment loading and appending. * @@ -2614,6 +2701,17 @@ export default class SegmentLoader extends videojs.EventTarget { this.logger_(segmentInfoString(segmentInfo)); + const segmentDurationMessage = + getTroublesomeSegmentDurationMessage(segmentInfo, this.sourceType_); + + if (segmentDurationMessage) { + if (segmentDurationMessage.severity === 'warn') { + videojs.log.warn(segmentDurationMessage.message); + } else { + this.logger_(segmentDurationMessage.message); + } + } + this.recordThroughput_(segmentInfo); this.pendingSegment_ = null; this.state = 'READY'; diff --git a/test/segment-loader.test.js b/test/segment-loader.test.js index e964152e6..b30a6fd81 100644 --- a/test/segment-loader.test.js +++ b/test/segment-loader.test.js @@ -4,7 +4,10 @@ import { illegalMediaSwitch, safeBackBufferTrimTime, timestampOffsetForSegment, - shouldWaitForTimelineChange + shouldWaitForTimelineChange, + segmentTooLong, + mediaDuration, + getTroublesomeSegmentDurationMessage } from '../src/segment-loader'; import segmentTransmuxer from '../src/segment-transmuxer'; import videojs from 'video.js'; @@ -481,6 +484,239 @@ QUnit.test('uses current time when seekable range is well before current time', ); }); +QUnit.module('mediaDuration'); + +QUnit.test('0 when no timing info', function(assert) { + assert.equal(mediaDuration({}, {}), 0, '0 when no timing info'); + assert.equal(mediaDuration({ start: 1 }, { start: 1 }), 0, '0 when no end times'); + assert.equal(mediaDuration({ end: 1 }, { end: 1 }), 0, '0 when no start times'); +}); + +QUnit.test('reports audio duration', function(assert) { + assert.equal( + mediaDuration({ start: 1, end: 2 }, {}), + 1, + 'audio duration when no video info' + ); + + assert.equal( + mediaDuration({ start: 1, end: 2 }, { start: 1 }), + 1, + 'audio duration when not enough video info' + ); + + assert.equal( + mediaDuration({ start: 1, end: 2 }, { end: 3 }), + 1, + 'audio duration when not enough video info' + ); + + assert.equal( + mediaDuration({ start: 1, end: 3 }, { start: 1, end: 2 }), + 2, + 'audio duration when audio duration > video duration' + ); +}); + +QUnit.test('reports video duration', function(assert) { + assert.equal( + mediaDuration({}, { start: 1, end: 2 }), + 1, + 'video duration when no audio info' + ); + + assert.equal( + mediaDuration({ start: 1 }, { start: 1, end: 2 }), + 1, + 'video duration when not enough audio info' + ); + + assert.equal( + mediaDuration({ end: 3 }, { start: 1, end: 2 }), + 1, + 'video duration when not enough audio info' + ); + + assert.equal( + mediaDuration({ start: 1, end: 2 }, { start: 1, end: 3 }), + 2, + 'video duration when video duration > audio duration' + ); +}); + +QUnit.module('segmentTooLong'); + +QUnit.test('false when no segment duration', function(assert) { + assert.notOk(segmentTooLong({ maxDuration: 9 }), 'false when no segment duration'); + assert.notOk( + segmentTooLong({ segmentDuration: 0, maxDuration: 9 }), + 'false when segment duration is 0' + ); +}); + +QUnit.test('false when duration is within range', function(assert) { + assert.notOk( + segmentTooLong({ + segmentDuration: 9, + maxDuration: 9 + }), + 'false when duration is same' + ); + assert.notOk( + segmentTooLong({ + segmentDuration: 9.49, + maxDuration: 9 + }), + 'false when duration rounds down to same' + ); +}); + +QUnit.test('true when duration is too long', function(assert) { + assert.ok( + segmentTooLong({ + segmentDuration: 9, + maxDuration: 8.9 + }), + 'true when duration is too long' + ); + assert.ok( + segmentTooLong({ + segmentDuration: 9.5, + maxDuration: 9 + }), + 'true when duration rounds up to be too long' + ); +}); + +QUnit.module('getTroublesomeSegmentDurationMessage'); + +QUnit.test('falsey when dash', function(assert) { + assert.notOk( + getTroublesomeSegmentDurationMessage( + { + audioTimingInfo: { start: 0, end: 10 }, + videoTimingInfo: { start: 0, end: 10 }, + mediaIndex: 0, + playlist: { + id: 'id', + targetDuration: 4 + } + }, + 'dash' + ), + 'falsey when dash' + ); +}); + +QUnit.test('falsey when segment is within range', function(assert) { + assert.notOk( + getTroublesomeSegmentDurationMessage( + { + audioTimingInfo: { start: 0, end: 10 }, + videoTimingInfo: { start: 0, end: 10 }, + duration: 10, + mediaIndex: 0, + playlist: { + id: 'id', + targetDuration: 10 + } + }, + 'hls' + ), + 'falsey when segment equal to target duration' + ); + + assert.notOk( + getTroublesomeSegmentDurationMessage( + { + audioTimingInfo: { start: 0, end: 10 }, + videoTimingInfo: { start: 0, end: 5 }, + duration: 10, + mediaIndex: 0, + playlist: { + id: 'id', + targetDuration: 10 + } + }, + 'hls' + ), + 'falsey when segment less than target duration' + ); + + assert.notOk( + getTroublesomeSegmentDurationMessage( + { + audioTimingInfo: { start: 0, end: 5 }, + videoTimingInfo: { start: 0, end: 5 }, + mediaIndex: 0, + duration: 5, + playlist: { + id: 'id', + targetDuration: 10 + } + }, + 'hls' + ), + 'falsey when segment less than target duration' + ); +}); + +QUnit.test('warn when segment is way too long', function(assert) { + assert.deepEqual( + getTroublesomeSegmentDurationMessage( + { + audioTimingInfo: { start: 0, end: 10 }, + videoTimingInfo: { start: 0, end: 10 }, + mediaIndex: 0, + duration: 10, + playlist: { + targetDuration: 4, + id: 'id' + } + }, + 'hls' + ), + { + severity: 'warn', + message: + 'Segment with index 0 from playlist id has a duration of 10 when the reported ' + + 'duration is 10 and the target duration is 4. For HLS content, a duration in ' + + 'excess of the target duration may result in playback issues. See the HLS ' + + 'specification section on EXT-X-TARGETDURATION for more details: ' + + 'https://tools.ietf.org/html/draft-pantos-http-live-streaming-23#section-4.3.3.1' + }, + 'warn when segment way too long' + ); +}); + +QUnit.test('info segment is bit too long', function(assert) { + assert.deepEqual( + getTroublesomeSegmentDurationMessage( + { + audioTimingInfo: { start: 0, end: 4.5 }, + videoTimingInfo: { start: 0, end: 4.5 }, + mediaIndex: 0, + duration: 4.5, + playlist: { + id: 'id', + targetDuration: 4 + } + }, + 'hls' + ), + { + severity: 'info', + message: + 'Segment with index 0 from playlist id has a duration of 4.5 when the reported ' + + 'duration is 4.5 and the target duration is 4. For HLS content, a duration in ' + + 'excess of the target duration may result in playback issues. See the HLS ' + + 'specification section on EXT-X-TARGETDURATION for more details: ' + + 'https://tools.ietf.org/html/draft-pantos-http-live-streaming-23#section-4.3.3.1' + }, + 'info when segment is a bit too long' + ); +}); + QUnit.module('SegmentLoader', function(hooks) { hooks.beforeEach(LoaderCommonHooks.beforeEach); hooks.afterEach(LoaderCommonHooks.afterEach); From c4f7d1d060d4b3f8d8634e08ea7d123835a193fd Mon Sep 17 00:00:00 2001 From: Gary Katsevman Date: Mon, 7 Dec 2020 16:16:02 -0500 Subject: [PATCH 047/399] 2.4.0 --- CHANGELOG.md | 40 ++++++++++++++++++++++++++++++++++++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 305a90ad5..a7577cc22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,43 @@ + +# [2.4.0](https://github.com/videojs/http-streaming/compare/v2.3.0...v2.4.0) (2020-12-07) + +### Features + +* **playback watcher:** Configurable live seekable window ([#997](https://github.com/videojs/http-streaming/issues/997)) ([ad5c270](https://github.com/videojs/http-streaming/commit/ad5c270)) +* log on mislabeled segment durations for HLS ([#1010](https://github.com/videojs/http-streaming/issues/1010)) ([4109a7f](https://github.com/videojs/http-streaming/commit/4109a7f)) +* update to mux.js 5.7.0 ([#1014](https://github.com/videojs/http-streaming/issues/1014)) ([5f14909](https://github.com/videojs/http-streaming/commit/5f14909)), closes [#1001](https://github.com/videojs/http-streaming/issues/1001) [#909](https://github.com/videojs/http-streaming/issues/909) + +### Bug Fixes + +* abort all loaders on earlyabort ([#965](https://github.com/videojs/http-streaming/issues/965)) ([e7cb63a](https://github.com/videojs/http-streaming/commit/e7cb63a)) +* don't save bandwidth and throughput for really small segments ([#1024](https://github.com/videojs/http-streaming/issues/1024)) ([a29e241](https://github.com/videojs/http-streaming/commit/a29e241)) +* filter out unsupported subtitles for dash ([#962](https://github.com/videojs/http-streaming/issues/962)) ([124834a](https://github.com/videojs/http-streaming/commit/124834a)) +* keep running the minimumUpdatePeriod unless cancelled or changed ([#1016](https://github.com/videojs/http-streaming/issues/1016)) ([f7b528c](https://github.com/videojs/http-streaming/commit/f7b528c)) +* prevent double source buffer ready on IE11 ([#1015](https://github.com/videojs/http-streaming/issues/1015)) ([b1c2969](https://github.com/videojs/http-streaming/commit/b1c2969)) +* remove duplicate cues with same time interval and text ([#1005](https://github.com/videojs/http-streaming/issues/1005)) ([6db2b6a](https://github.com/videojs/http-streaming/commit/6db2b6a)) +* support tracks with id 0 for fmp4 playlists ([#1018](https://github.com/videojs/http-streaming/issues/1018)) ([bf63692](https://github.com/videojs/http-streaming/commit/bf63692)) +* Wait for EME initialization before appending content ([#1002](https://github.com/videojs/http-streaming/issues/1002)) ([93132b7](https://github.com/videojs/http-streaming/commit/93132b7)) +* when changing renditions over a discontinuity, don't use buffered end as segment start ([#1023](https://github.com/videojs/http-streaming/issues/1023)) ([40caa45](https://github.com/videojs/http-streaming/commit/40caa45)) +* **experimentalBufferBasedABR:** start ABR timer on main playlist load ([#1026](https://github.com/videojs/http-streaming/issues/1026)) ([27de9a5](https://github.com/videojs/http-streaming/commit/27de9a5)), closes [#1025](https://github.com/videojs/http-streaming/issues/1025) + +### Chores + +* add multiple soon-to-work sources ([#1007](https://github.com/videojs/http-streaming/issues/1007)) ([030469f](https://github.com/videojs/http-streaming/commit/030469f)) +* don't run tests on release ([#1006](https://github.com/videojs/http-streaming/issues/1006)) ([d13b737](https://github.com/videojs/http-streaming/commit/d13b737)) +* skip duplicate ci workflows ([#1021](https://github.com/videojs/http-streaming/issues/1021)) ([20cc4a3](https://github.com/videojs/http-streaming/commit/20cc4a3)) +* switch from travis to github actions for ci ([#989](https://github.com/videojs/http-streaming/issues/989)) ([c9b195b](https://github.com/videojs/http-streaming/commit/c9b195b)) +* **demo page:** add an overrideNative button (default on) ([#1027](https://github.com/videojs/http-streaming/issues/1027)) ([197daab](https://github.com/videojs/http-streaming/commit/197daab)) + +### Code Refactoring + +* Add a better distinction between master and child dash loaders ([#992](https://github.com/videojs/http-streaming/issues/992)) ([56592bc](https://github.com/videojs/http-streaming/commit/56592bc)) +* add sidx segments to playlist object instead of re-parsing xml ([#994](https://github.com/videojs/http-streaming/issues/994)) ([e41f856](https://github.com/videojs/http-streaming/commit/e41f856)) +* unify sidx/master/error request logic ([#998](https://github.com/videojs/http-streaming/issues/998)) ([fe57e60](https://github.com/videojs/http-streaming/commit/fe57e60)) + +### Tests + +* fix tests on firefox 83 ([#1004](https://github.com/videojs/http-streaming/issues/1004)) ([00d9b1d](https://github.com/videojs/http-streaming/commit/00d9b1d)) + # [2.3.0](https://github.com/videojs/http-streaming/compare/v2.2.0...v2.3.0) (2020-11-05) diff --git a/package-lock.json b/package-lock.json index b44130e20..dba359542 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@videojs/http-streaming", - "version": "2.3.0", + "version": "2.4.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 3bb5b7465..8a51741d5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@videojs/http-streaming", - "version": "2.3.0", + "version": "2.4.0", "description": "Play back HLS and DASH with Video.js, even where it's not natively supported", "main": "dist/videojs-http-streaming.cjs.js", "module": "dist/videojs-http-streaming.es.js", From d39276d4cddb12e8d9724ccf5ae8dd12677bbf0a Mon Sep 17 00:00:00 2001 From: Gary Katsevman Date: Tue, 8 Dec 2020 17:24:44 -0500 Subject: [PATCH 048/399] chore(demo): clear type on manual source change (#1030) If a user manually changes the url, the type may not be correct anymore. We should clear it. Given that we auto-detect .m3u8 and .mpd types, it shouldn't be a big deal and would cause less problems than the incorrect type being present for the given source. --- scripts/index-demo-page.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/index-demo-page.js b/scripts/index-demo-page.js index 497230031..c378f121c 100644 --- a/scripts/index-demo-page.js +++ b/scripts/index-demo-page.js @@ -413,6 +413,11 @@ urlButton.click(); } }); + stateEls.url.addEventListener('input', function(event) { + if (stateEls.type.value.length) { + stateEls.type.value = ''; + } + }); stateEls.type.addEventListener('keyup', function(event) { if (event.key === 'Enter') { urlButton.click(); From f1d9f6eedd6dcfc8c8abd8c967fd9fcc9c17056a Mon Sep 17 00:00:00 2001 From: Brandon Casey <2381475+brandonocasey@users.noreply.github.com> Date: Thu, 10 Dec 2020 15:05:54 -0500 Subject: [PATCH 049/399] chore: move playback tests to a separate ci run (#1028) --- .github/workflows/ci.yml | 65 ++-- package-lock.json | 517 +++++++++++----------------- package.json | 4 +- scripts/rollup.config.js | 11 +- test/videojs-http-streaming.test.js | 1 + 5 files changed, 242 insertions(+), 356 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d931702ba..83880ea7c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,81 +8,72 @@ jobs: runs-on: ubuntu-latest # Map a step output to a job output outputs: - should-skip-job: ${{ steps.skip-check.outputs.should_skip }} + should-skip-job: ${{steps.skip-check.outputs.should_skip}} steps: - id: skip-check uses: fkirc/skip-duplicate-actions@v2.1.0 with: - github_token: ${{ github.token }} + github_token: ${{github.token}} ci: needs: should-skip - if: ${{ needs.should-skip.outputs.should-skip-job != 'true'}} - env: - BROWSER_STACK_USERNAME: ${{ secrets.BROWSER_STACK_USERNAME }} - BROWSER_STACK_ACCESS_KEY: ${{ secrets.BROWSER_STACK_ACCESS_KEY }} - runs-on: ${{ matrix.os }} + if: ${{needs.should-skip.outputs.should-skip-job != 'true'}} strategy: - # TODO: test IE 11, Legacy Edge, and New Edge on windows-latest - # test Safari on macos-latest + fail-fast: false matrix: os: [ubuntu-latest] - + test-type: [unit, playback] + env: + BROWSER_STACK_USERNAME: ${{secrets.BROWSER_STACK_USERNAME}} + BROWSER_STACK_ACCESS_KEY: ${{secrets.BROWSER_STACK_ACCESS_KEY}} + CI_TEST_TYPE: ${{matrix.test-type}} + runs-on: ${{matrix.os}} steps: - - uses: actions/checkout@v2 + - name: checkout code + uses: actions/checkout@v2 + - name: Cache dependencies uses: actions/cache@v2 with: path: | ~/.npm **/node_modules - key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }} + key: ${{runner.os}}-npm-${{hashFiles('**/package-lock.json')}} restore-keys: | - ${{ runner.os }}-npm- - ${{ runner.os }}- + ${{runner.os}}-npm- + ${{runner.os}}- - - name: Read .nvmrc + - name: read node version from .nvmrc run: echo ::set-output name=NVMRC::$(cat .nvmrc) shell: bash id: nvm - name: update apt cache on linux w/o browserstack run: sudo apt-get update - if: ${{ startsWith(matrix.os, 'ubuntu') && !env.BROWSER_STACK_USERNAME }} + if: ${{startsWith(matrix.os, 'ubuntu') && !env.BROWSER_STACK_USERNAME}} - - name: Install ffmpeg/pulseaudio for firefox on linux w/o browserstack + - name: install ffmpeg/pulseaudio for firefox on linux w/o browserstack run: sudo apt-get install ffmpeg pulseaudio - if: ${{ startsWith(matrix.os, 'ubuntu') && !env.BROWSER_STACK_USERNAME }} + if: ${{startsWith(matrix.os, 'ubuntu') && !env.BROWSER_STACK_USERNAME}} - name: start pulseaudio for firefox on linux w/o browserstack run: pulseaudio -D - if: ${{ startsWith(matrix.os, 'ubuntu') && !env.BROWSER_STACK_USERNAME }} + if: ${{startsWith(matrix.os, 'ubuntu') && !env.BROWSER_STACK_USERNAME}} - - name: Setup node + - name: setup node uses: actions/setup-node@v1 with: - node-version: '${{ steps.nvm.outputs.NVMRC }}' + node-version: '${{steps.nvm.outputs.NVMRC}}' + # turn off the default setup-node problem watchers... - run: echo "::remove-matcher owner=eslint-compact::" - run: echo "::remove-matcher owner=eslint-stylish::" - run: echo "::remove-matcher owner=tsc::" - - run: npm i --prefer-offline --no-audit - - # run safari on macos - - name: Run Mac test - run: npm run test -- --browsers Safari - if: ${{ startsWith(matrix.os, 'macos') }} + - name: npm install + run: npm i --prefer-offline --no-audit - # only run ie 11 on windows - - name: Run Windows test - run: npm run test -- --browsers IE - if: ${{ startsWith(matrix.os, 'windows') }} - - # run chrome/firefox or browserstack in linux - - name: Run linux test + - name: run npm test uses: GabrielBB/xvfb-action@v1 with: - run: npm test - if: ${{ startsWith(matrix.os, 'ubuntu') }} - + run: npm run test diff --git a/package-lock.json b/package-lock.json index dba359542..55aaed174 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1122,6 +1122,64 @@ "integrity": "sha512-Jq0JfThRZvmuDn0Sx3TTi0uf2ZhIDnx08l9af4741gCMghyT26zxR/DNPoPJCGDc1QFLohYdCWsMn21XFDt46Q==", "dev": true }, + "@rollup/plugin-babel": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.2.2.tgz", + "integrity": "sha512-MjmH7GvFT4TW8xFdIeFS3wqIX646y5tACdxkTO+khbHvS3ZcVJL6vkAHLw2wqPmkhwCfWHoNsp15VYNwW6JEJA==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.10.4", + "@rollup/pluginutils": "^3.1.0" + } + }, + "@rollup/plugin-commonjs": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-14.0.0.tgz", + "integrity": "sha512-+PSmD9ePwTAeU106i9FRdc+Zb3XUWyW26mo5Atr2mk82hor8+nPwkztEjFo8/B1fJKfaQDg9aM2bzQkjhi7zOw==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^3.0.8", + "commondir": "^1.0.1", + "estree-walker": "^1.0.1", + "glob": "^7.1.2", + "is-reference": "^1.1.2", + "magic-string": "^0.25.2", + "resolve": "^1.11.0" + } + }, + "@rollup/plugin-json": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-4.1.0.tgz", + "integrity": "sha512-yfLbTdNS6amI/2OpmbiBoW12vngr5NW2jCJVZSBEz+H5KfUJZ2M7sDjk0U6GOOdCWFVScShte29o9NezJ53TPw==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^3.0.8" + } + }, + "@rollup/plugin-multi-entry": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-multi-entry/-/plugin-multi-entry-4.0.0.tgz", + "integrity": "sha512-1Sw86rwFxrNS7ECY3iSZ7T940xKnruNGpmQDgSDVTp+VTa1g5cPXNzBgp+IoOer41CiVeGFLwYwvicVoJLHEDQ==", + "dev": true, + "requires": { + "@rollup/plugin-virtual": "^2.0.3", + "matched": "^5.0.0" + } + }, + "@rollup/plugin-node-resolve": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-9.0.0.tgz", + "integrity": "sha512-gPz+utFHLRrd41WMP13Jq5mqqzHL3OXrfj3/MkSyB6UBIcuNt9j60GCbarzMzdf1VHFpOxfQh/ez7wyadLMqkg==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^3.1.0", + "@types/resolve": "1.17.1", + "builtin-modules": "^3.1.0", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.17.0" + } + }, "@rollup/plugin-replace": { "version": "2.3.4", "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.3.4.tgz", @@ -1132,6 +1190,12 @@ "magic-string": "^0.25.7" } }, + "@rollup/plugin-virtual": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@rollup/plugin-virtual/-/plugin-virtual-2.0.3.tgz", + "integrity": "sha512-pw6ziJcyjZtntQ//bkad9qXaBx665SgEL8C8KI5wO8G5iU5MPxvdWrQyVaAvjojGm9tJoS8M9Z/EEepbqieYmw==", + "dev": true + }, "@rollup/pluginutils": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", @@ -1222,9 +1286,9 @@ "dev": true }, "@types/node": { - "version": "14.14.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.10.tgz", - "integrity": "sha512-J32dgx2hw8vXrSbu4ZlVhn1Nm3GbeCFNw2FWL8S5QKucHGY0cyNwjdQdO+KMBZ4wpmC7KhLCiNsdk1RFRIYUQQ==", + "version": "14.14.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.11.tgz", + "integrity": "sha512-BJ97wAUuU3NUiUCp44xzUFquQEvnk1wu7q4CMEUYKJWjdkr0YWYDsm4RFtAvxYsNjLsKcrFt6RvK8r+mnzMbEQ==", "dev": true }, "@types/normalize-package-data": { @@ -1234,14 +1298,28 @@ "dev": true }, "@types/resolve": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz", - "integrity": "sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", + "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", "dev": true, "requires": { "@types/node": "*" } }, + "@videojs/babel-config": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@videojs/babel-config/-/babel-config-0.2.0.tgz", + "integrity": "sha512-6OvuB7/UIF+SCx9EcCkZqsoplHqrawUYJt9R0CKXzoLsbfMQaXYfKbWvV2i2+1whOXd2LlyiVMINB3HxZ1quOw==", + "dev": true, + "requires": { + "@babel/core": "^7.11.6", + "@babel/plugin-transform-modules-commonjs": "^7.10.4", + "@babel/plugin-transform-object-assign": "^7.10.4", + "@babel/plugin-transform-runtime": "^7.11.5", + "@babel/preset-env": "^7.11.5", + "babel-plugin-add-module-exports": "^1.0.4" + } + }, "@videojs/generator-helpers": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@videojs/generator-helpers/-/generator-helpers-1.2.0.tgz", @@ -1275,16 +1353,6 @@ "video.js": "^6 || ^7" }, "dependencies": { - "@videojs/vhs-utils": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@videojs/vhs-utils/-/vhs-utils-2.2.1.tgz", - "integrity": "sha512-9Qbwx3LAdkG1jh2HKfninjXDxVZCeaoPcmct/bUcDRmLej68Z9XhLe5d2a9fy1qB+UuQwWg7YySASesWavYNjQ==", - "requires": { - "@babel/runtime": "^7.5.5", - "global": "^4.3.2", - "url-toolkit": "^2.1.6" - } - }, "mpd-parser": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/mpd-parser/-/mpd-parser-0.14.0.tgz", @@ -1356,9 +1424,9 @@ } }, "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", "dev": true }, "acorn-jsx": { @@ -1382,18 +1450,6 @@ "@videojs/vhs-utils": "^2.2.1", "global": "^4.3.2", "pkcs7": "^1.0.4" - }, - "dependencies": { - "@videojs/vhs-utils": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@videojs/vhs-utils/-/vhs-utils-2.2.1.tgz", - "integrity": "sha512-9Qbwx3LAdkG1jh2HKfninjXDxVZCeaoPcmct/bUcDRmLej68Z9XhLe5d2a9fy1qB+UuQwWg7YySASesWavYNjQ==", - "requires": { - "@babel/runtime": "^7.5.5", - "global": "^4.3.2", - "url-toolkit": "^2.1.6" - } - } } }, "after": { @@ -1614,12 +1670,6 @@ "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", "dev": true }, - "async-array-reduce": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/async-array-reduce/-/async-array-reduce-0.2.1.tgz", - "integrity": "sha1-yL4BCitc0A3qlsgRFgNGk9/dgtE=", - "dev": true - }, "async-limiter": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", @@ -1715,6 +1765,12 @@ "babel-runtime": "^6.22.0" } }, + "babel-plugin-add-module-exports": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-1.0.4.tgz", + "integrity": "sha512-g+8yxHUZ60RcyaUpfNzy56OtWW+x9cyEe9j+CranqLiqbju2yf/Cy6ZtYK40EZxtrdHllzlVZgLmcOUCTlJ7Jg==", + "dev": true + }, "babel-plugin-dynamic-import-node": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", @@ -2134,9 +2190,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001164", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001164.tgz", - "integrity": "sha512-G+A/tkf4bu0dSp9+duNiXc7bGds35DioCyC6vgK2m/rjA4Krpy5WeZgZyfH2f0wj2kI6yAWWucyap6oOwmY1mg==", + "version": "1.0.30001165", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001165.tgz", + "integrity": "sha512-8cEsSMwXfx7lWSUMA2s08z9dIgsnR5NAqjXP23stdsU3AUWkCr/rr4s4OFtHXn5XXr6+7kam3QFVoYyXNPdJPA==", "dev": true }, "caporal": { @@ -2513,6 +2569,12 @@ "integrity": "sha512-oB3TinFT+PV3p8UwDQt71+HkG03+zwPwikDlKU6ZDmql6QX2zFlQ+G0GGSDqyJhdZi4PSlzFBm+YJ+ebOX3Vgw==", "dev": true }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, "compare-func": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", @@ -2845,12 +2907,12 @@ "dev": true }, "core-js-compat": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.8.0.tgz", - "integrity": "sha512-o9QKelQSxQMYWHXc/Gc4L8bx/4F7TTraE5rhuN8I7mKBt5dBIUpXpIR3omv70ebr8ST5R3PqbDQr+ZI3+Tt1FQ==", + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.8.1.tgz", + "integrity": "sha512-a16TLmy9NVD1rkjUGbwuyWkiDoN0FDpAwrfLONvHFQx0D9k7J9y0srwMT8QP/Z6HE3MIFaVynEeYwZwPX1o5RQ==", "dev": true, "requires": { - "browserslist": "^4.14.7", + "browserslist": "^4.15.0", "semver": "7.0.0" }, "dependencies": { @@ -3043,6 +3105,12 @@ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, + "deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "dev": true + }, "define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", @@ -3300,9 +3368,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.614", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.614.tgz", - "integrity": "sha512-JMDl46mg4G+n6q/hAJkwy9eMTj5FJjsE+8f/irAGRMLM4yeRVbMuRrdZrbbGGOrGVcZc4vJPjUpEUWNb/fA6hg==", + "version": "1.3.620", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.620.tgz", + "integrity": "sha512-YbgWXUR2Mu+Fp6rm3GZ5YJdNo8SgZKLUTNSl2PNvdOcM8OIz07jRJnRkIaV9vdszFv9UUuGChh19w9qSuoLJgw==", "dev": true }, "elegant-spinner": { @@ -3356,9 +3424,9 @@ } }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true } } @@ -3477,14 +3545,6 @@ "acorn": "^6.4.1", "caporal": "1.4.0", "glob": "^7.1.2" - }, - "dependencies": { - "acorn": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", - "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", - "dev": true - } } }, "es-to-primitive": { @@ -3840,14 +3900,6 @@ "acorn": "^6.0.7", "acorn-jsx": "^5.0.0", "eslint-visitor-keys": "^1.0.0" - }, - "dependencies": { - "acorn": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", - "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", - "dev": true - } } }, "esprima": { @@ -3976,15 +4028,6 @@ } } }, - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -4817,30 +4860,6 @@ "process": "^0.11.10" } }, - "global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - } - }, - "global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - } - }, "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -4959,26 +4978,6 @@ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, - "has-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-glob/-/has-glob-1.0.0.tgz", - "integrity": "sha1-mqqe7b/7G6OZCnsAEPtnjuAIEgc=", - "dev": true, - "requires": { - "is-glob": "^3.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, "has-symbols": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", @@ -5023,15 +5022,6 @@ } } }, - "homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true, - "requires": { - "parse-passwd": "^1.0.0" - } - }, "hosted-git-info": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.7.tgz", @@ -5139,9 +5129,9 @@ } }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true } } @@ -5611,9 +5601,9 @@ "dev": true }, "is-negative-zero": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", - "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", + "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", "dev": true }, "is-number": { @@ -5750,12 +5740,6 @@ "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", "dev": true }, - "is-valid-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", - "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", - "dev": true - }, "is-whitespace-character": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz", @@ -5907,22 +5891,29 @@ } }, "jest-worker": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", - "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", "dev": true, "requires": { + "@types/node": "*", "merge-stream": "^2.0.0", - "supports-color": "^6.1.0" + "supports-color": "^7.0.0" }, "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" } } } @@ -5940,9 +5931,9 @@ "dev": true }, "js-yaml": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", - "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "requires": { "argparse": "^1.0.7", @@ -6489,9 +6480,9 @@ } }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, "pify": { @@ -6833,18 +6824,6 @@ "@babel/runtime": "^7.5.5", "@videojs/vhs-utils": "^2.2.1", "global": "^4.3.2" - }, - "dependencies": { - "@videojs/vhs-utils": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@videojs/vhs-utils/-/vhs-utils-2.2.1.tgz", - "integrity": "sha512-9Qbwx3LAdkG1jh2HKfninjXDxVZCeaoPcmct/bUcDRmLej68Z9XhLe5d2a9fy1qB+UuQwWg7YySASesWavYNjQ==", - "requires": { - "@babel/runtime": "^7.5.5", - "global": "^4.3.2", - "url-toolkit": "^2.1.6" - } - } } }, "magic-string": { @@ -6909,17 +6888,13 @@ "dev": true }, "matched": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/matched/-/matched-1.0.2.tgz", - "integrity": "sha512-7ivM1jFZVTOOS77QsR+TtYHH0ecdLclMkqbf5qiJdX2RorqfhsL65QHySPZgDE0ZjHoh+mQUNHTanNXIlzXd0Q==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/matched/-/matched-5.0.1.tgz", + "integrity": "sha512-E1fhSTPRyhAlNaNvGXAgZQlq1hL0bgYMTk/6bktVlIhzUnX/SZs7296ACdVeNJE8xFNGSuvd9IpI7vSnmcqLvw==", "dev": true, "requires": { - "arr-union": "^3.1.0", - "async-array-reduce": "^0.2.1", - "glob": "^7.1.2", - "has-glob": "^1.0.0", - "is-valid-glob": "^1.0.0", - "resolve-dir": "^1.0.0" + "glob": "^7.1.6", + "picomatch": "^2.2.1" } }, "matcher": { @@ -7181,18 +7156,6 @@ "@videojs/vhs-utils": "^2.2.1", "global": "^4.3.2", "xmldom": "^0.1.27" - }, - "dependencies": { - "@videojs/vhs-utils": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@videojs/vhs-utils/-/vhs-utils-2.2.1.tgz", - "integrity": "sha512-9Qbwx3LAdkG1jh2HKfninjXDxVZCeaoPcmct/bUcDRmLej68Z9XhLe5d2a9fy1qB+UuQwWg7YySASesWavYNjQ==", - "requires": { - "@babel/runtime": "^7.5.5", - "global": "^4.3.2", - "url-toolkit": "^2.1.6" - } - } } }, "ms": { @@ -8090,12 +8053,6 @@ "lines-and-columns": "^1.1.6" } }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true - }, "parseqs": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", @@ -8468,9 +8425,9 @@ "dev": true }, "qunit": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/qunit/-/qunit-2.12.0.tgz", - "integrity": "sha512-Lu3tbKziVzXTfseoEtTiiSAbSPB6SGU4Emc2uo8n+fbsXuRCLzfqPwJfAVJwKu9NdukX1V/L0qWf2UvmPX+QeA==", + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/qunit/-/qunit-2.13.0.tgz", + "integrity": "sha512-RvJquyNKbMSn5Qo28S2wKWxHl1Ku8m0zFLTKsXfq/WZkyM+b28gpEs6YkKN1fOCV4S+979+GnevD0FRgQayo3Q==", "dev": true, "requires": { "commander": "6.2.0", @@ -8873,16 +8830,6 @@ "path-parse": "^1.0.6" } }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - } - }, "resolve-from": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", @@ -8927,45 +8874,12 @@ } }, "rollup": { - "version": "1.32.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.32.1.tgz", - "integrity": "sha512-/2HA0Ec70TvQnXdzynFffkjA6XN+1e2pEv/uKS5Ulca40g2L7KuOE3riasHoNVHOsFD5KKZgDsMk1CP3Tw9s+A==", + "version": "2.34.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.34.2.tgz", + "integrity": "sha512-mvtQLqu3cNeoctS+kZ09iOPxrc1P1/Bt1z15enuQ5feyKOdM3MJAVFjjsygurDpSWn530xB4AlA83TWIzRstXA==", "dev": true, "requires": { - "@types/estree": "*", - "@types/node": "*", - "acorn": "^7.1.0" - } - }, - "rollup-plugin-babel": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-babel/-/rollup-plugin-babel-4.4.0.tgz", - "integrity": "sha512-Lek/TYp1+7g7I+uMfJnnSJ7YWoD58ajo6Oarhlex7lvUce+RCKRuGRSgztDO3/MF/PuGKmUL5iTHKf208UNszw==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.0.0", - "rollup-pluginutils": "^2.8.1" - } - }, - "rollup-plugin-commonjs": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-commonjs/-/rollup-plugin-commonjs-10.1.0.tgz", - "integrity": "sha512-jlXbjZSQg8EIeAAvepNwhJj++qJWNJw1Cl0YnOqKtP5Djx+fFGkp3WRh+W0ASCaFG5w1jhmzDxgu3SJuVxPF4Q==", - "dev": true, - "requires": { - "estree-walker": "^0.6.1", - "is-reference": "^1.1.2", - "magic-string": "^0.25.2", - "resolve": "^1.11.0", - "rollup-pluginutils": "^2.8.1" - }, - "dependencies": { - "estree-walker": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", - "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", - "dev": true - } + "fsevents": "~2.1.2" } }, "rollup-plugin-istanbul": { @@ -8978,48 +8892,16 @@ "rollup-pluginutils": "^2.0.1" } }, - "rollup-plugin-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-json/-/rollup-plugin-json-4.0.0.tgz", - "integrity": "sha512-hgb8N7Cgfw5SZAkb3jf0QXii6QX/FOkiIq2M7BAQIEydjHvTyxXHQiIzZaTFgx1GK0cRCHOCBHIyEkkLdWKxow==", - "dev": true, - "requires": { - "rollup-pluginutils": "^2.5.0" - } - }, - "rollup-plugin-multi-entry": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-multi-entry/-/rollup-plugin-multi-entry-2.1.0.tgz", - "integrity": "sha512-YVVsI15uvbxMKdeYS5NXQa5zbVr/DYdDBBwseC80+KAc7mqDUjM6Qe4wl+jFucVw1yvBDZFk0PPSBZqoLq8xUA==", - "dev": true, - "requires": { - "matched": "^1.0.2" - } - }, - "rollup-plugin-node-resolve": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-5.2.0.tgz", - "integrity": "sha512-jUlyaDXts7TW2CqQ4GaO5VJ4PwwaV8VUGA7+km3n6k6xtOEacf61u0VXwN80phY/evMcaS+9eIeJ9MOyDxt5Zw==", - "dev": true, - "requires": { - "@types/resolve": "0.0.8", - "builtin-modules": "^3.1.0", - "is-module": "^1.0.0", - "resolve": "^1.11.1", - "rollup-pluginutils": "^2.8.1" - } - }, "rollup-plugin-terser": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-5.3.1.tgz", - "integrity": "sha512-1pkwkervMJQGFYvM9nscrUoncPwiKR/K+bHdjv6PFgRo3cgPHoRT83y2Aa3GvINj4539S15t/tpFPb775TDs6w==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", + "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", "dev": true, "requires": { - "@babel/code-frame": "^7.5.5", - "jest-worker": "^24.9.0", - "rollup-pluginutils": "^2.8.2", + "@babel/code-frame": "^7.10.4", + "jest-worker": "^26.2.1", "serialize-javascript": "^4.0.0", - "terser": "^4.6.2" + "terser": "^5.0.0" } }, "rollup-pluginutils": { @@ -9499,9 +9381,9 @@ } }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true } } @@ -9562,9 +9444,9 @@ "dev": true }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, "socket.io-parser": { @@ -9636,9 +9518,9 @@ "dev": true }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true } } @@ -10127,14 +10009,22 @@ } }, "terser": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", - "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.5.1.tgz", + "integrity": "sha512-6VGWZNVP2KTUcltUQJ25TtNjx/XgdDsBDKGt8nN0MpydU36LmbPPcMBd2kmtZNNGVVDLg44k7GKeHHj+4zPIBQ==", "dev": true, "requires": { "commander": "^2.20.0", - "source-map": "~0.6.1", - "source-map-support": "~0.5.12" + "source-map": "~0.7.2", + "source-map-support": "~0.5.19" + }, + "dependencies": { + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + } } }, "text-extensions": { @@ -10730,9 +10620,9 @@ "integrity": "sha512-g8vHMKK2/JGorSfqAZQUmYYNnXmfec4MLhwtEFS+mMs2IDY398GLysy6BH6K+aS1KMNu/xWZ8Sue/X/mdQPliA==" }, "videojs-generate-karma-config": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/videojs-generate-karma-config/-/videojs-generate-karma-config-7.0.0.tgz", - "integrity": "sha512-nC3SZeVx3OtNiCtdjkC+GT4imfuDhGhpaxr/sfNJv2QmvzKhAhGkySRrh01+SLF85e+yAaCeitDYkXP5QlqtJg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/videojs-generate-karma-config/-/videojs-generate-karma-config-7.0.1.tgz", + "integrity": "sha512-XoyPtym+Wi86yZBVTkvljsPou6xzoeuWA4OVQviCjOyKsW+LQnYlVxmNZboAdT7w8ZuQ0HzvmLLHAnfaib7t3A==", "dev": true, "requires": { "is-ci": "^2.0.0", @@ -10746,26 +10636,23 @@ "karma-safari-applescript-launcher": "~0.1.0", "karma-static-server": "^1.0.0", "karma-teamcity-reporter": "^1.1.0", - "qunit": "~2.12.0" + "qunit": "~2.13.0" } }, "videojs-generate-rollup-config": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/videojs-generate-rollup-config/-/videojs-generate-rollup-config-5.0.2.tgz", - "integrity": "sha512-t+1SxvoJ8uqPwTMtZGE29FAM19slrchsbLCwrzCjT5xupbmvlGLwPMuHwoZN4GJcEyx0gYms3XFE3OpEcDEFXQ==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/videojs-generate-rollup-config/-/videojs-generate-rollup-config-6.0.2.tgz", + "integrity": "sha512-n3jPlMFTfGGEhtLFwMrzOSquzvSuBnV81niRn2AF6/QRD+Ze1hopQd42RjVhKy7LCL+MxCaCskCS1v2qh4652w==", "dev": true, "requires": { - "@babel/core": "^7.9.0", - "@babel/plugin-transform-object-assign": "^7.8.3", - "@babel/plugin-transform-runtime": "^7.9.0", - "@babel/preset-env": "^7.9.0", - "rollup-plugin-babel": "^4.4.0", - "rollup-plugin-commonjs": "^10.0.1", + "@rollup/plugin-babel": "^5.2.1", + "@rollup/plugin-commonjs": "^14.0.0", + "@rollup/plugin-json": "^4.1.0", + "@rollup/plugin-multi-entry": "^4.0.0", + "@rollup/plugin-node-resolve": "^9.0.0", + "@videojs/babel-config": "^0.2.0", "rollup-plugin-istanbul": "^2.0.1", - "rollup-plugin-json": "^4.0.0", - "rollup-plugin-multi-entry": "^2.1.0", - "rollup-plugin-node-resolve": "^5.2.0", - "rollup-plugin-terser": "^5.1.1" + "rollup-plugin-terser": "^7.0.2" } }, "videojs-generator-verify": { @@ -10936,9 +10823,9 @@ } }, "ws": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.0.tgz", - "integrity": "sha512-kyFwXuV/5ymf+IXhS6f0+eAFvydbaBW3zjpT6hUdAh/hbVjTIB5EHBGi0bPoCLSK2wcuz3BrEkB9LrYv1Nm4NQ==", + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.1.tgz", + "integrity": "sha512-pTsP8UAfhy3sk1lSk/O/s4tjD0CRwvMnzvwr4OKGX7ZvqZtUyx4KIJB5JWbkykPoc55tixMGgTNoh3k4FkNGFQ==", "dev": true }, "x-is-string": { diff --git a/package.json b/package.json index 8a51741d5..626edc8a1 100644 --- a/package.json +++ b/package.json @@ -76,14 +76,14 @@ "lodash": "^4.17.4", "lodash-compat": "^3.10.0", "nomnoml": "^0.3.0", - "rollup": "^1.19.4", + "rollup": "^2.34.2", "shelljs": "^0.8.2", "sinon": "^8.1.1", "url-toolkit": "^2.1.3", "videojs-contrib-eme": "^3.8.0", "videojs-contrib-quality-levels": "^2.0.4", "videojs-generate-karma-config": "~7.0.0", - "videojs-generate-rollup-config": "~5.0.1", + "videojs-generate-rollup-config": "~6.0.2", "videojs-generator-verify": "~2.0.0", "videojs-http-source-selector": "^1.1.6", "videojs-standard": "^8.0.3" diff --git a/scripts/rollup.config.js b/scripts/rollup.config.js index 55100c486..f9fbecf0a 100644 --- a/scripts/rollup.config.js +++ b/scripts/rollup.config.js @@ -52,8 +52,7 @@ const options = { worker: worker(), uglify: terser({ output: {comments: 'some'}, - compress: {passes: 2}, - include: [/^.+\.min\.js$/] + compress: {passes: 2} }), replace: replace({ "import {version as vhsVersion} from '../package.json';": `const vhsVersion = '${vhs.version}';`, @@ -75,6 +74,14 @@ const options = { return defaults; } }; + +if (process.env.CI_TEST_TYPE) { + if (process.env.CI_TEST_TYPE === 'playback') { + options.testInput = 'test/playback.test.js'; + } else { + options.testInput = {include: ['test/**/*.test.js'], exclude: ['test/playback.test.js']}; + } +} const config = generate(options); // Add additonal builds/customization here! diff --git a/test/videojs-http-streaming.test.js b/test/videojs-http-streaming.test.js index 22033fab5..9fd2eb9d2 100644 --- a/test/videojs-http-streaming.test.js +++ b/test/videojs-http-streaming.test.js @@ -44,6 +44,7 @@ import { import window from 'global/window'; // we need this so the plugin registers itself import 'videojs-contrib-quality-levels'; +import 'videojs-contrib-eme'; import {version as vhsVersion} from '../package.json'; import {version as muxVersion} from 'mux.js/package.json'; From 0976212d8c447b80904a8d1b5f8323579b875be2 Mon Sep 17 00:00:00 2001 From: Brandon Casey <2381475+brandonocasey@users.noreply.github.com> Date: Thu, 10 Dec 2020 15:33:08 -0500 Subject: [PATCH 050/399] chore: remove replace and update packages (#1031) --- package-lock.json | 2986 +++++++++++--------------------------- package.json | 25 +- scripts/rollup.config.js | 17 - 3 files changed, 839 insertions(+), 2189 deletions(-) diff --git a/package-lock.json b/package-lock.json index 55aaed174..d8966b126 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1180,16 +1180,6 @@ "resolve": "^1.17.0" } }, - "@rollup/plugin-replace": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.3.4.tgz", - "integrity": "sha512-waBhMzyAtjCL1GwZes2jaE9MjuQ/DQF2BatH3fRivUF3z0JBFrU0U6iBNC/4WR+2rLKhaAhPWDNPYp4mI6RqdQ==", - "dev": true, - "requires": { - "@rollup/pluginutils": "^3.1.0", - "magic-string": "^0.25.7" - } - }, "@rollup/plugin-virtual": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@rollup/plugin-virtual/-/plugin-virtual-2.0.3.tgz", @@ -1207,15 +1197,6 @@ "picomatch": "^2.2.2" } }, - "@samverschueren/stream-to-observable": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.1.tgz", - "integrity": "sha512-c/qwwcHyafOQuVQJj0IlBjf5yYgBI7YPJ77k4fOJYesb41jio65eaJODRUmfYKhTOFBrIZ66kgvGPlNbjuoRdQ==", - "dev": true, - "requires": { - "any-observable": "^0.3.0" - } - }, "@sinonjs/commons": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.1.tgz", @@ -1297,6 +1278,12 @@ "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==", "dev": true }, + "@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true + }, "@types/resolve": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", @@ -1321,21 +1308,21 @@ } }, "@videojs/generator-helpers": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@videojs/generator-helpers/-/generator-helpers-1.2.0.tgz", - "integrity": "sha512-cXmAatjPnkCJmi5E0+B+XQyXk2iMwRhT5glMrZ8EaoIg5ooLhi3TO3W5zAJkushX6SEi1TzajsuPqKI82e+dqA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@videojs/generator-helpers/-/generator-helpers-2.0.1.tgz", + "integrity": "sha512-YDqfAD9/NEhK+4OAr6QgheY0KM/aVPx7KOktZF8eRKNZn0CZW73WfWPUK6b/xB8gpveZ150Lt9IPodRu3RUkTA==", "dev": true, "requires": { - "conventional-changelog-cli": "^2.0.21", + "conventional-changelog-cli": "^2.1.0", "conventional-changelog-videojs": "^3.0.0", - "cross-env": "^5.2.0", + "cross-env": "^7.0.2", "doctoc": "^1.4.0", - "husky": "^2.7.0", - "lint-staged": "^8.2.1", + "husky": "^4.3.0", + "lint-staged": "^10.4.2", "not-prerelease": "^1.0.1", - "npm-merge-driver-install": "^1.1.1", + "npm-merge-driver-install": "^2.0.0", "npm-run-all": "^4.1.5", - "shx": "^0.3.2" + "shx": "^0.3.3" } }, "@videojs/http-streaming": { @@ -1467,6 +1454,16 @@ "es6-promisify": "^5.0.0" } }, + "aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, "ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -1501,6 +1498,12 @@ "integrity": "sha1-DELU+xcWDVqa8eSEus4cZpIsGyE=", "dev": true }, + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + }, "ansi-escapes": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", @@ -1522,12 +1525,6 @@ "color-convert": "^1.9.0" } }, - "any-observable": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz", - "integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==", - "dev": true - }, "anymatch": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", @@ -1589,24 +1586,6 @@ "sprintf-js": "~1.0.2" } }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true - }, "array-find-index": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", @@ -1619,27 +1598,6 @@ "integrity": "sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=", "dev": true }, - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, - "requires": { - "array-uniq": "^1.0.1" - } - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, "arraybuffer.slice": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", @@ -1652,12 +1610,6 @@ "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", "dev": true }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true - }, "astral-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", @@ -1676,12 +1628,6 @@ "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", "dev": true }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true - }, "babel-code-frame": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", @@ -1880,61 +1826,6 @@ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, "base64-arraybuffer": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz", @@ -2025,32 +1916,12 @@ } }, "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" } }, "browserslist": { @@ -2115,23 +1986,6 @@ "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", "dev": true }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - } - }, "call-bind": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.0.tgz", @@ -2142,36 +1996,12 @@ "get-intrinsic": "^1.0.0" } }, - "caller-callsite": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", - "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", - "dev": true, - "requires": { - "callsites": "^2.0.0" - } - }, - "caller-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", - "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", - "dev": true, - "requires": { - "caller-callsite": "^2.0.0" - } - }, "callsite": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", "dev": true }, - "callsites": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", - "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", - "dev": true - }, "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", @@ -2330,28 +2160,11 @@ "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", "dev": true }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true }, "cli-cursor": { "version": "2.1.0", @@ -2407,13 +2220,13 @@ } }, "cli-truncate": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", - "integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", "dev": true, "requires": { - "slice-ansi": "0.0.4", - "string-width": "^1.0.1" + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" } }, "cli-width": { @@ -2520,16 +2333,6 @@ "integrity": "sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ==", "dev": true }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } - }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -2585,6 +2388,12 @@ "dot-prop": "^5.1.0" } }, + "compare-versions": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz", + "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==", + "dev": true + }, "component-bind": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", @@ -2818,14 +2627,41 @@ "dev": true }, "conventional-changelog-videojs": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/conventional-changelog-videojs/-/conventional-changelog-videojs-3.0.1.tgz", - "integrity": "sha512-SOubwIReSKixpVFc0wFolZO4ELx0rlIPwF1voyWkgGOquzYI9HcDVk8PDGjgQH/6kWIQJu18b9cdGVLWyhCRgg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-videojs/-/conventional-changelog-videojs-3.0.0.tgz", + "integrity": "sha1-GMJt52U1lZmzXyQ4tYl6gg2wtxg=", "dev": true, "requires": { - "compare-func": "^2.0.0", + "compare-func": "^1.3.1", "github-url-from-git": "^1.4.0", "q": "^1.4.1" + }, + "dependencies": { + "compare-func": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-1.3.4.tgz", + "integrity": "sha512-sq2sWtrqKPkEXAC8tEJA1+BqAH9GbFkGBtUOqrUX57VSfwp8xyktctk+uLoRy5eccTdxzDcVIztlYDpKs3Jv1Q==", + "dev": true, + "requires": { + "array-ify": "^1.0.0", + "dot-prop": "^3.0.0" + } + }, + "dot-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-3.0.0.tgz", + "integrity": "sha1-G3CK8JSknJoOfbyteQq6U52sEXc=", + "dev": true, + "requires": { + "is-obj": "^1.0.0" + } + }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "dev": true + } } }, "conventional-changelog-writer": { @@ -2894,12 +2730,6 @@ "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", "dev": true }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true - }, "core-js": { "version": "2.6.12", "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", @@ -2931,26 +2761,23 @@ "dev": true }, "cosmiconfig": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", - "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz", + "integrity": "sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==", "dev": true, "requires": { - "import-fresh": "^2.0.0", - "is-directory": "^0.3.1", - "js-yaml": "^3.13.1", - "parse-json": "^4.0.0" + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" }, "dependencies": { - "parse-json": { + "path-type": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true } } }, @@ -2961,12 +2788,55 @@ "dev": true }, "cross-env": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-5.2.1.tgz", - "integrity": "sha512-1yHhtcfAd1r4nwQgknowuUNfIT9E8dOMMspC36g45dN+iD1blloi7xp8X/xAIDnjHWyt1uQ8PHk2fkNaym7soQ==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", "dev": true, "requires": { - "cross-spawn": "^6.0.5" + "cross-spawn": "^7.0.1" + }, + "dependencies": { + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } } }, "cross-spawn": { @@ -3036,12 +2906,6 @@ "number-is-nan": "^1.0.0" } }, - "date-fns": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", - "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==", - "dev": true - }, "date-format": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/date-format/-/date-format-3.0.0.tgz", @@ -3087,12 +2951,6 @@ } } }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true - }, "dedent": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", @@ -3120,69 +2978,6 @@ "object-keys": "^1.0.12" } }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "del": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz", - "integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=", - "dev": true, - "requires": { - "globby": "^6.1.0", - "is-path-cwd": "^1.0.0", - "is-path-in-cwd": "^1.0.0", - "p-map": "^1.1.1", - "pify": "^3.0.0", - "rimraf": "^2.2.8" - }, - "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } - } - }, "delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", @@ -3368,15 +3163,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.620", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.620.tgz", - "integrity": "sha512-YbgWXUR2Mu+Fp6rm3GZ5YJdNo8SgZKLUTNSl2PNvdOcM8OIz07jRJnRkIaV9vdszFv9UUuGChh19w9qSuoLJgw==", - "dev": true - }, - "elegant-spinner": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", - "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=", + "version": "1.3.621", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.621.tgz", + "integrity": "sha512-FeIuBzArONbAmKmZIsZIFGu/Gc9AVGlVeVbhCq+G2YIl6QkT0TDn2HKN/FMf1btXEB9kEmIuQf3/lBTVAbmFOg==", "dev": true }, "emoji-regex": { @@ -3495,6 +3284,15 @@ "has-binary2": "~1.0.2" } }, + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "requires": { + "ansi-colors": "^4.1.1" + } + }, "ent": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", @@ -3973,88 +3771,107 @@ "dev": true }, "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "exit-hook": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", - "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", - "dev": true - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", "dev": true, "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" }, "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" } }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, + "is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "dev": true + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, "requires": { - "is-extendable": "^0.1.0" + "isexe": "^2.0.0" } } } }, + "exit-hook": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-2.2.0.tgz", + "integrity": "sha512-YFH+2oGdldRH5GqGpnaiKbBxWHMmuXHmKTMtUC58kWSOrnTf95rKITVSFTTtas14DWvWpih429+ffAvFetPwNA==", + "dev": true + }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "dev": true }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, "external-editor": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-1.1.1.tgz", @@ -4077,71 +3894,6 @@ } } }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, "eyes": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", @@ -4176,13 +3928,12 @@ } }, "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", "dev": true, "requires": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" + "escape-string-regexp": "^1.0.5" } }, "file-entry-cache": { @@ -4195,26 +3946,12 @@ } }, "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "to-regex-range": "^5.0.1" } }, "finalhandler": { @@ -4248,6 +3985,15 @@ "path-exists": "^4.0.0" } }, + "find-versions": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-3.2.0.tgz", + "integrity": "sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww==", + "dev": true, + "requires": { + "semver-regex": "^2.0.0" + } + }, "flat-cache": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", @@ -4276,39 +4022,18 @@ "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", "dev": true }, - "fn-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fn-name/-/fn-name-2.0.1.tgz", - "integrity": "sha1-UhTXU3pNBqSjAcDMJi/rhBiAAuc=", - "dev": true - }, "follow-redirects": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz", "integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==", "dev": true }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, "format": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", "integrity": "sha1-1hcBB+nv3E7TDJ3DkBbflCtctYs=", "dev": true }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "map-cache": "^0.2.2" - } - }, "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", @@ -4363,17 +4088,6 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, - "g-status": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/g-status/-/g-status-2.0.2.tgz", - "integrity": "sha512-kQoE9qH+T1AHKgSSD0Hkv98bobE90ILQcXAF4wvGgsr7uFqNvwmh8j+Lq3l0RVt3E3HjSbv2B9biEGcEtpHLCA==", - "dev": true, - "requires": { - "arrify": "^1.0.1", - "matcher": "^1.0.0", - "simple-git": "^1.85.0" - } - }, "gauge": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/gauge/-/gauge-1.2.7.tgz", @@ -4616,20 +4330,14 @@ "dev": true }, "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", "dev": true, "requires": { "pump": "^3.0.0" } }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true - }, "git-raw-commits": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.0.tgz", @@ -4872,19 +4580,6 @@ "integrity": "sha512-LeguVWaxgHN0MNbWC6YljNMzHkrCny9fzjmEUdnF1kQ7wATFD1RHFRqA1qxaX2tgxGENlcxjOflopBwj3YZiXA==", "dev": true }, - "globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", - "dev": true, - "requires": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, "globrex": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", @@ -4990,38 +4685,6 @@ "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", "dev": true }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "hosted-git-info": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.7.tgz", @@ -5136,105 +4799,78 @@ } } }, + "human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "dev": true + }, "husky": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/husky/-/husky-2.7.0.tgz", - "integrity": "sha512-LIi8zzT6PyFpcYKdvWRCn/8X+6SuG2TgYYMrM6ckEYhlp44UcEduVymZGIZNLiwOUjrEud+78w/AsAiqJA/kRg==", - "dev": true, - "requires": { - "cosmiconfig": "^5.2.0", - "execa": "^1.0.0", - "find-up": "^3.0.0", - "get-stdin": "^7.0.0", - "is-ci": "^2.0.0", - "pkg-dir": "^4.1.0", - "please-upgrade-node": "^3.1.1", - "read-pkg": "^5.1.1", - "run-node": "^1.0.0", - "slash": "^3.0.0" + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/husky/-/husky-4.3.5.tgz", + "integrity": "sha512-E5S/1HMoDDaqsH8kDF5zeKEQbYqe3wL9zJDyqyYqc8I4vHBtAoxkDBGXox0lZ9RI+k5GyB728vZdmnM4bYap+g==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "ci-info": "^2.0.0", + "compare-versions": "^3.6.0", + "cosmiconfig": "^7.0.0", + "find-versions": "^3.2.0", + "opencollective-postinstall": "^2.0.2", + "pkg-dir": "^4.2.0", + "please-upgrade-node": "^3.2.0", + "slash": "^3.0.0", + "which-pm-runs": "^1.0.0" }, "dependencies": { - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "locate-path": "^3.0.0" + "color-convert": "^2.0.1" } }, - "get-stdin": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-7.0.0.tgz", - "integrity": "sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ==", - "dev": true - }, - "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", - "dev": true - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", "dev": true, "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" + "color-name": "~1.1.4" } }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" + "has-flag": "^4.0.0" } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true } } }, @@ -5254,13 +4890,13 @@ "dev": true }, "import-fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", - "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.2.tgz", + "integrity": "sha512-cTPNrlvJT6twpYy+YmKUKrTSjWFs3bjYjAhCwm+z4EOCubZxAuO+hHpRN64TqjEaYSHs7tJAE0w1CKMGmsG/lw==", "dev": true, "requires": { - "caller-path": "^2.0.0", - "resolve-from": "^3.0.0" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" } }, "imurmurhash": { @@ -5303,9 +4939,9 @@ "dev": true }, "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.6.tgz", + "integrity": "sha512-IZUoxEjNjubzrmvzZU4lKP7OnYmX72XRl3sqkfJhBKweKi5rnGi5+IUdlj/H1M+Ip5JQ1WzaDMOBRY90Ajc5jg==", "dev": true }, "inquirer": { @@ -5364,6 +5000,31 @@ "restore-cursor": "^1.0.1" } }, + "exit-hook": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", + "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", + "dev": true + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, "onetime": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", @@ -5380,6 +5041,17 @@ "onetime": "^1.0.0" } }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", @@ -5403,26 +5075,6 @@ "loose-envify": "^1.0.0" } }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "is-alphabetical": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", @@ -5484,26 +5136,6 @@ "has": "^1.0.3" } }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "is-date-object": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", @@ -5516,43 +5148,12 @@ "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==", "dev": true }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "is-directory": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", - "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", - "dev": true - }, "is-docker": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.1.1.tgz", "integrity": "sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw==", "dev": true }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -5566,13 +5167,10 @@ "dev": true }, "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true }, "is-function": { "version": "1.0.2", @@ -5607,24 +5205,10 @@ "dev": true }, "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true }, "is-obj": { "version": "2.0.0", @@ -5632,60 +5216,12 @@ "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", "dev": true }, - "is-observable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-1.1.0.tgz", - "integrity": "sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==", - "dev": true, - "requires": { - "symbol-observable": "^1.1.0" - } - }, - "is-path-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", - "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", - "dev": true - }, - "is-path-in-cwd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", - "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", - "dev": true, - "requires": { - "is-path-inside": "^1.0.0" - } - }, - "is-path-inside": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", - "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", - "dev": true, - "requires": { - "path-is-inside": "^1.0.1" - } - }, "is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", "dev": true }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "is-promise": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", - "dev": true - }, "is-reference": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", @@ -5746,12 +5282,6 @@ "integrity": "sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==", "dev": true }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, "is-word-character": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz", @@ -5785,12 +5315,6 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", @@ -6439,57 +5963,97 @@ } }, "lint-staged": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-8.2.1.tgz", - "integrity": "sha512-n0tDGR/rTCgQNwXnUf/eWIpPNddGWxC32ANTNYsj2k02iZb7Cz5ox2tytwBu+2r0zDXMEMKw7Y9OD/qsav561A==", + "version": "10.5.3", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-10.5.3.tgz", + "integrity": "sha512-TanwFfuqUBLufxCc3RUtFEkFraSPNR3WzWcGF39R3f2J7S9+iF9W0KTVLfSy09lYGmZS5NDCxjNvhGMSJyFCWg==", "dev": true, "requires": { - "chalk": "^2.3.1", - "commander": "^2.14.1", - "cosmiconfig": "^5.2.0", - "debug": "^3.1.0", + "chalk": "^4.1.0", + "cli-truncate": "^2.1.0", + "commander": "^6.2.0", + "cosmiconfig": "^7.0.0", + "debug": "^4.2.0", "dedent": "^0.7.0", - "del": "^3.0.0", - "execa": "^1.0.0", - "g-status": "^2.0.2", - "is-glob": "^4.0.0", - "is-windows": "^1.0.2", - "listr": "^0.14.2", - "listr-update-renderer": "^0.5.0", - "lodash": "^4.17.11", - "log-symbols": "^2.2.0", - "micromatch": "^3.1.8", - "npm-which": "^3.0.1", - "p-map": "^1.1.1", - "path-is-inside": "^1.0.2", - "pify": "^3.0.0", - "please-upgrade-node": "^3.0.2", - "staged-git-files": "1.1.2", - "string-argv": "^0.0.2", - "stringify-object": "^3.2.2", - "yup": "^0.27.0" + "enquirer": "^2.3.6", + "execa": "^4.1.0", + "listr2": "^3.2.2", + "log-symbols": "^4.0.0", + "micromatch": "^4.0.2", + "normalize-path": "^3.0.0", + "please-upgrade-node": "^3.2.0", + "string-argv": "0.3.1", + "stringify-object": "^3.3.0" }, "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "commander": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.0.tgz", + "integrity": "sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==", + "dev": true + }, "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } } } }, @@ -6499,114 +6063,69 @@ "integrity": "sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=", "dev": true }, - "listr": { - "version": "0.14.3", - "resolved": "https://registry.npmjs.org/listr/-/listr-0.14.3.tgz", - "integrity": "sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA==", - "dev": true, - "requires": { - "@samverschueren/stream-to-observable": "^0.3.0", - "is-observable": "^1.1.0", - "is-promise": "^2.1.0", - "is-stream": "^1.1.0", - "listr-silent-renderer": "^1.1.1", - "listr-update-renderer": "^0.5.0", - "listr-verbose-renderer": "^0.5.0", - "p-map": "^2.0.0", - "rxjs": "^6.3.3" - }, - "dependencies": { - "p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", - "dev": true - } - } - }, - "listr-silent-renderer": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz", - "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=", - "dev": true - }, - "listr-update-renderer": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz", - "integrity": "sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA==", + "listr2": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.2.3.tgz", + "integrity": "sha512-vUb80S2dSUi8YxXahO8/I/s29GqnOL8ozgHVLjfWQXa03BNEeS1TpBLjh2ruaqq5ufx46BRGvfymdBSuoXET5w==", "dev": true, "requires": { - "chalk": "^1.1.3", - "cli-truncate": "^0.2.1", - "elegant-spinner": "^1.0.1", - "figures": "^1.7.0", - "indent-string": "^3.0.0", - "log-symbols": "^1.0.2", - "log-update": "^2.3.0", - "strip-ansi": "^3.0.1" + "chalk": "^4.1.0", + "cli-truncate": "^2.1.0", + "figures": "^3.2.0", + "indent-string": "^4.0.0", + "log-update": "^4.0.0", + "p-map": "^4.0.0", + "rxjs": "^6.6.3", + "through": "^2.3.8" }, "dependencies": { "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } }, "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "indent-string": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", - "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", - "dev": true - }, - "log-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", - "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "chalk": "^1.0.0" + "color-name": "~1.1.4" } }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true - } - } - }, - "listr-verbose-renderer": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz", - "integrity": "sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "cli-cursor": "^2.1.0", - "date-fns": "^1.27.2", - "figures": "^2.0.0" - }, - "dependencies": { - "figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { - "escape-string-regexp": "^1.0.5" + "has-flag": "^4.0.0" } } } @@ -6730,33 +6249,177 @@ "dev": true }, "log-symbols": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "dev": true, - "requires": { - "chalk": "^2.0.1" - } - }, - "log-update": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-2.3.0.tgz", - "integrity": "sha1-iDKP19HOeTiykoN0bwsbwSayRwg=", - "dev": true, - "requires": { - "ansi-escapes": "^3.0.0", - "cli-cursor": "^2.0.0", - "wrap-ansi": "^3.0.1" - } - }, - "log4js": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.3.0.tgz", - "integrity": "sha512-Mc8jNuSFImQUIateBFwdOQcmC6Q5maU0VVvdC2R6XMb66/VnT+7WS4D/0EeNMZu1YODmJe5NIn2XftCzEocUgw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", + "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", "dev": true, "requires": { - "date-format": "^3.0.0", - "debug": "^4.1.1", + "chalk": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "log-update": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", + "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "dev": true, + "requires": { + "ansi-escapes": "^4.3.0", + "cli-cursor": "^3.1.0", + "slice-ansi": "^4.0.0", + "wrap-ansi": "^6.2.0" + }, + "dependencies": { + "ansi-escapes": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", + "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", + "dev": true, + "requires": { + "type-fest": "^0.11.0" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true + }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + } + }, + "type-fest": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", + "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", + "dev": true + } + } + }, + "log4js": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.3.0.tgz", + "integrity": "sha512-Mc8jNuSFImQUIateBFwdOQcmC6Q5maU0VVvdC2R6XMb66/VnT+7WS4D/0EeNMZu1YODmJe5NIn2XftCzEocUgw==", + "dev": true, + "requires": { + "date-format": "^3.0.0", + "debug": "^4.1.1", "flatted": "^2.0.1", "rfdc": "^1.1.4", "streamroller": "^2.2.4" @@ -6835,27 +6498,12 @@ "sourcemap-codec": "^1.4.4" } }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, "map-obj": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.1.0.tgz", "integrity": "sha512-glc9y00wgtwcDmp7GaE/0b0OnxpNJsVf3ael/An6Fe2Q51LLwN1er6sdomLRzz5h0+yMpiYLhWYF5R7HeqVd4g==", "dev": true }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "requires": { - "object-visit": "^1.0.0" - } - }, "markdown-escapes": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz", @@ -6897,15 +6545,6 @@ "picomatch": "^2.2.1" } }, - "matcher": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/matcher/-/matcher-1.1.1.tgz", - "integrity": "sha512-+BmqxWIubKTRKNWx/ahnCkk3mG8m7OturVlqq6HiojGJTd5hVYbgZm6WzcYPCoB+KBT4Vd6R7WSRG2OADNaCjg==", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.4" - } - }, "mdurl": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", @@ -7015,24 +6654,13 @@ "dev": true }, "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" } }, "micromist": { @@ -7111,27 +6739,6 @@ "kind-of": "^6.0.3" } }, - "mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, "mkdirp": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", @@ -7175,25 +6782,6 @@ "resolved": "https://registry.npmjs.org/mux.js/-/mux.js-5.7.0.tgz", "integrity": "sha512-SINb/qE0iN7YdpbGHtcj8JoHAJWXITUcN9ZCmakThZ8pVGvWukBMCDfJbEVmY2+GqmmrUkLkwUN9Ec2YLUSbuA==" }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - } - }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -7312,12 +6900,6 @@ "abbrev": "1" } }, - "normalize-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-newline/-/normalize-newline-3.0.0.tgz", - "integrity": "sha1-HL6oBKukNgAfg5OKsh7AOdaa6dM=", - "dev": true - }, "normalize-package-data": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.0.tgz", @@ -7358,422 +6940,19 @@ "dependencies": { "semver": { "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "npm-merge-driver": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/npm-merge-driver/-/npm-merge-driver-2.3.6.tgz", - "integrity": "sha512-uPjCEWZ93f379zw0AMEgFtZIlpSSnpXc8BEIcs8yYHEZs5Y3d85OZHisLjNhjbYnbdAznxTq+VbyBWAQZDEm9w==", - "dev": true, - "requires": { - "mkdirp": "^0.5.1", - "yargs": "^10.0.3" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "cross-spawn": { - "version": "5.1.0", - "bundled": true, - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "decamelize": { - "version": "1.2.0", - "bundled": true, - "dev": true - }, - "execa": { - "version": "0.7.0", - "bundled": true, - "dev": true, - "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "find-up": { - "version": "2.1.0", - "bundled": true, - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "get-caller-file": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "get-stream": { - "version": "3.0.0", - "bundled": true, - "dev": true - }, - "invert-kv": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "is-stream": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "isexe": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "lcid": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "lru-cache": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "mem": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "requires": { - "mimic-fn": "^1.0.0" - } - }, - "mimic-fn": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "requires": { - "minimist": "0.0.8" - } - }, - "npm-run-path": { - "version": "2.0.2", - "bundled": true, - "dev": true, - "requires": { - "path-key": "^2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "os-locale": { - "version": "2.1.0", - "bundled": true, - "dev": true, - "requires": { - "execa": "^0.7.0", - "lcid": "^1.0.0", - "mem": "^1.1.0" - } - }, - "p-finally": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "p-limit": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "p-locate": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "path-exists": { - "version": "3.0.0", - "bundled": true, - "dev": true - }, - "path-key": { - "version": "2.0.1", - "bundled": true, - "dev": true - }, - "pseudomap": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "require-directory": { - "version": "2.1.1", - "bundled": true, - "dev": true - }, - "require-main-filename": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "shebang-command": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-eof": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "which": { - "version": "1.3.0", - "bundled": true, - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "wrap-ansi": { - "version": "2.1.0", - "bundled": true, - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - } - }, - "y18n": { - "version": "3.2.1", - "bundled": true, - "dev": true - }, - "yallist": { - "version": "2.1.2", - "bundled": true, - "dev": true - }, - "yargs": { - "version": "10.0.3", - "bundled": true, - "dev": true, - "requires": { - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "find-up": "^2.1.0", - "get-caller-file": "^1.0.1", - "os-locale": "^2.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^8.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "bundled": true, - "dev": true - }, - "cliui": { - "version": "3.2.0", - "bundled": true, - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - }, - "dependencies": { - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - } - } - }, - "string-width": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "bundled": true, - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - } - } - }, - "yargs-parser": { - "version": "8.0.0", - "bundled": true, - "dev": true, - "requires": { - "camelcase": "^4.1.0" - }, - "dependencies": { - "camelcase": { - "version": "4.1.0", - "bundled": true, - "dev": true - } - } - } - } - }, - "npm-merge-driver-install": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/npm-merge-driver-install/-/npm-merge-driver-install-1.1.1.tgz", - "integrity": "sha512-QoEoJ1SAkkVPoZ9p84yel5xiMeXXqpkw1KwA8hP0iVO/NWZUYYgTUkXRL54YJ7HyLK3aTaiQrRVfpPpb9Cm/FA==", - "dev": true, - "requires": { - "find-root": "^1.1.0", - "is-ci": "^1.2.0", - "npm-merge-driver": "^2.3.5" - }, - "dependencies": { - "ci-info": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", - "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", - "dev": true - }, - "is-ci": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", - "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", - "dev": true, - "requires": { - "ci-info": "^1.5.0" - } + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true } } }, - "npm-path": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/npm-path/-/npm-path-2.0.4.tgz", - "integrity": "sha512-IFsj0R9C7ZdR5cP+ET342q77uSRdtWOlWpih5eC+lu29tIDbNEgDbzgVJ5UFvYHWhxDZ5TFkJafFioO0pPQjCw==", + "npm-merge-driver-install": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/npm-merge-driver-install/-/npm-merge-driver-install-2.0.1.tgz", + "integrity": "sha512-fYmv9ylp/OrA+3juab9SYBNI8iF6QvL2VMVVw3QwOhFloeb+3+8HHgIemgmB/JqaxgKBDO+v9nd5TmVl0aGUIg==", "dev": true, "requires": { - "which": "^1.2.10" + "is-ci": "^2.0.0" } }, "npm-run-all": { @@ -7802,17 +6981,6 @@ "path-key": "^2.0.0" } }, - "npm-which": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/npm-which/-/npm-which-3.0.1.tgz", - "integrity": "sha1-kiXybsOihcIJyuZ8OxGmtKtxQKo=", - "dev": true, - "requires": { - "commander": "^2.9.0", - "npm-path": "^2.0.2", - "which": "^1.2.10" - } - }, "npmlog": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-2.0.4.tgz", @@ -7842,37 +7010,6 @@ "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=", "dev": true }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "object-inspect": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz", @@ -7885,15 +7022,6 @@ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "requires": { - "isobject": "^3.0.0" - } - }, "object.assign": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", @@ -7906,15 +7034,6 @@ "object-keys": "^1.1.1" } }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -7942,6 +7061,12 @@ "mimic-fn": "^1.0.0" } }, + "opencollective-postinstall": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", + "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==", + "dev": true + }, "optionator": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", @@ -7993,10 +7118,13 @@ } }, "p-map": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", - "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", - "dev": true + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } }, "p-try": { "version": "2.2.0", @@ -8077,12 +7205,6 @@ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", "dev": true }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true - }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -8182,15 +7304,6 @@ "@babel/runtime": "^7.5.5" } }, - "pkg-can-install": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/pkg-can-install/-/pkg-can-install-1.0.4.tgz", - "integrity": "sha512-we6BP4jR0ZQcDc9G9ptFvFJvYXoHlCT2PAinu98AotA4j8ZeazkUM/VSuFD4aQG3aPcuyBLLZJLxOEfzvEF7gw==", - "dev": true, - "requires": { - "shelljs": "^0.8.3" - } - }, "pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", @@ -8200,136 +7313,6 @@ "find-up": "^4.0.0" } }, - "pkg-ok": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/pkg-ok/-/pkg-ok-2.3.1.tgz", - "integrity": "sha512-ObdQTDZO+zUJpljXM5HZdx+354o5qbQUs05oilAp2WisGoAmFw80y4RKMduZOmGpuXV1DWJ7PkZnkybd8QB68g==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "meow": "^5.0.0", - "normalize-newline": "^3.0.0" - }, - "dependencies": { - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - }, - "camelcase-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz", - "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=", - "dev": true, - "requires": { - "camelcase": "^4.1.0", - "map-obj": "^2.0.0", - "quick-lru": "^1.0.0" - } - }, - "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", - "dev": true - }, - "indent-string": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", - "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", - "dev": true - }, - "map-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz", - "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=", - "dev": true - }, - "meow": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-5.0.0.tgz", - "integrity": "sha512-CbTqYU17ABaLefO8vCU153ZZlprKYWDljcndKKDCFcYQITzWCXZAVk4QMFZPgvzrnUQ3uItnIE/LoUOwrT15Ig==", - "dev": true, - "requires": { - "camelcase-keys": "^4.0.0", - "decamelize-keys": "^1.0.0", - "loud-rejection": "^1.0.0", - "minimist-options": "^3.0.1", - "normalize-package-data": "^2.3.4", - "read-pkg-up": "^3.0.0", - "redent": "^2.0.0", - "trim-newlines": "^2.0.0", - "yargs-parser": "^10.0.0" - } - }, - "minimist-options": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-3.0.2.tgz", - "integrity": "sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==", - "dev": true, - "requires": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0" - } - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "quick-lru": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz", - "integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=", - "dev": true - }, - "redent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz", - "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=", - "dev": true, - "requires": { - "indent-string": "^3.0.0", - "strip-indent": "^2.0.0" - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "strip-indent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", - "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", - "dev": true - }, - "trim-newlines": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz", - "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=", - "dev": true - }, - "yargs-parser": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", - "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", - "dev": true, - "requires": { - "camelcase": "^4.1.0" - } - } - } - }, "please-upgrade-node": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", @@ -8339,12 +7322,6 @@ "semver-compare": "^1.0.0" } }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true - }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -8378,12 +7355,6 @@ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, - "property-expr": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-1.5.1.tgz", - "integrity": "sha512-CGuc0VUTGthpJXL36ydB6jnbyOf/rAHFvmVrJlH+Rg0DqqLFQGAP6hIaxD/G0OAmBJPhXDHuEJigrp0e0wFV6g==", - "dev": true - }, "pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -8680,16 +7651,6 @@ "@babel/runtime": "^7.8.4" } }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - } - }, "regexpp": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", @@ -8766,12 +7727,6 @@ "xtend": "^4.0.1" } }, - "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true - }, "repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", @@ -8831,15 +7786,9 @@ } }, "resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", - "dev": true - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, "restore-cursor": { @@ -8852,12 +7801,6 @@ "signal-exit": "^3.0.2" } }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true - }, "rfdc": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.4.tgz", @@ -8959,12 +7902,6 @@ "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", "dev": true }, - "run-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/run-node/-/run-node-1.0.0.tgz", - "integrity": "sha512-kc120TBlQ3mih1LSzdAJXo4xn/GWS2ec0l3S+syHDXP9uRr0JAT8Qd3mdMuyjqCzeZktgP3try92cEgf9Nks8A==", - "dev": true - }, "rust-result": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/rust-result/-/rust-result-1.0.0.tgz", @@ -9002,15 +7939,6 @@ "rust-result": "^1.0.0" } }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "requires": { - "ret": "~0.1.10" - } - }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -9029,6 +7957,12 @@ "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", "dev": true }, + "semver-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-2.0.0.tgz", + "integrity": "sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw==", + "dev": true + }, "send": { "version": "0.17.1", "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", @@ -9091,29 +8025,6 @@ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, - "set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, "setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", @@ -9152,54 +8063,28 @@ "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz", "integrity": "sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ==", "dev": true, - "requires": { - "glob": "^7.0.0", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" - } - }, - "shx": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/shx/-/shx-0.3.3.tgz", - "integrity": "sha512-nZJ3HFWVoTSyyB+evEKjJ1STiixGztlqwKLTUNV5KqMWtGey9fTd4KU1gdZ1X9BV6215pswQ/Jew9NsuS/fNDA==", - "dev": true, - "requires": { - "minimist": "^1.2.3", - "shelljs": "^0.8.4" - } - }, - "signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", - "dev": true - }, - "simple-git": { - "version": "1.132.0", - "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-1.132.0.tgz", - "integrity": "sha512-xauHm1YqCTom1sC9eOjfq3/9RKiUA9iPnxBbrY2DdL8l4ADMu0jjM5l5lphQP5YWNqAL2aXC/OeuQ76vHtW5fg==", - "dev": true, - "requires": { - "debug": "^4.0.1" - }, - "dependencies": { - "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } + "requires": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + } + }, + "shx": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/shx/-/shx-0.3.3.tgz", + "integrity": "sha512-nZJ3HFWVoTSyyB+evEKjJ1STiixGztlqwKLTUNV5KqMWtGey9fTd4KU1gdZ1X9BV6215pswQ/Jew9NsuS/fNDA==", + "dev": true, + "requires": { + "minimist": "^1.2.3", + "shelljs": "^0.8.4" } }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, "sinon": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/sinon/-/sinon-8.1.1.tgz", @@ -9239,121 +8124,45 @@ "dev": true }, "slice-ansi": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", - "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", - "dev": true - }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", "dev": true, "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" }, "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "color-convert": "^2.0.1" } }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", "dev": true - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "kind-of": "^6.0.0" + "color-name": "~1.1.4" } }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "requires": { - "kind-of": "^3.2.0" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true } } }, @@ -9531,19 +8340,6 @@ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true }, - "source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "dev": true, - "requires": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, "source-map-support": { "version": "0.5.19", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", @@ -9554,12 +8350,6 @@ "source-map": "^0.6.0" } }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, "sourcemap-codec": { "version": "1.4.8", "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", @@ -9617,15 +8407,6 @@ "through": "2" } }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.0" - } - }, "split2": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/split2/-/split2-2.2.0.tgz", @@ -9689,39 +8470,12 @@ "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", "dev": true }, - "staged-git-files": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/staged-git-files/-/staged-git-files-1.1.2.tgz", - "integrity": "sha512-0Eyrk6uXW6tg9PYkhi/V/J4zHp33aNyi2hOCmhFLqLTIhbgqWn5jlSzI+IU0VqrZq6+DbHcabQl/WP6P3BG0QA==", - "dev": true - }, "state-toggle": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.3.tgz", "integrity": "sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ==", "dev": true }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, "statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", @@ -9763,20 +8517,43 @@ } }, "string-argv": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.0.2.tgz", - "integrity": "sha1-2sMECGkMIfPDYwo/86BYd73L1zY=", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz", + "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==", "dev": true }, "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", "dev": true, "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + } } }, "string.prototype.padend": { @@ -9862,6 +8639,12 @@ "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true + }, "strip-indent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", @@ -9895,18 +8678,6 @@ "has-flag": "^3.0.0" } }, - "symbol-observable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", - "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", - "dev": true - }, - "synchronous-promise": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/synchronous-promise/-/synchronous-promise-2.0.15.tgz", - "integrity": "sha512-k8uzYIkIVwmT+TcglpdN50pS2y1BDcUnBPK9iJeGu0Pl1lOI8pD6wtzgw91Pjpe+RxtTncw32tLxs/R0yNL2Mg==", - "dev": true - }, "table": { "version": "5.4.6", "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", @@ -10096,46 +8867,13 @@ "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", "dev": true }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - } - }, "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" + "is-number": "^7.0.0" } }, "toidentifier": { @@ -10144,12 +8882,6 @@ "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", "dev": true }, - "toposort": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", - "integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA=", - "dev": true - }, "traverse": { "version": "0.6.6", "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", @@ -10318,18 +9050,6 @@ "x-is-string": "^0.1.0" } }, - "union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - } - }, "unist-util-is": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-3.0.0.tgz", @@ -10381,46 +9101,6 @@ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", "dev": true }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true - } - } - }, "unzipper": { "version": "0.9.15", "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.9.15.tgz", @@ -10491,23 +9171,11 @@ "punycode": "^2.1.0" } }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, "url-toolkit": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/url-toolkit/-/url-toolkit-2.2.1.tgz", "integrity": "sha512-8+DzgrtDZYZGhHaAop5WGVghMdCfOLGbhcArsJD0qDll71FXa7EeKxi2hilPIscn2nwMz4PRjML32Sz4JTN0Xw==" }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true - }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -10640,9 +9308,9 @@ } }, "videojs-generate-rollup-config": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/videojs-generate-rollup-config/-/videojs-generate-rollup-config-6.0.2.tgz", - "integrity": "sha512-n3jPlMFTfGGEhtLFwMrzOSquzvSuBnV81niRn2AF6/QRD+Ze1hopQd42RjVhKy7LCL+MxCaCskCS1v2qh4652w==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/videojs-generate-rollup-config/-/videojs-generate-rollup-config-6.1.0.tgz", + "integrity": "sha512-V4ehz26zKFSlfPTy6s5b/LwnxKZ1kn+Lx0p8XNC9s9app7ZEFb5j9AxfPmUpY728v1iltI0FgQsSZtCIbfo1Pg==", "dev": true, "requires": { "@rollup/plugin-babel": "^5.2.1", @@ -10656,16 +9324,15 @@ } }, "videojs-generator-verify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/videojs-generator-verify/-/videojs-generator-verify-2.0.0.tgz", - "integrity": "sha512-lYEaCcIEA5zyFQrD2Qs2gCVkbtvhPxZh0L9eswxgxm5CaiKBg/+ZtDpzlqt+l/ZkaF5nO435HUik10PBglXYnQ==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/videojs-generator-verify/-/videojs-generator-verify-3.0.1.tgz", + "integrity": "sha512-60+ac8KSRn9fqmzAtRzwhoSQNzQgCsMjQUF1naui94V5fYV29nzsiwaQLP+rXtpfIZPYgjW2s8XDDmA/Y93rAg==", "dev": true, "requires": { - "colorette": "^1.1.0", - "es-check": "^5.0.0", - "pkg-can-install": "^1.0.4", - "pkg-ok": "^2.3.1", - "shelljs": "^0.8.3" + "colorette": "^1.2.1", + "es-check": "^5.1.1", + "exit-hook": "^2.2.0", + "shelljs": "^0.8.4" } }, "videojs-http-source-selector": { @@ -10724,6 +9391,12 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, + "which-pm-runs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz", + "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=", + "dev": true + }, "winston": { "version": "2.4.5", "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.5.tgz", @@ -10765,44 +9438,53 @@ "dev": true }, "wrap-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz", - "integrity": "sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo=", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "dev": true, "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "dependencies": { "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", "dev": true }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "color-name": "~1.1.4" } }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "^5.0.0" } } } @@ -10869,6 +9551,12 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, + "yaml": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.0.tgz", + "integrity": "sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg==", + "dev": true + }, "yargs": { "version": "15.4.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", @@ -10949,20 +9637,6 @@ "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=", "dev": true - }, - "yup": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/yup/-/yup-0.27.0.tgz", - "integrity": "sha512-v1yFnE4+u9za42gG/b/081E7uNW9mUj3qtkmelLbW5YPROZzSH/KUUyJu9Wt8vxFJcT9otL/eZopS0YK1L5yPQ==", - "dev": true, - "requires": { - "@babel/runtime": "^7.0.0", - "fn-name": "~2.0.1", - "lodash": "^4.17.11", - "property-expr": "^1.5.0", - "synchronous-promise": "^2.0.6", - "toposort": "^2.0.2" - } } } } diff --git a/package.json b/package.json index 626edc8a1..dd871e066 100644 --- a/package.json +++ b/package.json @@ -55,10 +55,10 @@ "src/" ], "dependencies": { - "@babel/runtime": "^7.5.5", + "@babel/runtime": "^7.12.5", "@videojs/vhs-utils": "^2.3.0", "aes-decrypter": "3.1.0", - "global": "^4.3.2", + "global": "^4.4.0", "m3u8-parser": "4.5.0", "mpd-parser": "0.15.0", "mux.js": "5.7.0", @@ -66,8 +66,7 @@ }, "devDependencies": { "@gkatsev/rollup-plugin-bundle-worker": "^1.0.2", - "@rollup/plugin-replace": "^2.3.3", - "@videojs/generator-helpers": "~1.2.0", + "@videojs/generator-helpers": "~2.0.1", "d3": "^3.4.8", "es5-shim": "^4.5.13", "es6-shim": "^0.35.5", @@ -77,16 +76,16 @@ "lodash-compat": "^3.10.0", "nomnoml": "^0.3.0", "rollup": "^2.34.2", - "shelljs": "^0.8.2", + "shelljs": "^0.8.4", "sinon": "^8.1.1", "url-toolkit": "^2.1.3", "videojs-contrib-eme": "^3.8.0", "videojs-contrib-quality-levels": "^2.0.4", "videojs-generate-karma-config": "~7.0.0", - "videojs-generate-rollup-config": "~6.0.2", - "videojs-generator-verify": "~2.0.0", + "videojs-generate-rollup-config": "~6.1.0", + "videojs-generator-verify": "~3.0.1", "videojs-http-source-selector": "^1.1.6", - "videojs-standard": "^8.0.3" + "videojs-standard": "^8.0.4" }, "generator-videojs-plugin": { "version": "7.6.3" @@ -105,13 +104,7 @@ } }, "lint-staged": { - "*.js": [ - "vjsstandard --fix", - "git add" - ], - "README.md": [ - "doctoc --notitle", - "git add" - ] + "*.js": "vjsstandard --fix", + "README.md": "doctoc --notitle" } } diff --git a/scripts/rollup.config.js b/scripts/rollup.config.js index f9fbecf0a..12c072944 100644 --- a/scripts/rollup.config.js +++ b/scripts/rollup.config.js @@ -2,12 +2,6 @@ const generate = require('videojs-generate-rollup-config'); const worker = require('@gkatsev/rollup-plugin-bundle-worker'); const {terser} = require('rollup-plugin-terser'); const createTestData = require('./create-test-data.js'); -const vhs = require('../package.json'); -const mux = require('mux.js/package.json'); -const mpd = require('mpd-parser/package.json'); -const m3u8 = require('m3u8-parser/package.json'); -const aes = require('aes-decrypter/package.json'); -const replace = require('@rollup/plugin-replace'); // see https://github.com/videojs/videojs-generate-rollup-config // for options @@ -35,9 +29,6 @@ const options = { defaults.browser.splice(2, 0, 'worker'); defaults.test.splice(3, 0, 'worker'); - defaults.module.unshift('replace'); - defaults.browser.unshift('replace'); - defaults.test.unshift('replace'); defaults.test.splice(0, 0, 'createTestData'); // istanbul is only in the list for regular builds and not watch @@ -54,14 +45,6 @@ const options = { output: {comments: 'some'}, compress: {passes: 2} }), - replace: replace({ - "import {version as vhsVersion} from '../package.json';": `const vhsVersion = '${vhs.version}';`, - "import {version as muxVersion} from 'mux.js/package.json';": `const muxVersion = '${mux.version}';`, - "import {version as mpdVersion} from 'mpd-parser/package.json';": `const mpdVersion = '${mpd.version}';`, - "import {version as m3u8Version} from 'm3u8-parser/package.json';": `const m3u8Version = '${m3u8.version}';`, - "import {version as aesVersion} from 'aes-decrypter/package.json';": `const aesVersion = '${aes.version}';`, - 'delimiters': ['', ''] - }), createTestData: createTestData() }); }, From 904153f83fe0a270714f5c9dc41dfe59714e3b1e Mon Sep 17 00:00:00 2001 From: Brandon Casey <2381475+brandonocasey@users.noreply.github.com> Date: Tue, 15 Dec 2020 17:29:22 -0500 Subject: [PATCH 051/399] chore: mark many more sources as working (#1035) --- scripts/sources.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/sources.json b/scripts/sources.json index fde635c55..aac4fbb3f 100644 --- a/scripts/sources.json +++ b/scripts/sources.json @@ -311,19 +311,19 @@ "features": [] }, { - "name": "(Not Working) sidx v1 dash", + "name": "sidx v1 dash", "uri": "https://d2zihajmogu5jn.cloudfront.net/sidx-v1-dash/Dog.mpd", "mimetype": "application/dash+xml", "features": [] }, { - "name": "(Not Working) fmp4 x264/flac no manifest codecs", + "name": "fmp4 x264/flac no manifest codecs", "uri": "https://d2zihajmogu5jn.cloudfront.net/fmp4-flac-no-manifest-codecs/master.m3u8", "mimetype": "application/x-mpegurl", "features": [] }, { - "name": "(Not Working) fmp4 x264/opus no manifest codecs", + "name": "fmp4 x264/opus no manifest codecs", "uri": "https://d2zihajmogu5jn.cloudfront.net/fmp4-opus-no-manifest-codecs/master.m3u8", "mimetype": "application/x-mpegurl", "features": [] @@ -336,7 +336,7 @@ }, { "name": "(Not Working) ts one valid codec among many invalid", - "uri": "https://d2zihajmogu5jn.cloudfront.net/ts-one-valid-many-invalid/master.m3u8", + "uri": "https://d2zihajmogu5jn.cloudfront.net/ts-one-valid-many-invalid-codecs/master.m3u8", "mimetype": "application/x-mpegurl", "features": [] } From 8454da54e003f8239695a03208f6dc3381b10feb Mon Sep 17 00:00:00 2001 From: Gary Katsevman Date: Wed, 16 Dec 2020 14:00:43 -0500 Subject: [PATCH 052/399] fix: programmatically create Config getters/setters --- src/videojs-http-streaming.js | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/videojs-http-streaming.js b/src/videojs-http-streaming.js index 9ec9b12ec..355d548a8 100644 --- a/src/videojs-http-streaming.js +++ b/src/videojs-http-streaming.js @@ -60,17 +60,7 @@ const Vhs = { }; // Define getter/setters for config properties -[ - 'GOAL_BUFFER_LENGTH', - 'MAX_GOAL_BUFFER_LENGTH', - 'BACK_BUFFER_LENGTH', - 'GOAL_BUFFER_LENGTH_RATE', - 'BUFFER_LOW_WATER_LINE', - 'MAX_BUFFER_LOW_WATER_LINE', - 'EXPERIMENTAL_MAX_BUFFER_LOW_WATER_LINE', - 'BUFFER_LOW_WATER_LINE_RATE', - 'BANDWIDTH_VARIANCE' -].forEach((prop) => { +Object.keys(Config).forEach((prop) => { Object.defineProperty(Vhs, prop, { get() { videojs.log.warn(`using Vhs.${prop} is UNSAFE be sure you know what you are doing`); From 2e237eef58c08eccee3e3e595effbec0a4d6b89b Mon Sep 17 00:00:00 2001 From: Gary Katsevman Date: Mon, 21 Dec 2020 16:15:45 -0500 Subject: [PATCH 053/399] fix: if a playlist was last requested less than half target duration, delay retry (#1038) --- src/master-playlist-controller.js | 8 +- src/playlist-loader.js | 14 +- test/manifests/one-rendition.m3u8 | 4 + test/manifests/two-renditions.m3u8 | 6 + test/master-playlist-controller.test.js | 167 ++++++++++++++++++++++++ 5 files changed, 193 insertions(+), 6 deletions(-) create mode 100644 test/manifests/one-rendition.m3u8 create mode 100644 test/manifests/two-renditions.m3u8 diff --git a/src/master-playlist-controller.js b/src/master-playlist-controller.js index 8ac13075d..4017667d4 100644 --- a/src/master-playlist-controller.js +++ b/src/master-playlist-controller.js @@ -1015,6 +1015,7 @@ export class MasterPlaylistController extends videojs.EventTarget { 'Trying again since it is the only playlist.'); this.tech_.trigger('retryplaylist'); + // if this is a final rendition, we should delay return this.masterPlaylistLoader_.load(isFinalRendition); } @@ -1086,7 +1087,12 @@ export class MasterPlaylistController extends videojs.EventTarget { this.delegateLoaders_('main', ['abort', 'pause']); - return this.masterPlaylistLoader_.media(nextPlaylist, isFinalRendition); + const delayDuration = (nextPlaylist.targetDuration / 2) * 1000 || 5 * 1000; + const shouldDelay = typeof nextPlaylist.lastRequest === 'number' && + (Date.now() - nextPlaylist.lastRequest) <= delayDuration; + + // delay if it's a final rendition or if the last refresh is sooner than half targetDuration + return this.masterPlaylistLoader_.media(nextPlaylist, isFinalRendition || shouldDelay); } /** diff --git a/src/playlist-loader.js b/src/playlist-loader.js index 6089577fe..275985496 100644 --- a/src/playlist-loader.js +++ b/src/playlist-loader.js @@ -251,6 +251,8 @@ export default class PlaylistLoader extends EventTarget { customTagMappers: this.customTagMappers }); + playlist.lastRequest = Date.now(); + setupMediaPlaylist({ playlist, uri: url, @@ -312,11 +314,11 @@ export default class PlaylistLoader extends EventTarget { * * @param {Object=} playlist the parsed media playlist * object to switch to - * @param {boolean=} is this the last available playlist + * @param {boolean=} shouldDelay whether we should delay the request by half target duration * * @return {Playlist} the current loaded media */ - media(playlist, isFinalRendition) { + media(playlist, shouldDelay) { // getter if (!playlist) { return this.media_; @@ -338,7 +340,7 @@ export default class PlaylistLoader extends EventTarget { window.clearTimeout(this.finalRenditionTimeout); - if (isFinalRendition) { + if (shouldDelay) { const delay = (playlist.targetDuration / 2) * 1000 || 5 * 1000; this.finalRenditionTimeout = @@ -414,6 +416,8 @@ export default class PlaylistLoader extends EventTarget { return; } + playlist.lastRequest = Date.now(); + playlist.resolvedUri = resolveManifestRedirect(this.handleManifestRedirects, playlist.resolvedUri, req); if (error) { @@ -464,12 +468,12 @@ export default class PlaylistLoader extends EventTarget { /** * start loading of the playlist */ - load(isFinalRendition) { + load(shouldDelay) { window.clearTimeout(this.mediaUpdateTimeout); const media = this.media(); - if (isFinalRendition) { + if (shouldDelay) { const delay = media ? (media.targetDuration / 2) * 1000 : 5 * 1000; this.mediaUpdateTimeout = window.setTimeout(() => this.load(), delay); diff --git a/test/manifests/one-rendition.m3u8 b/test/manifests/one-rendition.m3u8 new file mode 100644 index 000000000..65516db41 --- /dev/null +++ b/test/manifests/one-rendition.m3u8 @@ -0,0 +1,4 @@ +# A simple main playlist with a single media playlist +#EXTM3U +#EXT-X-STREAM-INF:BANDWIDTH=240000,RESOLUTION=396x224 +media.m3u8 diff --git a/test/manifests/two-renditions.m3u8 b/test/manifests/two-renditions.m3u8 new file mode 100644 index 000000000..cd9c38aff --- /dev/null +++ b/test/manifests/two-renditions.m3u8 @@ -0,0 +1,6 @@ +# A simple main playlist with 2 media playlists +#EXTM3U +#EXT-X-STREAM-INF:BANDWIDTH=240000,RESOLUTION=396x224 +media.m3u8 +#EXT-X-STREAM-INF:BANDWIDTH=40000 +media1.m3u8 diff --git a/test/master-playlist-controller.test.js b/test/master-playlist-controller.test.js index dd503511c..7197a99dc 100644 --- a/test/master-playlist-controller.test.js +++ b/test/master-playlist-controller.test.js @@ -5718,3 +5718,170 @@ QUnit.test('false without nextPlaylist', function(assert) { this.env.log.warn.callCount = 0; }); + +QUnit.module('MasterPlaylistController blacklistCurrentPlaylist', sharedHooks); + +QUnit.test("don't exclude only playlist unless it was excluded forever", function(assert) { + // expect 9 because we have a failing assertion that shouldn't run unless something is broken + assert.expect(9); + + this.requests.length = 0; + this.player.dispose(); + this.player = createPlayer(); + this.player.src({ + src: 'manifest/one-rendition.m3u8', + type: 'application/vnd.apple.mpegurl' + }); + + this.clock.tick(1); + + this.masterPlaylistController = this.player.tech_.vhs.masterPlaylistController_; + + // main + this.standardXHRResponse(this.requests.shift()); + // media + this.standardXHRResponse(this.requests.shift()); + + let mpc = this.masterPlaylistController; + let mpl = mpc.masterPlaylistLoader_; + let playlist = mpl.master.playlists[0]; + let shouldDelay = false; + + mpl.load = (delay) => (shouldDelay = delay); + + mpc.blacklistCurrentPlaylist(); + + assert.notOk('excludeUntil' in playlist, 'playlist was not excluded since excludeDuration was finite'); + assert.ok(shouldDelay, 'we delay retry since it is the final rendition'); + assert.equal(this.env.log.warn.callCount, 1, 'logged a warning'); + + this.requests.length = 0; + // reload source to exclude forever + this.player.src({ + src: 'manifest/one-rendition.m3u8', + type: 'application/vnd.apple.mpegurl' + }); + + this.clock.tick(1); + + this.masterPlaylistController = this.player.tech_.vhs.masterPlaylistController_; + + // main + this.standardXHRResponse(this.requests.shift()); + // media + this.standardXHRResponse(this.requests.shift()); + + mpc = this.masterPlaylistController; + mpl = mpc.masterPlaylistLoader_; + playlist = mpl.master.playlists[0]; + shouldDelay = false; + + mpl.load = (delay) => { + shouldDelay = delay; + assert.ok(false, 'load should not be called in this case'); + }; + mpc.on('error', () => { + assert.ok(true, 'we triggered a playback error'); + }); + + // exclude forever + mpc.blacklistCurrentPlaylist({}, Infinity); + + assert.ok('excludeUntil' in playlist, 'playlist was excluded'); + assert.notOk(shouldDelay, 'value was not changed'); + assert.equal(this.env.log.error.callCount, 1, 'logged an error'); + + this.env.log.warn.callCount = 0; + this.env.log.error.callCount = 0; +}); + +QUnit.test('switch playlists if current playlist gets excluded and re-include if final rendition', function(assert) { + this.requests.length = 0; + this.player.dispose(); + this.player = createPlayer(); + this.player.src({ + src: 'manifest/two-renditions.m3u8', + type: 'application/vnd.apple.mpegurl' + }); + + this.clock.tick(1); + + this.masterPlaylistController = this.player.tech_.vhs.masterPlaylistController_; + + // main + this.standardXHRResponse(this.requests.shift()); + // media + this.standardXHRResponse(this.requests.shift()); + + const mpc = this.masterPlaylistController; + const mpl = mpc.masterPlaylistLoader_; + const playlist = mpl.master.playlists[0]; + let playlist2 = mpl.master.playlists[1]; + let shouldDelay = false; + + mpl.load = (delay) => (shouldDelay = delay); + + mpc.blacklistCurrentPlaylist(); + + assert.ok('excludeUntil' in playlist, 'playlist was excluded since there is another playlist'); + assert.notOk(shouldDelay, 'we do not delay retry since it is not the final rendition'); + assert.equal(this.env.log.warn.callCount, 1, 'logged a warning'); + + // ignore segment request + this.requests.shift(); + // media1 + this.standardXHRResponse(this.requests.shift()); + playlist2 = mpl.master.playlists[1]; + + mpc.blacklistCurrentPlaylist(); + + assert.ok('excludeUntil' in playlist2, 'playlist2 was excluded'); + assert.notOk('excludeUntil' in playlist, 'playlist was re-included'); + assert.equal(this.env.log.warn.callCount, 3, 'logged another warning'); + assert.ok( + this.env.log.warn.calledWith('Removing other playlists from the exclusion list because the last rendition is about to be excluded.'), + 'we logged a warning that we reincluded playlists' + ); + + this.env.log.warn.callCount = 0; +}); + +QUnit.test('should delay loading of new playlist if lastRequest was less than half target duration', function(assert) { + this.requests.length = 0; + this.player.dispose(); + this.player = createPlayer(); + this.player.src({ + src: 'manifest/two-renditions.m3u8', + type: 'application/vnd.apple.mpegurl' + }); + + this.clock.tick(1); + + this.masterPlaylistController = this.player.tech_.vhs.masterPlaylistController_; + + // main + this.standardXHRResponse(this.requests.shift()); + // media + this.standardXHRResponse(this.requests.shift()); + + const mpc = this.masterPlaylistController; + const mpl = mpc.masterPlaylistLoader_; + const oldMplMedia = mpl.media; + const playlist = mpl.master.playlists[0]; + const playlist2 = mpl.master.playlists[1]; + let shouldDelay = false; + + mpl.media = (nextPlaylist, delay) => { + shouldDelay = delay; + return oldMplMedia.call(mpl, nextPlaylist, delay); + }; + playlist2.lastRequest = Date.now() - 1000; + + mpc.blacklistCurrentPlaylist(); + + assert.ok('excludeUntil' in playlist, 'playlist was excluded since there is another playlist'); + assert.ok(shouldDelay, 'we delay retry since second rendition was loaded less than half target duration ago'); + assert.equal(this.env.log.warn.callCount, 1, 'logged a warning'); + + this.env.log.warn.callCount = 0; +}); From 6c337e18fc009ae2e201af4b3816898bafd2c3b1 Mon Sep 17 00:00:00 2001 From: Gary Katsevman Date: Tue, 22 Dec 2020 14:05:43 -0500 Subject: [PATCH 054/399] 2.4.1 --- CHANGELOG.md | 15 +++++++++++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a7577cc22..b1fc2c164 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,18 @@ + +## [2.4.1](https://github.com/videojs/http-streaming/compare/v2.4.0...v2.4.1) (2020-12-22) + +### Bug Fixes + +* if a playlist was last requested less than half target duration, delay retry ([#1038](https://github.com/videojs/http-streaming/issues/1038)) ([2e237ee](https://github.com/videojs/http-streaming/commit/2e237ee)) +* programmatically create Config getters/setters ([8454da5](https://github.com/videojs/http-streaming/commit/8454da5)) + +### Chores + +* **demo:** clear type on manual source change ([#1030](https://github.com/videojs/http-streaming/issues/1030)) ([d39276d](https://github.com/videojs/http-streaming/commit/d39276d)) +* mark many more sources as working ([#1035](https://github.com/videojs/http-streaming/issues/1035)) ([904153f](https://github.com/videojs/http-streaming/commit/904153f)) +* move playback tests to a separate ci run ([#1028](https://github.com/videojs/http-streaming/issues/1028)) ([f1d9f6e](https://github.com/videojs/http-streaming/commit/f1d9f6e)) +* remove replace and update packages ([#1031](https://github.com/videojs/http-streaming/issues/1031)) ([0976212](https://github.com/videojs/http-streaming/commit/0976212)) + # [2.4.0](https://github.com/videojs/http-streaming/compare/v2.3.0...v2.4.0) (2020-12-07) diff --git a/package-lock.json b/package-lock.json index d8966b126..05b2abced 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@videojs/http-streaming", - "version": "2.4.0", + "version": "2.4.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index dd871e066..dcc5d7ac5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@videojs/http-streaming", - "version": "2.4.0", + "version": "2.4.1", "description": "Play back HLS and DASH with Video.js, even where it's not natively supported", "main": "dist/videojs-http-streaming.cjs.js", "module": "dist/videojs-http-streaming.es.js", From 9919b85a6ec71b446a86887fcd5f2d8475ddf4ad Mon Sep 17 00:00:00 2001 From: Garrett Singer Date: Wed, 6 Jan 2021 15:31:08 -0500 Subject: [PATCH 055/399] fix: handle rollover and don't set wrong timing info for segments with high PTS/DTS values (#1040) --- docs/creating-content.md | 77 ++++++++ package-lock.json | 6 +- package.json | 2 +- src/media-segment-request.js | 43 +++++ src/segment-loader.js | 60 ++++--- src/segment-transmuxer.js | 4 + src/transmuxer-worker.js | 24 +++ src/util/segment.js | 4 + test/media-segment-request.test.js | 45 +++-- test/segment-loader.test.js | 264 ++++++++++++++++++++++++++++ test/segment-transmuxer.test.js | 9 +- test/segments/audioLargeOffset.ts | Bin 0 -> 2068 bytes test/segments/audioLargeOffset2.ts | Bin 0 -> 2068 bytes test/segments/audioMaxOffset.ts | Bin 0 -> 2068 bytes test/segments/audioMinOffset.ts | Bin 0 -> 2068 bytes test/segments/videoLargeOffset.ts | Bin 0 -> 4512 bytes test/segments/videoLargeOffset2.ts | Bin 0 -> 4512 bytes test/segments/videoMaxOffset.ts | Bin 0 -> 4512 bytes test/segments/videoMinOffset.ts | Bin 0 -> 4512 bytes test/transmuxer-worker.test.js | 5 + test/videojs-http-streaming.test.js | 2 +- 21 files changed, 503 insertions(+), 42 deletions(-) create mode 100644 test/segments/audioLargeOffset.ts create mode 100644 test/segments/audioLargeOffset2.ts create mode 100644 test/segments/audioMaxOffset.ts create mode 100644 test/segments/audioMinOffset.ts create mode 100644 test/segments/videoLargeOffset.ts create mode 100644 test/segments/videoLargeOffset2.ts create mode 100644 test/segments/videoMaxOffset.ts create mode 100644 test/segments/videoMinOffset.ts diff --git a/docs/creating-content.md b/docs/creating-content.md index 0caf9b864..3ac4e1488 100644 --- a/docs/creating-content.md +++ b/docs/creating-content.md @@ -41,6 +41,83 @@ Copy only the first two audio frames, leave out video. $ ffmpeg -i index0.ts -aframes 2 -vn -acodec copy audio.ts ``` +### videoMinOffset.ts + +video.ts but with an offset of 0 + +``` +$ ffmpeg -i video.ts -muxpreload 0 -muxdelay 0 -vcodec copy videoMinOffset.ts +``` + +### audioMinOffset.ts + +audio.ts but with an offset of 0. Note that muxed.ts is used because ffmpeg didn't like +the use of audio.ts + +``` +$ ffmpeg -i muxed.ts -muxpreload 0 -muxdelay 0 -acodec copy -vn audioMinOffset.ts +``` + +### videoMaxOffset.ts + +This segment offsets content such that it ends at exactly the max timestamp before a rollover occurs. It uses the max timestamp of 2^33 (8589934592) minus the segment duration of 6006 (0.066733 seconds) in order to not rollover mid segment, and divides the value by 90,000 to convert it from media time to seconds. + +(2^33 - 6006) / 90,000 = 95443.6509556 + +``` +$ ffmpeg -i videoMinOffset.ts -muxdelay 95443.6509556 -muxpreload 95443.6509556 -output_ts_offset 95443.6509556 -vcodec copy videoMaxOffset.ts +``` + +### audioMaxOffset.ts + +This segment offsets content such that it ends at exactly the max timestamp before a rollover occurs. It uses the max timestamp of 2^33 (8589934592) minus the segment duration of 11520 (0.128000 seconds) in order to not rollover mid segment, and divides the value by 90,000 to convert it from media time to seconds. + +(2^33 - 11520) / 90,000 = 95443.5896889 + +``` +$ ffmpeg -i audioMinOffset.ts -muxdelay 95443.5896889 -muxpreload 95443.5896889 -output_ts_offset 95443.5896889 -acodec copy audioMaxOffset.ts +``` + +### videoLargeOffset.ts + +This segment offsets content by the rollover threshhold of 2^32 (4294967296) found in the rollover handling of mux.js, adds 1 to ensure there aren't any cases where there's an equal match, then divides the value by 90,000 to convert it from media time to seconds. + +(2^32 + 1) / 90,000 = 47721.8588556 + +``` +$ ffmpeg -i videoMinOffset.ts -muxdelay 47721.8588556 -muxpreload 47721.8588556 -output_ts_offset 47721.8588556 -vcodec copy videoLargeOffset.ts +``` + +### audioLargeOffset.ts + +This segment offsets content by the rollover threshhold of 2^32 (4294967296) found in the rollover handling of mux.js, adds 1 to ensure there aren't any cases where there's an equal match, then divides the value by 90,000 to convert it from media time to seconds. + +(2^32 + 1) / 90,000 = 47721.8588556 + +``` +$ ffmpeg -i audioMinOffset.ts -muxdelay 47721.8588556 -muxpreload 47721.8588556 -output_ts_offset 47721.8588556 -acodec copy audioLargeOffset.ts +``` + +### videoLargeOffset2.ts + +This takes videoLargeOffset.ts and adds the duration of videoLargeOffset.ts (6006 / 90,000 = 0.066733 seconds) to its offset so that this segment can act as the second in one continuous stream. + +47721.8588556 + 0.066733 = 47721.9255886 + +``` +$ ffmpeg -i videoLargeOffset.ts -muxdelay 47721.9255886 -muxpreload 47721.9255886 -output_ts_offset 47721.9255886 -vcodec copy videoLargeOffset2.ts +``` + +### audioLargeOffset2.ts + +This takes audioLargeOffset.ts and adds the duration of audioLargeOffset.ts (11520 / 90,000 = 0.128 seconds) to its offset so that this segment can act as the second in one continuous stream. + +47721.8588556 + 0.128 = 47721.9868556 + +``` +$ ffmpeg -i audioLargeOffset.ts -muxdelay 47721.9868556 -muxpreload 47721.9868556 -output_ts_offset 47721.9868556 -acodec copy audioLargeOffset2.ts +``` + ### caption.ts Copy the first two frames of video out of a ts segment that already includes CEA-608 captions. diff --git a/package-lock.json b/package-lock.json index 05b2abced..f842a7426 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6778,9 +6778,9 @@ "dev": true }, "mux.js": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/mux.js/-/mux.js-5.7.0.tgz", - "integrity": "sha512-SINb/qE0iN7YdpbGHtcj8JoHAJWXITUcN9ZCmakThZ8pVGvWukBMCDfJbEVmY2+GqmmrUkLkwUN9Ec2YLUSbuA==" + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/mux.js/-/mux.js-5.8.0.tgz", + "integrity": "sha512-v56I2YPyCq1bVbXW7vcuvQs8iHrDy7AeXsZyG1kxCxBUqUjZD0Xq/cU1wrd5dy9YTxRpvw37aTQ4ILwi40GXiw==" }, "natural-compare": { "version": "1.4.0", diff --git a/package.json b/package.json index dcc5d7ac5..a3f3e4516 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "global": "^4.4.0", "m3u8-parser": "4.5.0", "mpd-parser": "0.15.0", - "mux.js": "5.7.0", + "mux.js": "5.8.0", "video.js": "^6 || ^7" }, "devDependencies": { diff --git a/src/media-segment-request.js b/src/media-segment-request.js index 71ab09952..009054013 100644 --- a/src/media-segment-request.js +++ b/src/media-segment-request.js @@ -263,6 +263,7 @@ const transmuxAndNotify = ({ trackInfoFn, timingInfoFn, videoSegmentTimingInfoFn, + audioSegmentTimingInfoFn, id3Fn, captionsFn, dataFn, @@ -350,6 +351,9 @@ const transmuxAndNotify = ({ onVideoSegmentTimingInfo: (videoSegmentTimingInfo) => { videoSegmentTimingInfoFn(videoSegmentTimingInfo); }, + onAudioSegmentTimingInfo: (audioSegmentTimingInfo) => { + audioSegmentTimingInfoFn(audioSegmentTimingInfo); + }, onId3: (id3Frames, dispatchType) => { id3Fn(segment, id3Frames, dispatchType); }, @@ -375,6 +379,7 @@ const handleSegmentBytes = ({ trackInfoFn, timingInfoFn, videoSegmentTimingInfoFn, + audioSegmentTimingInfoFn, id3Fn, captionsFn, dataFn, @@ -505,6 +510,7 @@ const handleSegmentBytes = ({ trackInfoFn, timingInfoFn, videoSegmentTimingInfoFn, + audioSegmentTimingInfoFn, id3Fn, captionsFn, dataFn, @@ -520,6 +526,13 @@ const handleSegmentBytes = ({ * @param {Object} segment - a simplified copy of the segmentInfo object * from SegmentLoader * @param {Function} trackInfoFn - a callback that receives track info + * @param {Function} timingInfoFn - a callback that receives timing info + * @param {Function} videoSegmentTimingInfoFn + * a callback that receives video timing info based on media times and + * any adjustments made by the transmuxer + * @param {Function} audioSegmentTimingInfoFn + * a callback that receives audio timing info based on media times and + * any adjustments made by the transmuxer * @param {Function} dataFn - a callback that is executed when segment bytes are available * and ready to use * @param {Function} doneFn - a callback that is executed after decryption has completed @@ -530,6 +543,7 @@ const decryptSegment = ({ trackInfoFn, timingInfoFn, videoSegmentTimingInfoFn, + audioSegmentTimingInfoFn, id3Fn, captionsFn, dataFn, @@ -553,6 +567,7 @@ const decryptSegment = ({ trackInfoFn, timingInfoFn, videoSegmentTimingInfoFn, + audioSegmentTimingInfoFn, id3Fn, captionsFn, dataFn, @@ -595,6 +610,12 @@ const decryptSegment = ({ * routines * @param {Function} trackInfoFn - a callback that receives track info * @param {Function} timingInfoFn - a callback that receives timing info + * @param {Function} videoSegmentTimingInfoFn + * a callback that receives video timing info based on media times and + * any adjustments made by the transmuxer + * @param {Function} audioSegmentTimingInfoFn + * a callback that receives audio timing info based on media times and + * any adjustments made by the transmuxer * @param {Function} id3Fn - a callback that receives ID3 metadata * @param {Function} captionsFn - a callback that receives captions * @param {Function} dataFn - a callback that is executed when segment bytes are available @@ -608,6 +629,7 @@ const waitForCompletion = ({ trackInfoFn, timingInfoFn, videoSegmentTimingInfoFn, + audioSegmentTimingInfoFn, id3Fn, captionsFn, dataFn, @@ -653,6 +675,7 @@ const waitForCompletion = ({ trackInfoFn, timingInfoFn, videoSegmentTimingInfoFn, + audioSegmentTimingInfoFn, id3Fn, captionsFn, dataFn, @@ -667,6 +690,7 @@ const waitForCompletion = ({ trackInfoFn, timingInfoFn, videoSegmentTimingInfoFn, + audioSegmentTimingInfoFn, id3Fn, captionsFn, dataFn, @@ -701,6 +725,13 @@ const handleLoadEnd = ({ loadendState, abortFn }) => (event) => { * @param {Function} progressFn - a callback that is executed each time a progress event * is received * @param {Function} trackInfoFn - a callback that receives track info + * @param {Function} timingInfoFn - a callback that receives timing info + * @param {Function} videoSegmentTimingInfoFn + * a callback that receives video timing info based on media times and + * any adjustments made by the transmuxer + * @param {Function} audioSegmentTimingInfoFn + * a callback that receives audio timing info based on media times and + * any adjustments made by the transmuxer * @param {Function} dataFn - a callback that is executed when segment bytes are available * and ready to use * @param {Event} event - the progress event object from XMLHttpRequest @@ -711,6 +742,7 @@ const handleProgress = ({ trackInfoFn, timingInfoFn, videoSegmentTimingInfoFn, + audioSegmentTimingInfoFn, id3Fn, captionsFn, dataFn, @@ -747,6 +779,7 @@ const handleProgress = ({ trackInfoFn, timingInfoFn, videoSegmentTimingInfoFn, + audioSegmentTimingInfoFn, id3Fn, captionsFn, dataFn @@ -811,6 +844,13 @@ const handleProgress = ({ * @param {Function} progressFn - a callback that receives progress events from the main * segment's xhr request * @param {Function} trackInfoFn - a callback that receives track info + * @param {Function} timingInfoFn - a callback that receives timing info + * @param {Function} videoSegmentTimingInfoFn + * a callback that receives video timing info based on media times and + * any adjustments made by the transmuxer + * @param {Function} audioSegmentTimingInfoFn + * a callback that receives audio timing info based on media times and + * any adjustments made by the transmuxer * @param {Function} id3Fn - a callback that receives ID3 metadata * @param {Function} captionsFn - a callback that receives captions * @param {Function} dataFn - a callback that receives data from the main segment's xhr @@ -830,6 +870,7 @@ export const mediaSegmentRequest = ({ trackInfoFn, timingInfoFn, videoSegmentTimingInfoFn, + audioSegmentTimingInfoFn, id3Fn, captionsFn, dataFn, @@ -843,6 +884,7 @@ export const mediaSegmentRequest = ({ trackInfoFn, timingInfoFn, videoSegmentTimingInfoFn, + audioSegmentTimingInfoFn, id3Fn, captionsFn, dataFn, @@ -909,6 +951,7 @@ export const mediaSegmentRequest = ({ trackInfoFn, timingInfoFn, videoSegmentTimingInfoFn, + audioSegmentTimingInfoFn, id3Fn, captionsFn, dataFn, diff --git a/src/segment-loader.js b/src/segment-loader.js index 360c4c536..ac689dad8 100644 --- a/src/segment-loader.js +++ b/src/segment-loader.js @@ -2067,26 +2067,31 @@ export default class SegmentLoader extends videojs.EventTarget { }); } - handleVideoSegmentTimingInfo_(requestId, videoSegmentTimingInfo) { + handleSegmentTimingInfo_(type, requestId, segmentTimingInfo) { if (!this.pendingSegment_ || requestId !== this.pendingSegment_.requestId) { return; } const segment = this.pendingSegment_.segment; - - if (!segment.videoTimingInfo) { - segment.videoTimingInfo = {}; - } - - segment.videoTimingInfo.transmuxerPrependedSeconds = - videoSegmentTimingInfo.prependedContentDuration || 0; - segment.videoTimingInfo.transmuxedPresentationStart = - videoSegmentTimingInfo.start.presentation; - segment.videoTimingInfo.transmuxedPresentationEnd = - videoSegmentTimingInfo.end.presentation; + const timingInfoProperty = `${type}TimingInfo`; + + if (!segment[timingInfoProperty]) { + segment[timingInfoProperty] = {}; + } + + segment[timingInfoProperty].transmuxerPrependedSeconds = + segmentTimingInfo.prependedContentDuration || 0; + segment[timingInfoProperty].transmuxedPresentationStart = + segmentTimingInfo.start.presentation; + segment[timingInfoProperty].transmuxedDecodeStart = + segmentTimingInfo.start.decode; + segment[timingInfoProperty].transmuxedPresentationEnd = + segmentTimingInfo.end.presentation; + segment[timingInfoProperty].transmuxedDecodeEnd = + segmentTimingInfo.end.decode; // mainly used as a reference for debugging - segment.videoTimingInfo.baseMediaDecodeTime = - videoSegmentTimingInfo.baseMediaDecodeTime; + segment[timingInfoProperty].baseMediaDecodeTime = + segmentTimingInfo.baseMediaDecodeTime; } appendData_(segmentInfo, result) { @@ -2209,7 +2214,8 @@ export default class SegmentLoader extends videojs.EventTarget { progressFn: this.handleProgress_.bind(this), trackInfoFn: this.handleTrackInfo_.bind(this), timingInfoFn: this.handleTimingInfo_.bind(this), - videoSegmentTimingInfoFn: this.handleVideoSegmentTimingInfo_.bind(this, segmentInfo.requestId), + videoSegmentTimingInfoFn: this.handleSegmentTimingInfo_.bind(this, 'video', segmentInfo.requestId), + audioSegmentTimingInfoFn: this.handleSegmentTimingInfo_.bind(this, 'audio', segmentInfo.requestId), captionsFn: this.handleCaptions_.bind(this), id3Fn: this.handleId3_.bind(this), @@ -2264,12 +2270,24 @@ export default class SegmentLoader extends videojs.EventTarget { gopsToAlignWith: segmentInfo.gopsToAlignWith }; - const previousSegment = segmentInfo.playlist.segments[segmentInfo.mediaIndex]; - - if (previousSegment && - previousSegment.end && - previousSegment.timeline === segment.timeline) { - simpleSegment.baseStartTime = previousSegment.end + segmentInfo.timestampOffset; + const previousSegment = segmentInfo.playlist.segments[segmentInfo.mediaIndex - 1]; + + if (previousSegment && previousSegment.timeline === segment.timeline) { + // The baseStartTime of a segment is used to handle rollover when probing the TS + // segment to retrieve timing information. Since the probe only looks at the media's + // times (e.g., PTS and DTS values of the segment), and doesn't consider the + // player's time (e.g., player.currentTime()), baseStartTime should reflect the + // media time as well. transmuxedDecodeEnd represents the end time of a segment, in + // seconds of media time, so should be used here. The previous segment is used since + // the end of the previous segment should represent the beginning of the current + // segment, so long as they are on the same timeline. + if (previousSegment.videoTimingInfo) { + simpleSegment.baseStartTime = + previousSegment.videoTimingInfo.transmuxedDecodeEnd; + } else if (previousSegment.audioTimingInfo) { + simpleSegment.baseStartTime = + previousSegment.audioTimingInfo.transmuxedDecodeEnd; + } } if (segment.key) { diff --git a/src/segment-transmuxer.js b/src/segment-transmuxer.js index 5bfc04260..aa3b606f2 100644 --- a/src/segment-transmuxer.js +++ b/src/segment-transmuxer.js @@ -78,6 +78,7 @@ export const processTransmux = ({ onAudioTimingInfo, onVideoTimingInfo, onVideoSegmentTimingInfo, + onAudioSegmentTimingInfo, onId3, onCaptions, onDone @@ -111,6 +112,9 @@ export const processTransmux = ({ if (event.data.action === 'videoSegmentTimingInfo') { onVideoSegmentTimingInfo(event.data.videoSegmentTimingInfo); } + if (event.data.action === 'audioSegmentTimingInfo') { + onAudioSegmentTimingInfo(event.data.audioSegmentTimingInfo); + } if (event.data.action === 'id3Frame') { onId3([event.data.id3Frame], event.data.id3Frame.dispatchType); } diff --git a/src/transmuxer-worker.js b/src/transmuxer-worker.js index b191057d5..ca9120a6d 100644 --- a/src/transmuxer-worker.js +++ b/src/transmuxer-worker.js @@ -94,6 +94,30 @@ const wireFullTransmuxerEvents = function(self, transmuxer) { }); }); + transmuxer.on('audioSegmentTimingInfo', function(timingInfo) { + // Note that all times for [audio/video]SegmentTimingInfo events are in video clock + const audioSegmentTimingInfo = { + start: { + decode: videoTsToSeconds(timingInfo.start.dts), + presentation: videoTsToSeconds(timingInfo.start.pts) + }, + end: { + decode: videoTsToSeconds(timingInfo.end.dts), + presentation: videoTsToSeconds(timingInfo.end.pts) + }, + baseMediaDecodeTime: videoTsToSeconds(timingInfo.baseMediaDecodeTime) + }; + + if (timingInfo.prependedContentDuration) { + audioSegmentTimingInfo.prependedContentDuration = + videoTsToSeconds(timingInfo.prependedContentDuration); + } + self.postMessage({ + action: 'audioSegmentTimingInfo', + audioSegmentTimingInfo + }); + }); + transmuxer.on('id3Frame', function(id3Frame) { self.postMessage({ action: 'id3Frame', diff --git a/src/util/segment.js b/src/util/segment.js index 03b92e735..4248e2333 100644 --- a/src/util/segment.js +++ b/src/util/segment.js @@ -7,6 +7,10 @@ import { ONE_SECOND_IN_TS } from 'mux.js/lib/utils/clock'; * * @private * @param {Uint8Array} bytes - segment bytes + * @param {number} baseStartTime + * Relative reference timestamp used when adjusting frame timestamps for rollover. + * This value should be in seconds, as it's converted to a 90khz clock within the + * function body. * @return {Object} The start time of the current segment in "media time" as well as * whether it contains video and/or audio */ diff --git a/test/media-segment-request.test.js b/test/media-segment-request.test.js index e4cdcd151..c7193fd00 100644 --- a/test/media-segment-request.test.js +++ b/test/media-segment-request.test.js @@ -115,7 +115,8 @@ QUnit.module('Media Segment Request - make it to transmuxer', { 'id3', 'captions', 'data', - 'videoSegmentTimingInfo' + 'videoSegmentTimingInfo', + 'audioSegmentTimingInfo' ].forEach((name) => { this.calls[name] = 0; this.options[`${name}Fn`] = () => this.calls[name]++; @@ -141,7 +142,8 @@ QUnit.test('ac3 without id3 segments will not make it to the transmuxer', functi timingInfo: 0, captions: 0, id3: 0, - videoSegmentTimingInfo: 0 + videoSegmentTimingInfo: 0, + audioSegmentTimingInfo: 0 }, 'calls as expected'); done(); }; @@ -165,7 +167,8 @@ QUnit.test('ac3 with id3 segments will not make it to the transmuxer', function( timingInfo: 0, captions: 0, id3: 0, - videoSegmentTimingInfo: 0 + videoSegmentTimingInfo: 0, + audioSegmentTimingInfo: 0 }, 'calls as expected'); done(); }; @@ -189,7 +192,8 @@ QUnit.test('muxed ts segments will make it to the transmuxer', function(assert) timingInfo: 4, captions: 0, id3: 0, - videoSegmentTimingInfo: 1 + videoSegmentTimingInfo: 1, + audioSegmentTimingInfo: 1 }, 'calls as expected'); done(); }; @@ -213,7 +217,8 @@ QUnit.test('video ts segments will make it to the transmuxer', function(assert) timingInfo: 2, captions: 0, id3: 0, - videoSegmentTimingInfo: 1 + videoSegmentTimingInfo: 1, + audioSegmentTimingInfo: 0 }, 'calls as expected'); done(); }; @@ -237,7 +242,8 @@ QUnit.test('audio ts segments will make it to the transmuxer', function(assert) timingInfo: 2, captions: 0, id3: 0, - videoSegmentTimingInfo: 0 + videoSegmentTimingInfo: 0, + audioSegmentTimingInfo: 1 }, 'calls as expected'); done(); }; @@ -261,7 +267,8 @@ QUnit.test('aac with id3 will make it to the transmuxer', function(assert) { timingInfo: 2, captions: 0, id3: 0, - videoSegmentTimingInfo: 0 + videoSegmentTimingInfo: 0, + audioSegmentTimingInfo: 0 }, 'calls as expected'); done(); }; @@ -285,7 +292,8 @@ QUnit.test('aac without id3 will make it to the transmuxer', function(assert) { timingInfo: 2, captions: 0, id3: 0, - videoSegmentTimingInfo: 0 + videoSegmentTimingInfo: 0, + audioSegmentTimingInfo: 0 }, 'calls as expected'); done(); }; @@ -309,7 +317,8 @@ QUnit.test('ac3 without id3 segments will not make it to the partial transmuxer' timingInfo: 0, captions: 0, id3: 0, - videoSegmentTimingInfo: 0 + videoSegmentTimingInfo: 0, + audioSegmentTimingInfo: 0 }, 'calls as expected'); done(); }; @@ -333,7 +342,8 @@ QUnit.test('ac3 with id3 segments will not make it to the partial transmuxer', f timingInfo: 0, captions: 0, id3: 0, - videoSegmentTimingInfo: 0 + videoSegmentTimingInfo: 0, + audioSegmentTimingInfo: 0 }, 'calls as expected'); done(); }; @@ -357,7 +367,8 @@ QUnit.test('muxed ts segments will make it to the partial transmuxer', function( timingInfo: 4, captions: 0, id3: 0, - videoSegmentTimingInfo: 0 + videoSegmentTimingInfo: 0, + audioSegmentTimingInfo: 0 }, 'calls as expected'); done(); }; @@ -381,7 +392,8 @@ QUnit.test('video ts segments will make it to the partial transmuxer', function( timingInfo: 2, captions: 0, id3: 0, - videoSegmentTimingInfo: 0 + videoSegmentTimingInfo: 0, + audioSegmentTimingInfo: 0 }, 'calls as expected'); done(); }; @@ -405,7 +417,8 @@ QUnit.test('audio ts segments will make it to the partial transmuxer', function( timingInfo: 2, captions: 0, id3: 0, - videoSegmentTimingInfo: 0 + videoSegmentTimingInfo: 0, + audioSegmentTimingInfo: 0 }, 'calls as expected'); done(); }; @@ -429,7 +442,8 @@ QUnit.test('aac with id3 will make it to the partial transmuxer', function(asser timingInfo: 2, captions: 0, id3: 0, - videoSegmentTimingInfo: 0 + videoSegmentTimingInfo: 0, + audioSegmentTimingInfo: 0 }, 'calls as expected'); done(); }; @@ -453,7 +467,8 @@ QUnit.test('aac without id3 will make it to the partial transmuxer', function(as timingInfo: 2, captions: 0, id3: 0, - videoSegmentTimingInfo: 0 + videoSegmentTimingInfo: 0, + audioSegmentTimingInfo: 0 }, 'calls as expected'); done(); }; diff --git a/test/segment-loader.test.js b/test/segment-loader.test.js index b30a6fd81..c09cf1e94 100644 --- a/test/segment-loader.test.js +++ b/test/segment-loader.test.js @@ -28,6 +28,14 @@ import { oneSecond as oneSecondSegment, audio as audioSegment, video as videoSegment, + videoLargeOffset as videoLargeOffsetSegment, + videoLargeOffset2 as videoLargeOffset2Segment, + videoMaxOffset as videoMaxOffsetSegment, + videoMinOffset as videoMinOffsetSegment, + audioLargeOffset as audioLargeOffsetSegment, + audioLargeOffset2 as audioLargeOffset2Segment, + audioMaxOffset as audioMaxOffsetSegment, + audioMinOffset as audioMinOffsetSegment, mp4Video as mp4VideoSegment, mp4VideoInit as mp4VideoInitSegment, mp4Audio as mp4AudioSegment, @@ -3603,6 +3611,262 @@ QUnit.module('SegmentLoader', function(hooks) { assert.equal(loader.throughput.rate, 1000, 'did not save throughput'); assert.equal(loader.throughput.count, 1, 'did not save throughput'); }); + + QUnit.test('sets correct video start time for large DTS value', function(assert) { + const playlist = playlistWithDuration(40); + const { + mediaSource_: mediaSource, + sourceUpdater_: sourceUpdater + } = loader; + const mediaSettings = { isVideoOnly: true }; + + return setupMediaSource(mediaSource, sourceUpdater, mediaSettings).then(() => { + loader.playlist(playlist); + loader.load(); + + this.clock.tick(1); + standardXHRResponse(this.requests.shift(), videoLargeOffsetSegment()); + + return new Promise((resolve, reject) => { + loader.one('appended', resolve); + loader.one('error', reject); + }); + }).then(() => { + this.clock.tick(1); + + const segment = playlist.segments[0]; + + assert.equal(segment.start, 0, 'set start to 0'); + assert.equal( + segment.videoTimingInfo.transmuxedDecodeEnd, + // the segment's DTS (2^32 + 1) + segment's duration (6006 clock cycles), + // divided by 90khz clock to get seconds + (Math.pow(2, 32) + 1 + 6006) / 90000, + 'set proper transmuxed decode end' + ); + + standardXHRResponse(this.requests.shift(), videoLargeOffset2Segment()); + + return new Promise((resolve, reject) => { + loader.one('appended', resolve); + loader.one('error', reject); + }); + }).then(() => { + const segment = playlist.segments[1]; + + assert.equal( + segment.start.toFixed(6), + // since this is the second segment, it should start at the first segment's + // duration (6006 clock cycles divided by 90khz clock to get seconds) + (6006 / 90000).toFixed(6), + 'set correct start' + ); + assert.equal( + segment.videoTimingInfo.transmuxedDecodeEnd, + // the segment's DTS (2^32 + 1 + 6006) + this segment's duration of 6006, + // divided by 90khz clock to get seconds + (Math.pow(2, 32) + 1 + (6006 * 2)) / 90000, + 'set proper transmuxed decode end' + ); + }); + }); + + QUnit.test('sets correct video start time with rollover', function(assert) { + const playlist = playlistWithDuration(40); + const { + mediaSource_: mediaSource, + sourceUpdater_: sourceUpdater + } = loader; + const mediaSettings = { isVideoOnly: true }; + + return setupMediaSource(mediaSource, sourceUpdater, mediaSettings).then(() => { + loader.playlist(playlist); + loader.load(); + + this.clock.tick(1); + standardXHRResponse(this.requests.shift(), videoMaxOffsetSegment()); + + return new Promise((resolve, reject) => { + loader.one('appended', resolve); + loader.one('error', reject); + }); + }).then(() => { + this.clock.tick(1); + + const segment = playlist.segments[0]; + + assert.equal(segment.start, 0, 'set start to 0'); + assert.equal( + segment.videoTimingInfo.transmuxedDecodeEnd, + // Segment's ending DTS (max DTS) divided by 90khz clock to get seconds. + // + // Note that this segment is meant to end exactly at the max DTS of 2^33. The + // starting DTS should be 2^33 - 6006 (the segment's duration). + Math.pow(2, 33) / 90000, + 'set proper transmuxed decode end' + ); + + standardXHRResponse(this.requests.shift(), videoMinOffsetSegment()); + + return new Promise((resolve, reject) => { + loader.one('appended', resolve); + loader.one('error', reject); + }); + }).then(() => { + const segment = playlist.segments[1]; + + assert.equal( + segment.start.toFixed(6), + // since this is the second segment, it should start at the first segment's + // duration (6006 clock cycles divided by 90khz clock to get seconds) + (6006 / 90000).toFixed(6), + 'set correct start' + ); + assert.equal( + segment.videoTimingInfo.transmuxedDecodeEnd, + // previous segment's ending DTS (max DTS) + duration of this segment (6006), + // divided by 90khz clock to get seconds + // + // This is verifying that we handled rollover. If we didn't handle rollover, then + // the DTS of this segment would be 0 + 6006, the segment's DTS + duration. These + // are the values you'd see when probing the segment alone, without a reference + // to a prior segment. But our rollover handling adds the max value of 2^33 to + // the timestamp values, since it detected from the prior segment that we reached + // the max value for a timestamp of 2^33, and since JavaScript can handle values + // larger than 2^33 in value, it does the addition from the player side. + (Math.pow(2, 33) + (6006)) / 90000, + 'set proper transmuxed decode end greater than rollover value' + ); + }); + }); + + QUnit.test('sets correct audio start time for large DTS value', function(assert) { + const playlist = playlistWithDuration(40); + const { + mediaSource_: mediaSource, + sourceUpdater_: sourceUpdater + } = loader; + const mediaSettings = { isAudioOnly: true }; + + return setupMediaSource(mediaSource, sourceUpdater, mediaSettings).then(() => { + loader.playlist(playlist); + loader.load(); + + this.clock.tick(1); + standardXHRResponse(this.requests.shift(), audioLargeOffsetSegment()); + + return new Promise((resolve, reject) => { + loader.one('appended', resolve); + loader.one('error', reject); + }); + }).then(() => { + this.clock.tick(1); + + const segment = playlist.segments[0]; + + assert.equal(segment.start, 0, 'set start to 0'); + assert.equal( + segment.audioTimingInfo.transmuxedDecodeEnd.toFixed(4), + // the segment's DTS (2^32 + 1) + segment's duration (11520 clock cycles), + // divided by 90khz clock to get seconds + ((Math.pow(2, 32) + 1 + 11520) / 90000).toFixed(4), + 'set proper transmuxed decode end' + ); + + standardXHRResponse(this.requests.shift(), audioLargeOffset2Segment()); + + return new Promise((resolve, reject) => { + loader.one('appended', resolve); + loader.one('error', reject); + }); + }).then(() => { + const segment = playlist.segments[1]; + + assert.equal( + segment.start.toFixed(6), + // since this is the second segment, it should start at the first segment's + // duration (11520 clock cycles divided by 90khz clock to get seconds) + (11520 / 90000).toFixed(6), + 'set correct start' + ); + assert.equal( + segment.audioTimingInfo.transmuxedDecodeEnd.toFixed(4), + // the segment's DTS (2^32 + 1 + 11520) + this segment's duration of 11520, + // divided by 90khz clock to get seconds + ((Math.pow(2, 32) + 1 + (11520 * 2)) / 90000).toFixed(4), + 'set proper transmuxed decode end' + ); + }); + }); + + QUnit.test('sets correct audio start time with rollover', function(assert) { + const playlist = playlistWithDuration(40); + const { + mediaSource_: mediaSource, + sourceUpdater_: sourceUpdater + } = loader; + const mediaSettings = { isAudioOnly: true }; + + return setupMediaSource(mediaSource, sourceUpdater, mediaSettings).then(() => { + loader.playlist(playlist); + loader.load(); + + this.clock.tick(1); + standardXHRResponse(this.requests.shift(), audioMaxOffsetSegment()); + + return new Promise((resolve, reject) => { + loader.one('appended', resolve); + loader.one('error', reject); + }); + }).then(() => { + this.clock.tick(1); + + const segment = playlist.segments[0]; + + assert.equal(segment.start, 0, 'set start to 0'); + assert.equal( + segment.audioTimingInfo.transmuxedDecodeEnd.toFixed(5), + // Segment's ending DTS (max DTS) divided by 90khz clock to get seconds. + // + // Note that this segment is meant to end exactly at the max DTS of 2^33. The + // starting DTS should be 2^33 - 11520 (the segment's duration). + (Math.pow(2, 33) / 90000).toFixed(5), + 'set proper transmuxed decode end' + ); + + standardXHRResponse(this.requests.shift(), audioMinOffsetSegment()); + + return new Promise((resolve, reject) => { + loader.one('appended', resolve); + loader.one('error', reject); + }); + }).then(() => { + const segment = playlist.segments[1]; + + assert.equal( + segment.start.toFixed(6), + // since this is the second segment, it should start at the first segment's + // duration (11520 clock cycles divided by 90khz clock to get seconds) + (11520 / 90000).toFixed(6), + 'set correct start' + ); + assert.equal( + segment.audioTimingInfo.transmuxedDecodeEnd.toFixed(5), + // previous segment's ending DTS (max DTS) + duration of this segment (11520), + // divided by 90khz clock to get seconds + // + // This is verifying that we handled rollover. If we didn't handle rollover, then + // the DTS of this segment would be 0 + 6006, the segment's DTS + duration. These + // are the values you'd see when probing the segment alone, without a reference + // to a prior segment. But our rollover handling adds the max value of 2^33 to + // the timestamp values, since it detected from the prior segment that we reached + // the max value for a timestamp of 2^33, and since JavaScript can handle values + // larger than 2^33 in value, it does the addition from the player side. + ((Math.pow(2, 33) + (11520)) / 90000).toFixed(5), + 'set proper transmuxed decode end greater than rollover value' + ); + }); + }); }); }); diff --git a/test/segment-transmuxer.test.js b/test/segment-transmuxer.test.js index 3901cd374..cb30298e8 100644 --- a/test/segment-transmuxer.test.js +++ b/test/segment-transmuxer.test.js @@ -68,6 +68,7 @@ QUnit.test('transmux returns data for full appends', function(assert) { const audioTimingFn = sinon.spy(); const videoTimingFn = sinon.spy(); const videoSegmentTimingInfoFn = sinon.spy(); + const audioSegmentTimingInfoFn = sinon.spy(); this.transmuxer = createTransmuxer(false); @@ -82,6 +83,7 @@ QUnit.test('transmux returns data for full appends', function(assert) { onAudioTimingInfo: audioTimingFn, onVideoTimingInfo: videoTimingFn, onVideoSegmentTimingInfo: videoSegmentTimingInfoFn, + onAudioSegmentTimingInfo: audioSegmentTimingInfoFn, onId3: noop, onCaptions: noop, onDone: () => { @@ -90,6 +92,7 @@ QUnit.test('transmux returns data for full appends', function(assert) { assert.ok(audioTimingFn.callCount, 'got audioTimingInfo events'); assert.ok(videoTimingFn.callCount, 'got videoTimingInfo events'); assert.ok(videoSegmentTimingInfoFn.callCount, 'got videoSegmentTimingInfo events'); + assert.ok(audioSegmentTimingInfoFn.callCount, 'got audioSegmentTimingInfo events'); done(); } }); @@ -130,6 +133,7 @@ QUnit.test('transmux returns data for partial appends', function(assert) { const audioTimingFn = sinon.spy(); const videoTimingFn = sinon.spy(); const videoSegmentTimingInfoFn = sinon.spy(); + const audioSegmentTimingInfoFn = sinon.spy(); this.transmuxer = createTransmuxer(true); @@ -141,8 +145,10 @@ QUnit.test('transmux returns data for partial appends', function(assert) { isPartial: true, onData: () => { dataFn(); - // TODO: parial appends don't current fire this + // TODO: partial appends don't currently fire this + // assert.ok(videoSegmentTimingInfoFn.callCount, 'got videoSegmentTimingInfoFn event'); + // assert.ok(audioSegmentTimingInfoFn.callCount, 'got audioSegmentTimingInfoFn event'); assert.ok(trackInfoFn.callCount, 'got trackInfo event'); assert.ok(videoTimingFn.callCount, 'got videoTimingInfo event'); @@ -155,6 +161,7 @@ QUnit.test('transmux returns data for partial appends', function(assert) { onAudioTimingInfo: audioTimingFn, onVideoTimingInfo: videoTimingFn, onVideoSegmentTimingInfo: videoSegmentTimingInfoFn, + onAudioSegmentTimingInfo: audioSegmentTimingInfoFn, onId3: noop, onCaptions: noop, // This will be called on partialdone events, diff --git a/test/segments/audioLargeOffset.ts b/test/segments/audioLargeOffset.ts new file mode 100644 index 0000000000000000000000000000000000000000..8945477c1941805767be01880bce2bfe98935fb5 GIT binary patch literal 2068 zcmZ>F5ENi=`k>0dc#whNKjVJ}#y<@r9zu+4Zf>~+sp*`-sYPX($*Bg0~;pm4-8rxSvCzWC*pLCdjQbwOdEv2Zhy$|fq@@HY@2=HCQdDbM#9~Z z!Js>!fq{YHAH!g96axd}0S2{(23Ac5Mh52pAAK5_@Bg{S#Nd-ymTYRSXKtuxXkftL zq`+}d!UE`a!#O~=GancnZpR2euxCUep5X_3hH?KNMFEzC9vPt9jX-W^Zx{k@m&0(o zG05%Q4nx50x)^RZ0lA%jkfe9KX~qW4?G6lrL%56-9KvO!DJabd4TW;X8#T=U0AW=5 A*Z=?k literal 0 HcmV?d00001 diff --git a/test/segments/audioLargeOffset2.ts b/test/segments/audioLargeOffset2.ts new file mode 100644 index 0000000000000000000000000000000000000000..dd5ec23bed67ab17ed5f45924555efec4f5f0f15 GIT binary patch literal 2068 zcmZ>F5ENi=`k>0dc#whNKjVJ}#y<@r9zu+4Zf>~+sp*`-sYPX($*Bg0~;pm4-8rxSvCzWC*pLCdjQbwOdEv2Zhy$|fq@@HY@2=HCQdDbM#9~Z z!Js>!fkCX{AH!g96axd}0S2{(23Ac5#wh0hAAK5_@Bg{S#Nd-ymTYRSXKtuxXkftL zq`+}d!UE`a!#O~=OF0YS75l^ z802=v14F>=?HF!10l8gukfe9KX=WOl+Z`ALhj1AwIE2ecQ&5`G917*kQq(j901(Lh AdjJ3c literal 0 HcmV?d00001 diff --git a/test/segments/audioMaxOffset.ts b/test/segments/audioMaxOffset.ts new file mode 100644 index 0000000000000000000000000000000000000000..0045004eaac5765e9ebbc9da2ade84060d0d6e0e GIT binary patch literal 2068 zcmZ>F5ENi=`k>0dc#whNKjVJ}#y<@r9zu+4Zf>~+sp*`-sYPX($*Bg0~;pm4-8rxSvCzWC*pLCdjQbwOdEv2Zhy$|fq@@HY@2=HCQdDbM#9~Z z!Js?f|NoZ_bqs^SQ49=>2N={E8d&xJ|6j)V|D#U>^Zh^fm>7H#%aTpa^~??R3=Iqz zoD?_?N>~8hZa4?%_O}j$!|fR12lk98#4}sLo?+boM^S(!p+^Sjb|aA6KQasfw;#c9 zyD`Y^Uk(fbw_nC^y9vncKL$y9$D3vzp}F0GL2w9{k%B|Gj5GzMnLk6JocV~FW&m)p B6+Qp} literal 0 HcmV?d00001 diff --git a/test/segments/audioMinOffset.ts b/test/segments/audioMinOffset.ts new file mode 100644 index 0000000000000000000000000000000000000000..454b3b7a19c2f89fac2f5dd36609a679d78e4a39 GIT binary patch literal 2068 zcmZ>F5ENi=`k>0dc#whNKjVJ}#y<@r9zu+4Zf>~+sp*`-sYPX($*Bg0~;pm4-8rxSvCzWC*pLCdjQbwOdEv2Zhy$|fq@@HY@2=HCQdDbM#9~Z z!Js>U0SM|C27{v*7#I&Qs5LaODl#xKF#iAO)4+WH&pjpvpTx3cQ*%9YLp?(S0|qAr zj)M{wK(`yt0lJ;}z~FE@M)-j}BMR{hKiD&j`~N5kuq5=z0Nri`ayxs&5OBL3hTDxn yZs&Fw0&dsEaJvb}?fiozz2i+YHfU~lU=SR_Wu)K`E+b7rX+~%$lr!F_X$AlfvGbe& literal 0 HcmV?d00001 diff --git a/test/segments/videoLargeOffset.ts b/test/segments/videoLargeOffset.ts new file mode 100644 index 0000000000000000000000000000000000000000..4048edfa33fd0ac4da78152c985dbf5fa2f290bd GIT binary patch literal 4512 zcmdUycT^ME8o(!n5)cH!q96zZ3St2g2t_2)q$mVIMFoWr!h}RfAqfzq1x2Med zrUu|DF#!+{0YHk70*G1ucV1|OqK5~a1w|-th1jt)GK9g#CAvM4{<$tsXFvl0%GJKH z0|*JQ>W2KyKNsR3(s=s8>~iJkZ|q_~0_e$v_5;H9KTP@4I6PedjFKN80DyV;j}QR> zpRceIKmbVDP+20A5v~G*E}+QGzZB{HUwgE_8{BJ7J~&z7;?B>xHatXvVa3D34ZRL<~Y!0 zyBi!C4v}Gp8G!CrU^X$XPTo{2IO^0PTL<--_WI%W;EX)53H@5=0R5qN&!P|mSOlBmB3J-|C*{~od3VxygX~2LC_P2S+G&+eZ zW1%s)5Ic$l2f_BRs2DaWo=9fWS)^}NaGSVn5{&_ufCJeiSqz0uqC*^5i-TwpR4xnF zBB6NLjkmJ-RfXBL7+fNq#(+&AhYT?wats%b!^mc1lVsgtLmVoc$R-p2K`ryM$#^oG z0@B0a7Rl(~0p7~m0s}_NnD7`2TUceu3V*wkczD~juz|ycSa=*rW5NA~*A`w5xE3iI zUP{@*0DSoQgVNI$dEL-gCezBpdCYyY~hyPURPELzM-k)n)H z&fl@oC(l29_cq^dX&ha{lJ8;cT5VdltZFzE8|SbqNl%=+Rr%7GN>KH|mXWo0Qg?lt z&1iQ~Z}`Hj_wK6&uyB&u;YW6ZhFZ354zZgE&R(9&7l6bZX8=?ZtL=Tm8`m`@H2SR=5CYG|aNl*I-3v_? zh7|R`O0@l2&@Vrlis~kR^0pv<~|)SGhAes%DSGjZ5dTzcc2jRc7ryhv@(d%5Xc zU2}OD614@TrMEC>1G3JhGr=o0YgZUKr`ozxf59(@=Qk@BcGmXy3FMp-5!)9mZ8E9n z>t?ra%)jPibn~KWF``*5>DK-$$AA?}4yrZr9g}neceEZtt@-|CjS?!3hdQ;qfiLJn zIB5Es1#C0btasnFE`S=Ow)52|-HkyTou**+CGoXDdVp@3K$V`MFdiIwHi@zE=)M$Y zy}bLIL$wKg=d<(&-`qIseyPO&^19f0?F-DeuQ8biuvsEivhu>W!Tg@##Ju6|$8#*7 zg!fZjbqD95K@_NzWMPLK?{9~Ut`5~P z|I@+BQ?n+^nHy)Y6NTajZTqE@~^VluY@0t)CnFQkNpgtI4)>Ifg zOcZO^=Asin^#^ICd)D78Gg;0B03Dmln>uXMy|UJg4OQof%dM&ZbwY zeY%v4?@E;G#pvw*@`20`=_LoQ=bxRqU!!LptlZeOHteAP!H+%m@9|D%pC3d|+ACQe z@#jwR1I*}&QiB3u%j<^lJsB-(2+L5Fws6Eg6HmSqb_Lqvm6&PRWN4lZWX|{yuEXpG z{g$n|CZ!>ZQ^7YCR|#E@Hau!v;|uH=y!aw;|HsT%x{c2efvR8Dq@s^|`)7&t&H4_T z?rQ%&a!@mE+AZY$=mL?#=u@8;1P>c|56WC7Ut?2ygT45Wk6XjK)aX zx15+U8ta*?ywvegqG-uOq#|nWSsFglEZQVg3xU}UX^Kr1T84yAB)EoIo1I9(rBS3?=DzMxWQjyJ0>x31so#CNX2*6Q+bM60uAL; zk|iv8t<|Uk>C{HMr&=g|BUj}L+E!-Hz}*86+BWF%yju&E0v?W}Jbu}XAOIhkWrD!` z-OjTIw(N7-=1!};HQ8d2et3yk*NE6vIbjn&gr&T=la-M2R?8}@)q3Sa&j%w?9^c2& z=GA<>;`L)%pI8;%CX%#m9CQ3A%#Kz%(jm#%KQ(sLr>|`7qOw^5Q9R|V4qZ&?wCnDv z)A5@s=xCX&RodVce(t*4s#BwYskWsrI@|5huDzd?YoX7BHvu1Hp#l16&FQq=PqYIP ze2Rud8fV|`J~KC7w)Mk!3G>G8`OuAnAyl2RRM7TL46}YgQ|#2X&$Ii777rL;lcSGS zOZ%md{T?oq(_-38%rkH3tRE2a^+VFT4dk4zT-$OFBldYcFK_Oumi3cucbDz<{43Ma zJeXZeDeR1+!3*LjB%R`Uz3g>6g%?dfz&#(-@!PWPEN)7npyT87vy`laL^+XpZ{qpx zgAu!=9UnFXj5W`^c-r|P@r{eWN z9iY<|iVF6xOxRpKJb}F2znULu9;!4;*a8`5SIOmyg924M=J#NYjTbwHmFzx|qHS(! zs((7kPpGEwgQiV$cShgsT(P<@E^+%puT0Lqa!JI(WeeR*xTB8;O%Sn5wDUJXU#L5hS4f}x`N}iPwEkKN`(cF1)#pKx-tCm bjB6F9mM{Y2Yah>QIIr?l4gO^wkQHT=?LUa+_&%TKl{#k=asWNXU?7Pe(nCwcW1tH$J1F; z18^0a0EmYGAVEj~#4K;27Yd=^;Xz|U5lUMjRxFhSp)qlZZcinDuFKOI&;WpPweRcz zLJX|BA$Rl7h4_awo_;X9OgZX1y9f{ideTAr0e<@*hWu#^o-P1d(T@kHRL=tdfDi%z zk0-wpKv;}Or%Gb!7~#q{=mLr@r_#ke5hkZ`_9- z^mlpP&0X^f>{|ADgllDs1O6E#uml~NgNn~6itK2aEKVbmqCYcRv4HawFX|5Ok{HiOm-xd z3A_J2Ni>tdAd}e;2WM^tawse~ijA`cqZo`xA_blhe$!z8$VTkf<~w zN6JE_b0Ag}5q5(0VNo$GVmyJwpfQQxso*kkSVSrvP60czh*BRii%5gmuoMSTBPbju zEJZ@`uo-7%^Q#E6YtcCb8kG*KKsE`YL!=lE4vUtq#v)3q!-CipIFLmm{DWF*XOVCu z78#_4!6lN?!4sU7wFMfCmNMbc7Phd+lqUZEByw@KYheYO12J(}kjjMX4eu?y9dIsU zG`yA4jRAP@`v;|`seBFN0asfJ|K$a4|c;DqR{=4yr!bGP3qg>aNeT z8SO6W4PP1c-hH(I=8mgjU`$<&-54ober{V+#j2SDY0d(da=F}ctl-|cT5*NxoRjVO z)`rC+yvT0QP|LQ>A$Akq*~@de3P{Lt20%rT+TOR^aa~h``OON2owfaad>N-i#CDaXO(yj` z-R$;_`PY1mZeCO^Ml`D>-P(WU7_ef=LA55HW0G#*j@CoSH9x$nQAEaZk*Ah7@c3N_ z2TfnIfNiFl_3pdY1yF+2cE0|syD?~^(-h3UB)%3%56~^+tI{&$$Ad%9Ceb$@-Iv0s zmveu6s5YVRe3t&;+Z$)yFO~RTUKcyBeSz`r4Lb7xCQGPFQd;mXnAbC$m^a-0c#i3l z@L{Tp6mYkpCU3=uZFxY->XV0e_R8Ko)-RbLuNKN#-N8C&5ctX^S(qWm``aO-t3~3R zIrf+9n%{u;5jRhEp4i*M4xa3nw2NJ)p0>Z>ikoUBS_i!Oi@q3KjCS93)I-vD*|kQt zgp=Fx{uTpf*SjQ9KW!QjkxX;XZ=Oe`$E@#()h!sm`mtom{o?HNOLKc>l;R!Rp6w{s ze{!($)U3&J#>N@UM4{-x+hv=}0G(GA6h~+6q}fMxi4QLrsf&yy0C>+Z{e*An$f(ij zinWKPHkqN0mke|7?#Pw{Fv6Dug^1GQ)%6xVX`6puJHP7jtJ=bD_)MXcaxC{3|6T*vP4)}`?CYVs|)aA`}Ca>8W-CuH>#!CW%Zet|J3_YryC zP&{3%?V1{xINSWylH8lkG=SNcdOQ^H@Md;)Kg;~&pY`Er+y&Zr*3eK&*6~H#nhJx5 z2_o&mNutUy`37BLK)49&BF%o!j2b(r0t z-?CNLq%>r4D)_eID!%K{hDVKSe1ScK7heYM|CIS!xA8e5Q1$DYRMc^A|16=tS>IvP zUF|_bWgP$rH=YPHz$$6T8wFWPih`eOAdjLMa!Qk}!5ncIsw+fGyV=`-T zEhlD-#(E|zFLitpD_C+7sfe0;mWGcsi#7?=LSS}7szOtRmLdK#5zb-OW+#+)sTHd3 z)1UR@OB7@u>6lxE0s+{^*xvHxzHChT9<1(Iw?MBkp|#nmGV4n0oa4vV`63~&SW7jR zUNzgF)>gCue@xy@k$l4*I@46O?|w%3d=QiSWa#v|B$1Vg3|6!|U`-)j4Bp-^;F-Pi zdFlwb*d}8hDco9_LDQ^BxSYG}*orFHLD+Gk8|=E(hz_|}dr5m0S$W61m!tuqlR3VQP+32) ze8`4cSg_gKek5bDSx^|wZrPny!NhPZ0G|rg59l>E%s7)GnId|qt6dEC;!<_f+(j*W zn&xK>`tv=ldw#ky)?4;4rq=eRq};^h)KuZM>nql8zji#YJ%@F7B3+Hq)GrTI|Rn)vsHS>hF6-M-{Hvzgm|gR1-^Z#@-Ocss z(~||$C(rEZ6eN6juee5|(^0RxRYN4=x$~FeZ}67bj)@Ii0fz{Ztit>1sXT=&zJ}5% z@e-z-)@o#dWNM?`GcBaPk*iV#bt@xh;O>D3Z5#Bs-mQg-0S`w~9=~cv;DJw!GJatG zZs*wpTlP6^bEj6`nrtyhKfFYwYeeX(oUn->!jNCy$x29hr)8DZYQ6HI=YtUmm*?YX z^LjpB;rcPH&&&#M6LH!$wmEJTW=AO==@4h^pBg*r(^s~3QQ0h?Ae!=3hc2dc+I9ET z>G(|*bhJ#?DsJ!!KX=`2)u~ayRNK-QmF@Ou*WNEmwa}Nrn}CmOp#kb>&FQq=PqhOQ ze2RvI8fV|_J~KC7w)Nw93FF4@`OuAnArzgmRM7TL45MD9DRyexm)ZS8iw6ua$GU(Jg&4^^DSZ-ET6t7LLTL4m3r^LsGH#)}=pN_L+}(Ka_V z)jyr&Cs33BQPZZmJEQM*E=&9PG^4*g$BYhV^z@Pb^I^^Zt+QAS->pno6}vXrqq2PI z^rFqJR`HdxE^+%puT0LqcC#Lr&nyh`e0}IzNG(s}g%xOnIja247`>d(UP@7^t8h!+ zy2{1=Wb+&E=u-zD>}_p4@a_%kh*!yqv*sC2!zkrFUBU6%C-n$9rGkRTd{Ez4-57uo aTLq~l^uYMq$FmyFt2|YMf0;+*^Zo|UCs{TC literal 0 HcmV?d00001 diff --git a/test/segments/videoMaxOffset.ts b/test/segments/videoMaxOffset.ts new file mode 100644 index 0000000000000000000000000000000000000000..f6503982130bacf1aea45819c67d58a1ca3a7381 GIT binary patch literal 4512 zcmdUyc{o&iAHdI8hX^A@#GyzFW*AE{*|HQPDiy^TJk;QCbZ=ej(c0CfN;SN+Zo zAjH7x8*(@QT!?>2DS%G0tXe5Iafy3CN?a?5SPK=CWLpU@S zo^vr63`m1;6o?D5qeEfI7G$#Ha2V-GV1?l@=4dzw9zYtE3xyG+8Kn^f7Lgtf;V?EJ ziNa#ghy*wk19DhUWF(ahOLknlFcJqwAVtyOF$^Mx?PJg(oFxWkN3DfdB@@{k0+Ss< zWy0=%PZGr>Fvw&!#KDaZX-1rB792>+m#+F2wV ziA4r!p>T<$bnpacX=RQEqohnYw7Cr|GNp;XKZ#tN%{o}Y=0Hpw7Nj!adc%7QZwH)< z7zJ;obYlP>{Qg1dsSCb_@_?%?h5zz`*%$rha3;Dl=&y9c>{|bAVz2*21^lePW4iwi z7G_`kSE}{z(4%2?TPNT@Y}vn0`2UlG;r^}-e;&f$`ubp&v}^y`*PTz>EfFqZCrglq zNT)?C)XDSD-oMMYT^37Ix8S)Oxm26fEw365!Nl6{PSh3UZd1B6rW{y(uw`W3os`|5 zXEWNJ)f&Ds>b?4E0n8m2gMjF|8rv~aw*1`ori#@wX{k;E=W@B+a;)Iqxmt0B$(*Cj z`PPOdBfN-i&_L6s%|2!`-pSKr#R8C!;{<`j=Vtk9v_W+N}wiaUu+xh)Qpqvlh!D2QN|@bYE>g zSJzw~DvR8T)YM%VxKXywx-;H0C2MymDW}@1Q*Xg9hv&B_6n573_wi*M6A(KVENe2Z z=jmj(Z_2;sZFuvdN-?5YHSyMgE60G9OAo3x@f;F$0(Q0@LazPcRgEGtmWw>KqJhWn zLfC8gnEG!w(WrOZz22V^sJiR*XPr%fn;fTL_N8&PK)Sz98DE8#AwM1zayF5^>FEAs zM!lTd+e5YSedn|E2H)N|>vpNc@ACSXd94eKcW=;{X_zdb3Q1|4C5@3Kpc zYzZf~JlDaFjNy6NdWMkLHY@w(veZa z(-rFuO>H(s9WNQ?-rbok2VjIR2MQ6T$E)kjds4Ujyl#H=<5#tX-SC-0Dfw9LFMhoW z-n^2zChg3x6Dt~gwp3C0Y>IZ0p798d?%m2R@)b?T1SP77yp}r#>ql1cnBp9?%#jTfyPA7c60xQ2 z26si~S0APZCl$37Scs>5JU7gZeXUF8=hfs}aN*LHBISh31&+w-CxW>oq}@UzPVOV} zyn%SSSj#0PAYr!os|C3?o2d`8FLQq=;NeYeZGV>e$uH}}(bx;L@vNbtK3A z4HHCKwYjK-Rg`Rs&W{4+>AFj9GY*{!xA}#de85TB*13iK{&~QGSdS^WekZzRypze5 zYVR&Zqq}0IdJ!tSzkDF`V|q#2_58Cl_iJ>`f|MG&)`cGQJNT)`?gP%z^vi>&NjpW0 zBYvDop1&zAL84y(Y<<%Zwl||i6=4yg+!lt|Z|uQy#H>V_zZNkJnheacfy^0i{B@XJ zzu%%&$G9|jNecM3;wrxD(Z)xOYkh#dgBM>09Qc&^TBq?jB0%Nq+7#4rFTX6Io@w7< zlilq`@^)=lf1DpmK=w42j(UX- zo5)6qc2PB*+?*|^I|e^hGS2^eFM{(l|7s0hED?FiYV`noeuMt$_ai#;ajq5atHxy3 z;aX127>@N!R$l7(Bv!ECB2o}F_bdz^X%uZ1s0PFA22_Qn3QYt2XCj=#w9Qs1?_4WX z*{?V2%a2DKeerBBmS7Yt0MV^9dxFtYXAL=u=zkH_sP)d^@$=&V;QVykN?_2ycoQFK)^G7 z=l#?HaJEUpJW{x|Dubp`6Ms3KrPXU!?0r-H5^i7xuYSCBa^;=Ix7lLZoo-gU5PG{x zH~x6LWPCv%%&xv`*(j%YBVrq>U?*YciEgm#RwFw2V(lfZ)nw(J?_QDygpOwTIznar zz=|PjYGJ_^FT0V9C8mL)G~4BOS_KosF#vojR7=xsY?yH(MKDG55Et8M?8RkjCb^4S z_BPGW>i6e+SoQpLWvsXCVRWs{O-Z@2@u{i8Yu8t9*m3Q6UV9Gf?xy_(cLyVqWC$~+ zlRU%Xb8RL$9ktkzLn>dlBGumajE*W?(K+wB*K!{6X7wHXuZy8!m#Bw2;`)l+#2S$uV+ zQ{tseIn6c50?E`S+h>|cJwq3z3hFjS&cNNY2W=a5xn8Y>ivABrk{`cnM&N-@j52;e z{vM~a=~Q3OZUQYZW(ohMl|ay86^8V4`K=gUWV&w0qwdrCR9A;7!0=woo5+wB~f`o~K&= z@!my4LiMxn_MDj;FWdHUyo7OM&wR+H!C;DZSqf-#Cz?^epebf*`H{$tHEFQ0XOOn9qlC)b(DUyn+DVdSkK89Y>E+sezTAajqHIS4{8hkf?T zL-}jBg&>3cD&x0Q4^PNm?q9=;Fbh$f#czcSva4irMS%e-9rJrJMn+2vd*#lL#|BDzIL@5m(MH=^mu*fT5v5-{e>lHjXA3P%?Q1M&|XSeP*>ra zv~9Js-O1)RUQwqGKG@gVnD*`s>xgH`%Clw}j>9PBy!}+Q+l%POCjsf_|At$)YTRiV6xLgc}keBqRZXY(Y`kTo@HW zP!QW~R6ub7QHaXY$kx&-f=Uul7Ey_^Bal~dUccA>%$zgly_wTf_onVw-&Vi#Rc@WS z9!?tSkc-$DLOq5c2}%N?=6FAOVo(b1?sO&+p|l-g#nH$J78jr7`b_fYY93CIIs{dy z{$PhtVrb1Rx!Zp(#J@}9;Ro1dDlk9TMUWWMm3CT>e0KibkUx#V!x_RV`az(jfFDW- zK|G$kA%p@K7%GXSeS`~NzZ)vCm|7-?|My z8tC@CpSSKc+`Zzk51YYc1`C04csrP7X@kYVBrG}HHrxsrJk5cFg^!<`hZ!Dr z-suWF!x1ttxH6atQ3!N9Gua6QoU|vh!U;HYEC>P}Os8>?aH2G$G=j(?MMoe6oDEE- zvKVv{5rpDk4hxBjqOpNw$F&P5a{vN4h7S60gcQD?5seTmaey7O4$Mj+u{lI0JCeo( z?*E-6hDl^lC~Sm7Ftda?R2GP06Kvop1|yP01q0&mIvmW70x$IcDzI=g>&HA~8lA+E zve2SA2rG&NoPa(oDwah`Ad(q$Cg}$iC=-W8qD6xgz>!6g`cPOTI>H80JVJ}0a+pAh zL=u3RU}^m~5wL4UbBJ_WG*H28G7^oDV>tvoRyrGtB&`k$VN*dMi%k3vd7B&7obf~A!?7LJiJ5wPYqKx9f2|9FzP1e^6h!R8=L0v@I@LA}A+g5?0YNHJh3 zr3(Y`!2b`)NMH0Vj0atBE&7KIu>bVC!@1b5;Qyo>uxtH)6MOwDD&TMZ1JnHvuz-EZ ze^RagfF29jZJnV1Wv5EehG?gs zSeVlnpMQ8?V7ok?u5Q6|H*%>lsb5h&5{iqr-;=B>%G<7VWn4L^=5Xui`g>`6zRYEI zIIA^&V>Ed6*Fm^@E(U?I^|iL+w>jd7Cm&C+Nk?_%Z2)u ziZEI9HngVh;-F2k_10a9o@v>8!pONbR$Y3FemlCbRiUV>ZlIqp=vIs6nc`-+a;89JJYS8n7=*sDm;BbjtZE^i27Q;L!8Q(VLGSNM$t0 zxxG75m)L(XTW{#yt@CbIO8u{Hh+ELQ#CZP}n{^16EmR>ZEq))&>m5nTAL)5I&-70G zINePSxZhZtzv|7%>*WN)7skW5n63gs;C;qBFleC5(?+_1yLorvM}VsY*~ z`|C}O@6d;c+o!uu?QdlVPYp;q#Lm;tI$m`pG$CnJ%L`D(_eqfMs%C~HE%Qz)gL$otK|Pr;j4 zI^V3F^=)!xqwm&gDxXc&PSG z!Nvy6xl0}2lVk&o`c{C0j21NPo@L;^hwA_GGv}K}`$+a5q zZbhT}Vx7kni=Vu?*>Y4>BHFd8KJM4e>bFbY;f}`ozM=?`&iWbNG zIa9m9O9Cg6hgXf4_g)x64Vi+_VnB_oOv)(>80lWTy zMVpRsS;*2f_+907pYA7{o;0oVh4u|yeieA|bJiQ3rWdF{m2d0PFeknIvxR!5{YOpq zbo?c9NF#m5HRR*iBBA`)bMIF^?$&bdl=&>4`j(DHJJAtu*TxMe`C&wKZ&TTrSJ;S& zY>a3(P1DKE*>a|H=yMh0;;#=PInN5N*ZPPhB2QVZUWm_c)Ia-SR7XC+wbFg{xXgM& z>#148@!qMbE1jRk3Km>c8mjhzg~1bz;w=Kz5WsFgQ)sT#H1PRC0y#|EZH4mAbwZT` zdUJk!iGu7CZ8OVIC;C&#VpYT7 z%3*6-QQ=lEyV1<0ra@tJ+ZFfP1d}6i5I7a89nx)ToOL2cGDXp$F1E4w%gfbF@|Lvj zYhIYsA1Ls!>iz4r@xJoMv2`}LB^AcTXQqp8++4MB=Z%y39l5Ogn-3J;ABs$oAK8o9FvaD!&*c0(On_{hz8sb+$HS z%uE%|oIba&OOW{SgW@{%E(hJ7Hg%DR=f+>|bBnjkW?ZcA0@+89WfeZuOy?_P^VOBk zh?g~)$uwC#Z74mVoWovBv+jHAm$I)=pVs!8jFVI1Yvz3jx)_nMa3ZC0xvdpsJIaCzPi z)^8RP6mFi-{KBmCG8U)rV4D%f06RwUSf@Di;Pm)$@BZ@jOUmc?MA5Xb8ge8CR!H0m>kz9d-i`-szbgG-G;nni}W$aYtN?deWn$V z=v_Q4R6qZI@45Mj^6j4{N*TBIE`)9#3ZZJ3r@=P&Vi^sKn&YN-e4RTuymU|>mlAWL zMlv9I>i2lDj3&c+a)EJ6d*h&hrx%jZqc7ul?Z&nTSdsVJ1vxVp)$Ctvdb(|P7F?T= za2>)_O+i%;B^Z04`!p_ex&r`A!lVpTueMuL4 z4oB>fbbi_tFy1oz>Ur0vq<5Nja$Q;c4VcuIM&1gNp(Dk%ZM^JC3ip_qgCOi`_!s|t zOn`QKC_31`DsgMg$fWGmfwjCyvrxr3pKXXiPPI&)C@4^+b73FO$Y`lUSn1wVsaj?x zCVFR+{RFD=KWkXG^knwm&0}euoM8-fxYe9&e7^2&v<#zqEv{amSUv8(~)xJIbhw>MLDS zwy$xvJKgfuE9T7MNBi5F4!wWNI_6or>bzN|;|NB1Uw3eV)@fa0ZkeF)DIeDJRWkyg c&iFP#T4{7(Lfz9jb*D8RD#5=kpbB{Z1*gbXCjbBd literal 0 HcmV?d00001 diff --git a/test/transmuxer-worker.test.js b/test/transmuxer-worker.test.js index 443d54694..69a054cca 100644 --- a/test/transmuxer-worker.test.js +++ b/test/transmuxer-worker.test.js @@ -93,6 +93,7 @@ QUnit.test('flush should return data from transmuxer', function(assert) { 'videoSegmentTimingInfo', 'videoTimingInfo', 'data', + 'audioSegmentTimingInfo', 'audioTimingInfo', 'data', 'done', @@ -128,6 +129,10 @@ QUnit.test('flush should return data from transmuxer', function(assert) { 'video', 'returns video data with the 1st data event' ); + assert.ok( + messages.shift().audioSegmentTimingInfo, + 'returns timing information with audioSegmentTimingInfo event' + ); assert.ok( messages.shift().audioTimingInfo, 'returns timing information with audioTimingInfo event' diff --git a/test/videojs-http-streaming.test.js b/test/videojs-http-streaming.test.js index 9fd2eb9d2..079d73b15 100644 --- a/test/videojs-http-streaming.test.js +++ b/test/videojs-http-streaming.test.js @@ -5120,7 +5120,7 @@ QUnit.test('convertToProgramTime will return stream time if buffered', function( mainSegmentLoader_.one('appending', () => { // since we don't run through the transmuxer, we have to manually trigger the timing // info callback - mainSegmentLoader_.handleVideoSegmentTimingInfo_(mainSegmentLoader_.pendingSegment_.requestId, { + mainSegmentLoader_.handleSegmentTimingInfo_('video', mainSegmentLoader_.pendingSegment_.requestId, { prependedGopDuration: 0, start: { presentation: 0 From ee39672c64647eaa39844709ea4106c814ab17da Mon Sep 17 00:00:00 2001 From: Garrett Singer Date: Thu, 7 Jan 2021 14:28:36 -0500 Subject: [PATCH 056/399] 2.4.2 --- CHANGELOG.md | 7 +++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b1fc2c164..f35bd7e87 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ + +## [2.4.2](https://github.com/videojs/http-streaming/compare/v2.4.1...v2.4.2) (2021-01-07) + +### Bug Fixes + +* handle rollover and don't set wrong timing info for segments with high PTS/DTS values ([#1040](https://github.com/videojs/http-streaming/issues/1040)) ([9919b85](https://github.com/videojs/http-streaming/commit/9919b85)) + ## [2.4.1](https://github.com/videojs/http-streaming/compare/v2.4.0...v2.4.1) (2020-12-22) diff --git a/package-lock.json b/package-lock.json index f842a7426..e773b1b35 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@videojs/http-streaming", - "version": "2.4.1", + "version": "2.4.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index a3f3e4516..989ae4c7b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@videojs/http-streaming", - "version": "2.4.1", + "version": "2.4.2", "description": "Play back HLS and DASH with Video.js, even where it's not natively supported", "main": "dist/videojs-http-streaming.cjs.js", "module": "dist/videojs-http-streaming.es.js", From 83057a8ea7ad481bfcd6305ce4549249a9e6544f Mon Sep 17 00:00:00 2001 From: Brandon Casey <2381475+brandonocasey@users.noreply.github.com> Date: Wed, 13 Jan 2021 09:57:27 -0500 Subject: [PATCH 057/399] test: clear segment transmuxer in media segment request tests (#1043) --- test/media-segment-request.test.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/media-segment-request.test.js b/test/media-segment-request.test.js index c7193fd00..3f3afd21e 100644 --- a/test/media-segment-request.test.js +++ b/test/media-segment-request.test.js @@ -10,6 +10,7 @@ import { } from './test-helpers'; import TransmuxWorker from 'worker!../src/transmuxer-worker.worker.js'; import Decrypter from 'worker!../src/decrypter-worker.worker.js'; +import {dispose as segmentTransmuxerDispose} from '../src/segment-transmuxer.js'; import { aacWithoutId3 as aacWithoutId3Segment, aacWithId3 as aacWithId3Segment, @@ -91,6 +92,9 @@ const sharedHooks = { if (this.transmuxer) { this.transmuxer.terminate(); } + + // clear current transmux on segment transmuxer + segmentTransmuxerDispose(); } }; @@ -1209,7 +1213,6 @@ QUnit.test('callbacks fire for TS segment with partial data', function(assert) { this.standardXHRResponse(request, muxedSegment()); }); -// TODO: tests after this one appear to fail QUnit.test('data callback does not fire if too little partial data', function(assert) { const progressSpy = sinon.spy(); const dataSpy = sinon.spy(); From b072c934392c86699086ebf6f3fff6b0d0f3e70c Mon Sep 17 00:00:00 2001 From: Brandon Casey <2381475+brandonocasey@users.noreply.github.com> Date: Thu, 14 Jan 2021 14:00:55 -0500 Subject: [PATCH 058/399] chore: update @videojs/vhs-utils to v3.0.0 (#1036) --- package-lock.json | 1977 ++++++++++------------- package.json | 15 +- scripts/rollup.config.js | 8 + scripts/sources.json | 2 +- src/dash-playlist-loader.js | 2 +- src/master-playlist-controller.js | 80 +- src/media-segment-request.js | 2 +- src/resolve-url.js | 2 +- src/source-updater.js | 2 +- src/util/codecs.js | 68 +- src/util/container-request.js | 5 +- src/videojs-http-streaming.js | 4 +- test/master-playlist-controller.test.js | 16 +- test/test-helpers.js | 4 +- test/videojs-http-streaming.test.js | 12 +- 15 files changed, 985 insertions(+), 1214 deletions(-) diff --git a/package-lock.json b/package-lock.json index e773b1b35..2228c433e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,9 +5,9 @@ "requires": true, "dependencies": { "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", "dev": true, "requires": { "@babel/highlight": "^7.10.4" @@ -20,33 +20,32 @@ "dev": true }, "@babel/core": { - "version": "7.12.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.9.tgz", - "integrity": "sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ==", + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.10.tgz", + "integrity": "sha512-eTAlQKq65zHfkHZV0sIVODCPGVgoo1HdBlbSLi9CqOzuZanMv2ihzY+4paiKr1mH+XmYESMAmJ/dpZ68eN6d8w==", "dev": true, "requires": { "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.12.5", + "@babel/generator": "^7.12.10", "@babel/helper-module-transforms": "^7.12.1", "@babel/helpers": "^7.12.5", - "@babel/parser": "^7.12.7", + "@babel/parser": "^7.12.10", "@babel/template": "^7.12.7", - "@babel/traverse": "^7.12.9", - "@babel/types": "^7.12.7", + "@babel/traverse": "^7.12.10", + "@babel/types": "^7.12.10", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.1", "json5": "^2.1.2", "lodash": "^4.17.19", - "resolve": "^1.3.2", "semver": "^5.4.1", "source-map": "^0.5.0" }, "dependencies": { "@babel/parser": { - "version": "7.12.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.7.tgz", - "integrity": "sha512-oWR02Ubp4xTLCAqPRiNIuMVgNO5Aif/xpXtabhzW2HWUD47XJsAB4Zd/Rg30+XeQA3juXigV7hlquOTmwqLiwg==", + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.11.tgz", + "integrity": "sha512-N3UxG+uuF4CMYoNj8AhnbAcJF0PiuJ9KHuy1lQmkYsxTer/MAH9UBNHsBoAX/4s6NvlDD047No8mYVGGzLL4hg==", "dev": true }, "debug": { @@ -79,12 +78,12 @@ } }, "@babel/generator": { - "version": "7.12.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.5.tgz", - "integrity": "sha512-m16TQQJ8hPt7E+OS/XVQg/7U184MLXtvuGbCdA7na61vha+ImkyyNM/9DDA0unYCVZn3ZOhng+qz48/KBOT96A==", + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.11.tgz", + "integrity": "sha512-Ggg6WPOJtSi8yYQvLVjG8F/TlpWDlKx0OpS4Kt+xMQPs5OaGYWy+v1A+1TvxI6sAMGZpKWWoAQ1DaeQbImlItA==", "dev": true, "requires": { - "@babel/types": "^7.12.5", + "@babel/types": "^7.12.11", "jsesc": "^2.5.1", "source-map": "^0.5.0" }, @@ -98,12 +97,12 @@ } }, "@babel/helper-annotate-as-pure": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz", - "integrity": "sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA==", + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.10.tgz", + "integrity": "sha512-XplmVbC1n+KY6jL8/fgLVXXUauDIB+lD5+GsQEh6F6GBF1dq1qy4DP4yXWzDKcoqXB3X58t61e85Fitoww4JVQ==", "dev": true, "requires": { - "@babel/types": "^7.10.4" + "@babel/types": "^7.12.10" } }, "@babel/helper-builder-binary-assignment-operator-visitor": { @@ -180,23 +179,23 @@ } }, "@babel/helper-function-name": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", - "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.11.tgz", + "integrity": "sha512-AtQKjtYNolKNi6nNNVLQ27CP6D9oFR6bq/HPYSizlzbp7uC1M59XJe8L+0uXjbIaZaUJF99ruHqVGiKXU/7ybA==", "dev": true, "requires": { - "@babel/helper-get-function-arity": "^7.10.4", - "@babel/template": "^7.10.4", - "@babel/types": "^7.10.4" + "@babel/helper-get-function-arity": "^7.12.10", + "@babel/template": "^7.12.7", + "@babel/types": "^7.12.11" } }, "@babel/helper-get-function-arity": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", - "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.10.tgz", + "integrity": "sha512-mm0n5BPjR06wh9mPQaDdXWDoll/j5UpCAPl1x8fS71GHm7HA6Ua2V4ylG1Ju8lvcTOietbPNNPaSilKj+pj+Ag==", "dev": true, "requires": { - "@babel/types": "^7.10.4" + "@babel/types": "^7.12.10" } }, "@babel/helper-hoist-variables": { @@ -244,12 +243,12 @@ } }, "@babel/helper-optimise-call-expression": { - "version": "7.12.7", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.7.tgz", - "integrity": "sha512-I5xc9oSJ2h59OwyUqjv95HRyzxj53DAubUERgQMrpcCEYQyToeHA+NEcUEsVWB4j53RDeskeBJ0SgRAYHDBckw==", + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.10.tgz", + "integrity": "sha512-4tpbU0SrSTjjt65UMWSrUOPZTsgvPgGG4S8QSTNHacKzpS51IVWGDj0yCwyeZND/i+LSN2g/O63jEXEWm49sYQ==", "dev": true, "requires": { - "@babel/types": "^7.12.7" + "@babel/types": "^7.12.10" } }, "@babel/helper-plugin-utils": { @@ -270,15 +269,15 @@ } }, "@babel/helper-replace-supers": { - "version": "7.12.5", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.12.5.tgz", - "integrity": "sha512-5YILoed0ZyIpF4gKcpZitEnXEJ9UoDRki1Ey6xz46rxOzfNMAhVIJMoune1hmPVxh40LRv1+oafz7UsWX+vyWA==", + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.12.11.tgz", + "integrity": "sha512-q+w1cqmhL7R0FNzth/PLLp2N+scXEK/L2AHbXUyydxp828F4FEa5WcVoqui9vFRiHDQErj9Zof8azP32uGVTRA==", "dev": true, "requires": { - "@babel/helper-member-expression-to-functions": "^7.12.1", - "@babel/helper-optimise-call-expression": "^7.10.4", - "@babel/traverse": "^7.12.5", - "@babel/types": "^7.12.5" + "@babel/helper-member-expression-to-functions": "^7.12.7", + "@babel/helper-optimise-call-expression": "^7.12.10", + "@babel/traverse": "^7.12.10", + "@babel/types": "^7.12.11" } }, "@babel/helper-simple-access": { @@ -300,24 +299,24 @@ } }, "@babel/helper-split-export-declaration": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", - "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.11.tgz", + "integrity": "sha512-LsIVN8j48gHgwzfocYUSkO/hjYAOJqlpJEc7tGXcIm4cubjVUf8LGW6eWRyxEu7gA25q02p0rQUWoCI33HNS5g==", "dev": true, "requires": { - "@babel/types": "^7.11.0" + "@babel/types": "^7.12.11" } }, "@babel/helper-validator-identifier": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", - "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", "dev": true }, "@babel/helper-validator-option": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.1.tgz", - "integrity": "sha512-YpJabsXlJVWP0USHjnC/AQDTLlZERbON577YUVO/wLpqyj6HAtVYnWaQaN0iUN+1/tWn3c+uKKXjRut5115Y2A==", + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.11.tgz", + "integrity": "sha512-TBFCyj939mFSdeX7U7DDj32WtzYY7fDcalgq8v3fBZMNOJQNn7nOYzMaUCiPxPYfCup69mtIpqlKgMZLvQ8Xhw==", "dev": true }, "@babel/helper-wrap-function": { @@ -355,15 +354,15 @@ } }, "@babel/parser": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.2.3.tgz", - "integrity": "sha512-0LyEcVlfCoFmci8mXx8A5oIkpkOgyo8dRHtxBnK9RRBwxO2+JZPNsqtVEZQ7mJFPxnXF9lfmU24mHOPI0qnlkA==", + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.11.tgz", + "integrity": "sha512-N3UxG+uuF4CMYoNj8AhnbAcJF0PiuJ9KHuy1lQmkYsxTer/MAH9UBNHsBoAX/4s6NvlDD047No8mYVGGzLL4hg==", "dev": true }, "@babel/plugin-proposal-async-generator-functions": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.1.tgz", - "integrity": "sha512-d+/o30tJxFxrA1lhzJqiUcEJdI6jKlNregCv5bASeGf2Q4MXmnwH7viDo7nhx1/ohf09oaH8j1GVYG/e3Yqk6A==", + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.12.tgz", + "integrity": "sha512-nrz9y0a4xmUrRq51bYkWJIO5SBZyG2ys2qinHsN0zHDHVsUaModrkpyWWWXfGqYQmOL3x9sQIcTNN/pBGpo09A==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.10.4", @@ -631,9 +630,9 @@ } }, "@babel/plugin-transform-block-scoping": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.1.tgz", - "integrity": "sha512-zJyAC9sZdE60r1nVQHblcfCj29Dh2Y0DOvlMkcqSo0ckqjiCwNiUezUKw+RjOCwGfpLRwnAeQ2XlLpsnGkvv9w==", + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.12.tgz", + "integrity": "sha512-VOEPQ/ExOVqbukuP7BYJtI5ZxxsmegTwzZ04j1aF0dkSypGo9XpDHuOrABsJu+ie+penpSJheDJ11x1BEZNiyQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.10.4" @@ -859,14 +858,13 @@ } }, "@babel/plugin-transform-runtime": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.12.1.tgz", - "integrity": "sha512-Ac/H6G9FEIkS2tXsZjL4RAdS3L3WHxci0usAnz7laPWUmFiGtj7tIASChqKZMHTSQTQY6xDbOq+V1/vIq3QrWg==", + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.12.10.tgz", + "integrity": "sha512-xOrUfzPxw7+WDm9igMgQCbO3cJKymX7dFdsgRr1eu9n3KjjyU4pptIXbXPseQDquw+W+RuJEJMHKHNsPNNm3CA==", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.12.1", + "@babel/helper-module-imports": "^7.12.5", "@babel/helper-plugin-utils": "^7.10.4", - "resolve": "^1.8.1", "semver": "^5.5.1" }, "dependencies": { @@ -916,9 +914,9 @@ } }, "@babel/plugin-transform-typeof-symbol": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.12.1.tgz", - "integrity": "sha512-EPGgpGy+O5Kg5pJFNDKuxt9RdmTgj5sgrus2XVeMp/ZIbOESadgILUbm50SNpghOh3/6yrbsH+NB5+WJTmsA7Q==", + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.12.10.tgz", + "integrity": "sha512-JQ6H8Rnsogh//ijxspCjc21YPd3VLVoYtAwv3zQmqAt8YGYUtdo5usNhdl4b9/Vir2kPFZl6n1h0PfUz4hJhaA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.10.4" @@ -944,16 +942,16 @@ } }, "@babel/preset-env": { - "version": "7.12.7", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.12.7.tgz", - "integrity": "sha512-OnNdfAr1FUQg7ksb7bmbKoby4qFOHw6DKWWUNB9KqnnCldxhxJlP+21dpyaWFmf2h0rTbOkXJtAGevY3XW1eew==", + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.12.11.tgz", + "integrity": "sha512-j8Tb+KKIXKYlDBQyIOy4BLxzv1NUOwlHfZ74rvW+Z0Gp4/cI2IMDPBWAgWceGcE7aep9oL/0K9mlzlMGxA8yNw==", "dev": true, "requires": { "@babel/compat-data": "^7.12.7", "@babel/helper-compilation-targets": "^7.12.5", "@babel/helper-module-imports": "^7.12.5", "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-validator-option": "^7.12.1", + "@babel/helper-validator-option": "^7.12.11", "@babel/plugin-proposal-async-generator-functions": "^7.12.1", "@babel/plugin-proposal-class-properties": "^7.12.1", "@babel/plugin-proposal-dynamic-import": "^7.12.1", @@ -982,7 +980,7 @@ "@babel/plugin-transform-arrow-functions": "^7.12.1", "@babel/plugin-transform-async-to-generator": "^7.12.1", "@babel/plugin-transform-block-scoped-functions": "^7.12.1", - "@babel/plugin-transform-block-scoping": "^7.12.1", + "@babel/plugin-transform-block-scoping": "^7.12.11", "@babel/plugin-transform-classes": "^7.12.1", "@babel/plugin-transform-computed-properties": "^7.12.1", "@babel/plugin-transform-destructuring": "^7.12.1", @@ -1008,12 +1006,12 @@ "@babel/plugin-transform-spread": "^7.12.1", "@babel/plugin-transform-sticky-regex": "^7.12.7", "@babel/plugin-transform-template-literals": "^7.12.1", - "@babel/plugin-transform-typeof-symbol": "^7.12.1", + "@babel/plugin-transform-typeof-symbol": "^7.12.10", "@babel/plugin-transform-unicode-escapes": "^7.12.1", "@babel/plugin-transform-unicode-regex": "^7.12.1", "@babel/preset-modules": "^0.1.3", - "@babel/types": "^7.12.7", - "core-js-compat": "^3.7.0", + "@babel/types": "^7.12.11", + "core-js-compat": "^3.8.0", "semver": "^5.5.0" }, "dependencies": { @@ -1058,34 +1056,34 @@ }, "dependencies": { "@babel/parser": { - "version": "7.12.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.7.tgz", - "integrity": "sha512-oWR02Ubp4xTLCAqPRiNIuMVgNO5Aif/xpXtabhzW2HWUD47XJsAB4Zd/Rg30+XeQA3juXigV7hlquOTmwqLiwg==", + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.11.tgz", + "integrity": "sha512-N3UxG+uuF4CMYoNj8AhnbAcJF0PiuJ9KHuy1lQmkYsxTer/MAH9UBNHsBoAX/4s6NvlDD047No8mYVGGzLL4hg==", "dev": true } } }, "@babel/traverse": { - "version": "7.12.9", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.9.tgz", - "integrity": "sha512-iX9ajqnLdoU1s1nHt36JDI9KG4k+vmI8WgjK5d+aDTwQbL2fUnzedNedssA645Ede3PM2ma1n8Q4h2ohwXgMXw==", + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.12.tgz", + "integrity": "sha512-s88i0X0lPy45RrLM8b9mz8RPH5FqO9G9p7ti59cToE44xFm1Q+Pjh5Gq4SXBbtb88X7Uy7pexeqRIQDDMNkL0w==", "dev": true, "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.12.5", - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.11.0", - "@babel/parser": "^7.12.7", - "@babel/types": "^7.12.7", + "@babel/code-frame": "^7.12.11", + "@babel/generator": "^7.12.11", + "@babel/helper-function-name": "^7.12.11", + "@babel/helper-split-export-declaration": "^7.12.11", + "@babel/parser": "^7.12.11", + "@babel/types": "^7.12.12", "debug": "^4.1.0", "globals": "^11.1.0", "lodash": "^4.17.19" }, "dependencies": { "@babel/parser": { - "version": "7.12.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.7.tgz", - "integrity": "sha512-oWR02Ubp4xTLCAqPRiNIuMVgNO5Aif/xpXtabhzW2HWUD47XJsAB4Zd/Rg30+XeQA3juXigV7hlquOTmwqLiwg==", + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.11.tgz", + "integrity": "sha512-N3UxG+uuF4CMYoNj8AhnbAcJF0PiuJ9KHuy1lQmkYsxTer/MAH9UBNHsBoAX/4s6NvlDD047No8mYVGGzLL4hg==", "dev": true }, "debug": { @@ -1106,12 +1104,12 @@ } }, "@babel/types": { - "version": "7.12.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.7.tgz", - "integrity": "sha512-MNyI92qZq6jrQkXvtIiykvl4WtoRrVV9MPn+ZfsoEENjiWcBQ3ZSHrkxnJWgWtLX3XXqX5hrSQ+X69wkmesXuQ==", + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz", + "integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.10.4", + "@babel/helper-validator-identifier": "^7.12.11", "lodash": "^4.17.19", "to-fast-properties": "^2.0.0" } @@ -1180,6 +1178,16 @@ "resolve": "^1.17.0" } }, + "@rollup/plugin-replace": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.3.4.tgz", + "integrity": "sha512-waBhMzyAtjCL1GwZes2jaE9MjuQ/DQF2BatH3fRivUF3z0JBFrU0U6iBNC/4WR+2rLKhaAhPWDNPYp4mI6RqdQ==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^3.1.0", + "magic-string": "^0.25.7" + } + }, "@rollup/plugin-virtual": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@rollup/plugin-virtual/-/plugin-virtual-2.0.3.tgz", @@ -1234,9 +1242,9 @@ "dev": true }, "@textlint/ast-node-types": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/@textlint/ast-node-types/-/ast-node-types-4.3.4.tgz", - "integrity": "sha512-Grq+vJuNH7HCa278eFeiqJvowrD+onMCoG2ctLyoN+fXYIQGIr1/8fo8AcIg+VM16Kga+N6Y1UWNOWPd8j1nFg==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@textlint/ast-node-types/-/ast-node-types-4.3.5.tgz", + "integrity": "sha512-syl8VE34DQDTV7+IADP1jYtGsxTC9MmCKLmpJX90G6nNv9CzgAZIukd7WMiJFZpFgcDAlibEaCKlJRxjfEmmPA==", "dev": true }, "@textlint/markdown-to-ast": { @@ -1267,9 +1275,9 @@ "dev": true }, "@types/node": { - "version": "14.14.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.11.tgz", - "integrity": "sha512-BJ97wAUuU3NUiUCp44xzUFquQEvnk1wu7q4CMEUYKJWjdkr0YWYDsm4RFtAvxYsNjLsKcrFt6RvK8r+mnzMbEQ==", + "version": "14.14.20", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.20.tgz", + "integrity": "sha512-Y93R97Ouif9JEOWPIUyU+eyIdyRqQR0I8Ez1dzku4hDx34NWh4HbtIc3WNzwB1Y9ULvNGeu5B8h8bVL5cAk4/A==", "dev": true }, "@types/normalize-package-data": { @@ -1326,9 +1334,9 @@ } }, "@videojs/http-streaming": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@videojs/http-streaming/-/http-streaming-2.3.0.tgz", - "integrity": "sha512-nMEnku3BSGIrB4dpo4LWCbDH9NqnGhY1cop0bn9Kwy63VJKG5B3d2mnS4N0OibNpY6I+mJKTqJLSRW9KYBs2TA==", + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/@videojs/http-streaming/-/http-streaming-2.2.4.tgz", + "integrity": "sha512-gzT46RpAEegOhMId/zZ6uXCVGDMPOv8qmoTykBuvd6/4lVM3lZ1ZJCq0kytAkisDuDKipy93gP46oZEtonlc/Q==", "requires": { "@babel/runtime": "^7.5.5", "@videojs/vhs-utils": "^2.2.1", @@ -1340,6 +1348,37 @@ "video.js": "^6 || ^7" }, "dependencies": { + "@videojs/vhs-utils": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@videojs/vhs-utils/-/vhs-utils-2.3.0.tgz", + "integrity": "sha512-ThSmm91S7tuIJ757ON50K4y7S/bvKN4+B0tu303gCOxaG57PoP1UvPfMQZ90XGhxwNgngexVojOqbBHhTvXVHQ==", + "requires": { + "@babel/runtime": "^7.5.5", + "global": "^4.3.2", + "url-toolkit": "^2.1.6" + } + }, + "aes-decrypter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aes-decrypter/-/aes-decrypter-3.1.0.tgz", + "integrity": "sha512-wL1NFwP2yNrJG4InpXYFhhYe9TfonnDyhyxMq2+K9/qt+SrZzUieOpviN6pkDly7GawTqw5feehk0rn5iYo00g==", + "requires": { + "@babel/runtime": "^7.5.5", + "@videojs/vhs-utils": "^2.2.1", + "global": "^4.3.2", + "pkcs7": "^1.0.4" + } + }, + "m3u8-parser": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/m3u8-parser/-/m3u8-parser-4.5.0.tgz", + "integrity": "sha512-RGm/1WVCX3o1bSWbJGmJUu4zTbtJy8lImtgHM4CESFvJRXYztr1j6SW/q9/ghYOrUjgH7radsIar+z1Leln0sA==", + "requires": { + "@babel/runtime": "^7.5.5", + "@videojs/vhs-utils": "^2.2.1", + "global": "^4.3.2" + } + }, "mpd-parser": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/mpd-parser/-/mpd-parser-0.14.0.tgz", @@ -1359,13 +1398,13 @@ } }, "@videojs/vhs-utils": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@videojs/vhs-utils/-/vhs-utils-2.3.0.tgz", - "integrity": "sha512-ThSmm91S7tuIJ757ON50K4y7S/bvKN4+B0tu303gCOxaG57PoP1UvPfMQZ90XGhxwNgngexVojOqbBHhTvXVHQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@videojs/vhs-utils/-/vhs-utils-3.0.0.tgz", + "integrity": "sha512-HPgiaVB8/g7DooYFQ20uTinq4eNRHmIXGHHttK/Xwyvn19MfIpg9BfMNr9ywCvgHh0IUGrxt6P8AcmMO4xvxIA==", "requires": { - "@babel/runtime": "^7.5.5", - "global": "^4.3.2", - "url-toolkit": "^2.1.6" + "@babel/runtime": "^7.12.5", + "global": "^4.4.0", + "url-toolkit": "^2.2.1" } }, "@videojs/xhr": { @@ -1429,13 +1468,13 @@ "dev": true }, "aes-decrypter": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aes-decrypter/-/aes-decrypter-3.1.0.tgz", - "integrity": "sha512-wL1NFwP2yNrJG4InpXYFhhYe9TfonnDyhyxMq2+K9/qt+SrZzUieOpviN6pkDly7GawTqw5feehk0rn5iYo00g==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/aes-decrypter/-/aes-decrypter-3.1.2.tgz", + "integrity": "sha512-42nRwfQuPRj9R1zqZBdoxnaAmnIFyDi0MNyTVhjdFOd8fifXKKRfwIHIZ6AMn1or4x5WONzjwRTbTWcsIQ0O4A==", "requires": { - "@babel/runtime": "^7.5.5", - "@videojs/vhs-utils": "^2.2.1", - "global": "^4.3.2", + "@babel/runtime": "^7.12.5", + "@videojs/vhs-utils": "^3.0.0", + "global": "^4.4.0", "pkcs7": "^1.0.4" } }, @@ -1505,15 +1544,26 @@ "dev": true }, "ansi-escapes": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", - "dev": true + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", + "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", + "dev": true, + "requires": { + "type-fest": "^0.11.0" + }, + "dependencies": { + "type-fest": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", + "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", + "dev": true + } + } }, "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", "dev": true }, "ansi-styles": { @@ -1611,9 +1661,9 @@ "dev": true }, "astral-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", - "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", "dev": true }, "async": { @@ -1622,12 +1672,6 @@ "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", "dev": true }, - "async-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", - "dev": true - }, "babel-code-frame": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", @@ -1639,6 +1683,12 @@ "js-tokens": "^3.0.2" }, "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, "ansi-styles": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", @@ -1664,6 +1714,15 @@ "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", "dev": true }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", @@ -1838,15 +1897,6 @@ "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", "dev": true }, - "better-assert": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", - "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", - "dev": true, - "requires": { - "callsite": "1.0.0" - } - }, "big-integer": { "version": "1.6.48", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz", @@ -1864,9 +1914,9 @@ } }, "binary-extensions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", - "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true }, "blob": { @@ -1925,16 +1975,16 @@ } }, "browserslist": { - "version": "4.15.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.15.0.tgz", - "integrity": "sha512-IJ1iysdMkGmjjYeRlDU8PQejVwxvVO5QOfXH7ylW31GO6LwNRSmm/SgRXtNsEXqMLl2e+2H5eEJ7sfynF8TCaQ==", + "version": "4.16.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.1.tgz", + "integrity": "sha512-UXhDrwqsNcpTYJBTZsbGATDxZbiVDsx6UjpmRUmtnP10pr8wAYr5LgFoEFw9ixriQH2mv/NX2SfGzE/o8GndLA==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001164", + "caniuse-lite": "^1.0.30001173", "colorette": "^1.2.1", - "electron-to-chromium": "^1.3.612", + "electron-to-chromium": "^1.3.634", "escalade": "^3.1.1", - "node-releases": "^1.1.67" + "node-releases": "^1.1.69" } }, "browserstack": { @@ -1975,9 +2025,9 @@ "dev": true }, "builtin-modules": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz", - "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz", + "integrity": "sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==", "dev": true }, "bytes": { @@ -1987,19 +2037,19 @@ "dev": true }, "call-bind": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.0.tgz", - "integrity": "sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.1.tgz", + "integrity": "sha512-tvAvUwNcRikl3RVF20X9lsYmmepsovzTWeJiXjO0PkJp15uy/6xKFZOQtuiSULwYW+6ToZBprphCgWXC2dSgcQ==", "dev": true, "requires": { "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.0" + "get-intrinsic": "^1.0.2" } }, - "callsite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", - "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true }, "camelcase": { @@ -2020,9 +2070,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001165", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001165.tgz", - "integrity": "sha512-8cEsSMwXfx7lWSUMA2s08z9dIgsnR5NAqjXP23stdsU3AUWkCr/rr4s4OFtHXn5XXr6+7kam3QFVoYyXNPdJPA==", + "version": "1.0.30001174", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001174.tgz", + "integrity": "sha512-tqClL/4ThQq6cfFXH3oJL4rifFBeM6gTkphjao5kgwMaW9yn0tKgQLAEfKzDwj6HQWCB/aWo8kTFlSvIN8geEA==", "dev": true }, "caporal": { @@ -2104,54 +2154,19 @@ "dev": true }, "chokidar": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", - "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.0.tgz", + "integrity": "sha512-JgQM9JS92ZbFR4P90EvmzNpSGhpPBGBSj10PILeDyYFwp4h2/D9OM03wsJ4zW1fEp4ka2DGrnUeD7FuvQ2aZ2Q==", "dev": true, "requires": { "anymatch": "~3.1.1", "braces": "~3.0.2", - "fsevents": "~2.1.2", + "fsevents": "~2.3.1", "glob-parent": "~5.1.0", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.5.0" - }, - "dependencies": { - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - } } }, "ci-info": { @@ -2167,12 +2182,12 @@ "dev": true }, "cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", "dev": true, "requires": { - "restore-cursor": "^2.0.0" + "restore-cursor": "^3.1.0" } }, "cli-table3": { @@ -2244,81 +2259,6 @@ "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^6.2.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - }, - "wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - } } }, "code-point-at": { @@ -2361,9 +2301,9 @@ "dev": true }, "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", "dev": true }, "comment-parser": { @@ -2552,9 +2492,9 @@ } }, "conventional-changelog-core": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-4.2.1.tgz", - "integrity": "sha512-8cH8/DEoD3e5Q6aeogdR5oaaKs0+mG6+f+Om0ZYt3PNv7Zo0sQhu4bMDRsqAF+UTekTAtP1W/C41jH/fkm8Jtw==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-4.2.2.tgz", + "integrity": "sha512-7pDpRUiobQDNkwHyJG7k9f6maPo9tfPzkSWbRq97GGiZqisElhnvUZSvyQH20ogfOjntB5aadvv6NNcKL1sReg==", "dev": true, "requires": { "add-stream": "^1.0.0", @@ -2562,7 +2502,7 @@ "conventional-commits-parser": "^3.2.0", "dateformat": "^3.0.0", "get-pkg-repo": "^1.0.0", - "git-raw-commits": "2.0.0", + "git-raw-commits": "^2.0.8", "git-remote-origin-url": "^2.0.0", "git-semver-tags": "^4.1.1", "lodash": "^4.17.15", @@ -2665,9 +2605,9 @@ } }, "conventional-changelog-writer": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-4.0.18.tgz", - "integrity": "sha512-mAQDCKyB9HsE8Ko5cCM1Jn1AWxXPYV0v8dFPabZRkvsiWUul2YyAqbIaoMKF88Zf2ffnOPSvKhboLf3fnjo5/A==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-4.1.0.tgz", + "integrity": "sha512-WwKcUp7WyXYGQmkLsX4QmU42AZ1lqlvRW9mqoyiQzdD+rJWbTepdWoKJuwXTS+yq79XKnQNa93/roViPQrAQgw==", "dev": true, "requires": { "compare-func": "^2.0.0", @@ -2725,9 +2665,9 @@ } }, "cookie": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", "dev": true }, "core-js": { @@ -2737,12 +2677,12 @@ "dev": true }, "core-js-compat": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.8.1.tgz", - "integrity": "sha512-a16TLmy9NVD1rkjUGbwuyWkiDoN0FDpAwrfLONvHFQx0D9k7J9y0srwMT8QP/Z6HE3MIFaVynEeYwZwPX1o5RQ==", + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.8.2.tgz", + "integrity": "sha512-LO8uL9lOIyRRrQmZxHZFl1RV+ZbcsAkFWTktn5SmH40WgLtSNYN4m4W2v9ONT147PxBY/XrRhrWq8TlvObyUjQ==", "dev": true, "requires": { - "browserslist": "^4.15.0", + "browserslist": "^4.16.0", "semver": "7.0.0" }, "dependencies": { @@ -2794,70 +2734,17 @@ "dev": true, "requires": { "cross-spawn": "^7.0.1" - }, - "dependencies": { - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } } }, "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" } }, "currently-unhandled": { @@ -2898,13 +2785,10 @@ } }, "dargs": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/dargs/-/dargs-4.1.0.tgz", - "integrity": "sha1-A6nbtLXC8Tm/FK5T8LiipqhvThc=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", + "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", + "dev": true }, "date-format": { "version": "3.0.0", @@ -3163,9 +3047,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.621", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.621.tgz", - "integrity": "sha512-FeIuBzArONbAmKmZIsZIFGu/Gc9AVGlVeVbhCq+G2YIl6QkT0TDn2HKN/FMf1btXEB9kEmIuQf3/lBTVAbmFOg==", + "version": "1.3.636", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.636.tgz", + "integrity": "sha512-Adcvng33sd3gTjNIDNXGD1G4H6qCImIy2euUJAQHtLNplEKU5WEz5KRJxupRNIIT8sD5oFZLTKBWAf12Bsz24A==", "dev": true }, "emoji-regex": { @@ -3190,17 +3074,17 @@ } }, "engine.io": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.4.2.tgz", - "integrity": "sha512-b4Q85dFkGw+TqgytGPrGgACRUhsdKc9S9ErRAXpPGy/CXKs4tYoHDkvIRdsseAF7NjfVwjRFIn6KTnbw7LwJZg==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.5.0.tgz", + "integrity": "sha512-21HlvPUKaitDGE4GXNtQ7PLP0Sz4aWLddMPw2VTyFz1FVZqu/kZsJUO8WNpKuE/OCL7nkfRaOui2ZCJloGznGA==", "dev": true, "requires": { "accepts": "~1.3.4", "base64id": "2.0.0", - "cookie": "0.3.1", + "cookie": "~0.4.1", "debug": "~4.1.0", "engine.io-parser": "~2.2.0", - "ws": "^7.1.2" + "ws": "~7.4.2" }, "dependencies": { "debug": { @@ -3221,9 +3105,9 @@ } }, "engine.io-client": { - "version": "3.4.4", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.4.4.tgz", - "integrity": "sha512-iU4CRr38Fecj8HoZEnFtm2EiKGbYZcPn3cHxqNGl/tmdWRf60KhK+9vE0JeSjgnlS/0oynEfLgKbT9ALpim0sQ==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.5.0.tgz", + "integrity": "sha512-12wPRfMrugVw/DNyJk34GQ5vIVArEcVMXWugQGGuw2XxUSztFNmJggZmv8IZlLyEdnpO1QB9LkcjeWewO2vxtA==", "dev": true, "requires": { "component-emitter": "~1.3.0", @@ -3234,7 +3118,7 @@ "indexof": "0.0.1", "parseqs": "0.0.6", "parseuri": "0.0.6", - "ws": "~6.1.0", + "ws": "~7.4.2", "xmlhttprequest-ssl": "~1.5.4", "yeast": "0.1.2" }, @@ -3247,27 +3131,6 @@ "requires": { "ms": "2.0.0" } - }, - "parseqs": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz", - "integrity": "sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w==", - "dev": true - }, - "parseuri": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz", - "integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow==", - "dev": true - }, - "ws": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz", - "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==", - "dev": true, - "requires": { - "async-limiter": "~1.0.0" - } } } }, @@ -3357,9 +3220,9 @@ } }, "es5-shim": { - "version": "4.5.14", - "resolved": "https://registry.npmjs.org/es5-shim/-/es5-shim-4.5.14.tgz", - "integrity": "sha512-7SwlpL+2JpymWTt8sNLuC2zdhhc+wrfe5cMPI2j0o6WsPdfAiPwmFy2f0AocPB4RQVBOZ9kNTgi5YF7TdhkvEg==", + "version": "4.5.15", + "resolved": "https://registry.npmjs.org/es5-shim/-/es5-shim-4.5.15.tgz", + "integrity": "sha512-FYpuxEjMeDvU4rulKqFdukQyZSTpzhg4ScQHrAosrlVpR6GFyaw14f74yn2+4BugniIS0Frpg7TvwZocU4ZMTw==", "dev": true }, "es6-promise": { @@ -3414,12 +3277,6 @@ "source-map": "~0.2.0" }, "dependencies": { - "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true - }, "source-map": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", @@ -3476,13 +3333,41 @@ "text-table": "^0.2.0" }, "dependencies": { + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, "ansi-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, - "debug": { + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "debug": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", @@ -3511,16 +3396,6 @@ "escape-string-regexp": "^1.0.5" } }, - "import-fresh": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.2.tgz", - "integrity": "sha512-cTPNrlvJT6twpYy+YmKUKrTSjWFs3bjYjAhCwm+z4EOCubZxAuO+hHpRN64TqjEaYSHs7tJAE0w1CKMGmsG/lw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, "inquirer": { "version": "6.5.2", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", @@ -3565,6 +3440,12 @@ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -3577,18 +3458,52 @@ "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", "dev": true }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", "dev": true }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", @@ -3616,6 +3531,15 @@ "requires": { "os-tmpdir": "~1.0.2" } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } } } }, @@ -3701,9 +3625,9 @@ } }, "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", "dev": true }, "esquery": { @@ -3785,79 +3709,6 @@ "onetime": "^5.1.0", "signal-exit": "^3.0.2", "strip-final-newline": "^2.0.0" - }, - "dependencies": { - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", - "dev": true - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } } }, "exit-hook": { @@ -3986,12 +3837,12 @@ } }, "find-versions": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-3.2.0.tgz", - "integrity": "sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-4.0.0.tgz", + "integrity": "sha512-wgpWy002tA+wgmO27buH/9KzyEOQnKsG/R0yrcjPT9BOFm0zRBVQbZ95nRGXWMywS8YR5knRbpohio0bcJABxQ==", "dev": true, "requires": { - "semver-regex": "^2.0.0" + "semver-regex": "^3.1.2" } }, "flat-cache": { @@ -4023,9 +3874,9 @@ "dev": true }, "follow-redirects": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz", - "integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.1.tgz", + "integrity": "sha512-SSG5xmZh1mkPGyKzjZP8zLjltIfpW32Y5QpdNJyjcfGxK3qo3NDDkZOZSFiGn1A6SclQxY9GzEwAHQ3dmYRWpg==", "dev": true }, "format": { @@ -4058,9 +3909,9 @@ "dev": true }, "fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.1.tgz", + "integrity": "sha512-YR47Eg4hChJGAB1O3yEAOkGO+rlzutoICGqGo9EZ4lKWokzZRSyIW1QmTzqjtw8MJdj9srP869CuWw/hyzSiBw==", "dev": true, "optional": true }, @@ -4074,6 +3925,17 @@ "inherits": "~2.0.0", "mkdirp": ">=0.5 0", "rimraf": "2" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } } }, "function-bind": { @@ -4114,9 +3976,9 @@ "dev": true }, "get-intrinsic": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.1.tgz", - "integrity": "sha512-ZnWP+AmS1VUaLgTRy47+zKtjTxz+0xMpx3I52i+aalBK1QP19ggLF3Db89KJX7kjfOfP2eoa01qc++GwPgufPg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.2.tgz", + "integrity": "sha512-aeX0vrFm21ILl3+JpFFRNe9aUvp6VFZb2/CTbgLb8j75kOhvoNYjt9d8KA/tJG4gSo8nzEDedRl0h7vDmBYRVg==", "dev": true, "requires": { "function-bind": "^1.1.1", @@ -4339,165 +4201,26 @@ } }, "git-raw-commits": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.0.tgz", - "integrity": "sha512-w4jFEJFgKXMQJ0H0ikBk2S+4KP2VEjhCvLCNqbNRQC8BgGWgLKNCO7a9K9LI+TVT7Gfoloje502sEnctibffgg==", + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.9.tgz", + "integrity": "sha512-hSpNpxprVno7IOd4PZ93RQ+gNdzPAIrW0x8av6JQDJGV4k1mR9fE01dl8sEqi2P7aKmmwiGUn1BCPuf16Ae0Qw==", "dev": true, "requires": { - "dargs": "^4.0.1", + "dargs": "^7.0.0", "lodash.template": "^4.0.2", - "meow": "^4.0.0", - "split2": "^2.0.0", - "through2": "^2.0.0" + "meow": "^8.0.0", + "split2": "^3.0.0", + "through2": "^4.0.0" }, "dependencies": { - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - }, - "camelcase-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz", - "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=", - "dev": true, - "requires": { - "camelcase": "^4.1.0", - "map-obj": "^2.0.0", - "quick-lru": "^1.0.0" - } - }, - "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", - "dev": true - }, - "indent-string": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", - "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", - "dev": true - }, - "map-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz", - "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=", - "dev": true - }, - "meow": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/meow/-/meow-4.0.1.tgz", - "integrity": "sha512-xcSBHD5Z86zaOc+781KrupuHAzeGXSLtiAOmBsiLDiPSaYSB6hdew2ng9EBAnZ62jagG9MHAOdxpDi/lWBFJ/A==", - "dev": true, - "requires": { - "camelcase-keys": "^4.0.0", - "decamelize-keys": "^1.0.0", - "loud-rejection": "^1.0.0", - "minimist": "^1.1.3", - "minimist-options": "^3.0.1", - "normalize-package-data": "^2.3.4", - "read-pkg-up": "^3.0.0", - "redent": "^2.0.0", - "trim-newlines": "^2.0.0" - } - }, - "minimist-options": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-3.0.2.tgz", - "integrity": "sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==", - "dev": true, - "requires": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0" - } - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "quick-lru": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz", - "integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=", - "dev": true - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "redent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz", - "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=", - "dev": true, - "requires": { - "indent-string": "^3.0.0", - "strip-indent": "^2.0.0" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-indent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", - "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", - "dev": true - }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", "dev": true, "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" + "readable-stream": "^3.0.0" } - }, - "trim-newlines": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz", - "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=", - "dev": true } } }, @@ -4636,6 +4359,14 @@ "dev": true, "requires": { "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + } } }, "has-binary2": { @@ -4806,18 +4537,18 @@ "dev": true }, "husky": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/husky/-/husky-4.3.5.tgz", - "integrity": "sha512-E5S/1HMoDDaqsH8kDF5zeKEQbYqe3wL9zJDyqyYqc8I4vHBtAoxkDBGXox0lZ9RI+k5GyB728vZdmnM4bYap+g==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-4.3.7.tgz", + "integrity": "sha512-0fQlcCDq/xypoyYSJvEuzbDPHFf8ZF9IXKJxlrnvxABTSzK1VPT2RKYQKrcgJ+YD39swgoB6sbzywUqFxUiqjw==", "dev": true, "requires": { "chalk": "^4.0.0", "ci-info": "^2.0.0", "compare-versions": "^3.6.0", "cosmiconfig": "^7.0.0", - "find-versions": "^3.2.0", + "find-versions": "^4.0.0", "opencollective-postinstall": "^2.0.2", - "pkg-dir": "^4.2.0", + "pkg-dir": "^5.0.0", "please-upgrade-node": "^3.2.0", "slash": "^3.0.0", "which-pm-runs": "^1.0.0" @@ -4890,9 +4621,9 @@ "dev": true }, "import-fresh": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.2.tgz", - "integrity": "sha512-cTPNrlvJT6twpYy+YmKUKrTSjWFs3bjYjAhCwm+z4EOCubZxAuO+hHpRN64TqjEaYSHs7tJAE0w1CKMGmsG/lw==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, "requires": { "parent-module": "^1.0.0", @@ -4939,9 +4670,9 @@ "dev": true }, "ini": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.6.tgz", - "integrity": "sha512-IZUoxEjNjubzrmvzZU4lKP7OnYmX72XRl3sqkfJhBKweKi5rnGi5+IUdlj/H1M+Ip5JQ1WzaDMOBRY90Ajc5jg==", + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true }, "inquirer": { @@ -4972,6 +4703,12 @@ "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", "dev": true }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, "ansi-styles": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", @@ -5052,6 +4789,15 @@ "strip-ansi": "^3.0.0" } }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", @@ -5247,9 +4993,9 @@ "dev": true }, "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", "dev": true }, "is-symbol": { @@ -5343,12 +5089,6 @@ "wordwrap": "^1.0.0" }, "dependencies": { - "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true - }, "glob": { "version": "5.0.15", "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", @@ -5382,6 +5122,15 @@ "requires": { "has-flag": "^1.0.0" } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } } } }, @@ -5462,42 +5211,75 @@ "requires": { "argparse": "^1.0.7", "esprima": "^4.0.0" + }, + "dependencies": { + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + } } }, "js2xmlparser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-3.0.0.tgz", - "integrity": "sha1-P7YOqgicVED5MZ9RdgzNB+JJlzM=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.1.tgz", + "integrity": "sha512-KrPTolcw6RocpYjdC7pL7v62e55q7qOMHvLX1UCLc5AAS8qeJ6nukarEJAF2KL2PZxlbGueEbINqZR2bDe/gUw==", "dev": true, "requires": { - "xmlcreate": "^1.0.1" + "xmlcreate": "^2.0.3" } }, "jsdoc": { - "version": "github:BrandonOCasey/jsdoc#a3c385e800d8b64ab166d163494182aa4ef92535", - "from": "github:BrandonOCasey/jsdoc#feat/plugin-from-cli", - "dev": true, - "requires": { - "@babel/parser": "~7.2.3", - "bluebird": "~3.5.0", - "catharsis": "~0.8.9", - "escape-string-regexp": "~1.0.5", - "js2xmlparser": "~3.0.0", - "klaw": "~3.0.0", - "markdown-it": "~8.4.2", - "markdown-it-anchor": "~5.0.2", - "marked": "~0.6.0", - "mkdirp": "~0.5.1", - "requizzle": "~0.2.1", - "strip-json-comments": "~2.0.1", + "version": "3.6.6", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.6.tgz", + "integrity": "sha512-znR99e1BHeyEkSvgDDpX0sTiTu+8aQyDl9DawrkOGZTTW8hv0deIFXx87114zJ7gRaDZKVQD/4tr1ifmJp9xhQ==", + "dev": true, + "requires": { + "@babel/parser": "^7.9.4", + "bluebird": "^3.7.2", + "catharsis": "^0.8.11", + "escape-string-regexp": "^2.0.0", + "js2xmlparser": "^4.0.1", + "klaw": "^3.0.0", + "markdown-it": "^10.0.0", + "markdown-it-anchor": "^5.2.7", + "marked": "^0.8.2", + "mkdirp": "^1.0.4", + "requizzle": "^0.2.3", + "strip-json-comments": "^3.1.0", "taffydb": "2.6.2", - "underscore": "~1.9.1" + "underscore": "~1.10.2" }, "dependencies": { + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, "underscore": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.2.tgz", - "integrity": "sha512-D39qtimx0c1fI3ya1Lnhk3E9nONswSKhnffBI0gME9C99fYOkNi04xs8K6pePLhvl1frbDemkaBQ5ikWllR2HQ==", + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.10.2.tgz", + "integrity": "sha512-N4P+Q/BuyuEKFJ43B9gYuOj4TQUHXX+j2FqguVOpjkssLUUrnJofCcBccJSCoeturDoZU6GorDTHSvUDlSQbTg==", "dev": true } } @@ -5613,50 +5395,6 @@ "tmp": "0.2.1", "ua-parser-js": "0.7.22", "yargs": "^15.3.1" - }, - "dependencies": { - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - } } }, "karma-browserstack-launcher": { @@ -5677,6 +5415,17 @@ "dev": true, "requires": { "which": "^1.2.1" + }, + "dependencies": { + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } } }, "karma-coverage": { @@ -5855,6 +5604,17 @@ "dev": true, "requires": { "which": "^1.2.4" + }, + "dependencies": { + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } } }, "karma-firefox-launcher": { @@ -5865,17 +5625,6 @@ "requires": { "is-wsl": "^2.2.0", "which": "^2.0.1" - }, - "dependencies": { - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } } }, "karma-ie-launcher": { @@ -5894,9 +5643,9 @@ "dev": true }, "karma-safari-applescript-launcher": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/karma-safari-applescript-launcher/-/karma-safari-applescript-launcher-0.1.1.tgz", - "integrity": "sha512-QVwXLtDnDbuKiupIZGCD56AUmGHUtDFoe80eMNf+dfZMJ7n4T1lNYr3wVjwuvB0vQaFV1/qdtqaZxmTMQ3VASQ==", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/karma-safari-applescript-launcher/-/karma-safari-applescript-launcher-0.1.0.tgz", + "integrity": "sha512-BAg8Q+VFgb8G9IajAYWvFSmvCYBr/RwqwZBRs6jbyaoIrHdi5boPgjz92c+y95zcKtsOqg8hncelsuuU6pA4hw==", "dev": true, "requires": { "run-applescript": "^3.2.0" @@ -6019,12 +5768,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "commander": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.0.tgz", - "integrity": "sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==", - "dev": true - }, "debug": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", @@ -6320,15 +6063,6 @@ "wrap-ansi": "^6.2.0" }, "dependencies": { - "ansi-escapes": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", - "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", - "dev": true, - "requires": { - "type-fest": "^0.11.0" - } - }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -6338,21 +6072,6 @@ "color-convert": "^2.0.1" } }, - "astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "requires": { - "restore-cursor": "^3.1.0" - } - }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -6368,31 +6087,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - } - }, "slice-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", @@ -6403,12 +6097,6 @@ "astral-regex": "^2.0.0", "is-fullwidth-code-point": "^3.0.0" } - }, - "type-fest": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", - "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", - "dev": true } } }, @@ -6480,13 +6168,13 @@ } }, "m3u8-parser": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/m3u8-parser/-/m3u8-parser-4.5.0.tgz", - "integrity": "sha512-RGm/1WVCX3o1bSWbJGmJUu4zTbtJy8lImtgHM4CESFvJRXYztr1j6SW/q9/ghYOrUjgH7radsIar+z1Leln0sA==", + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/m3u8-parser/-/m3u8-parser-4.5.2.tgz", + "integrity": "sha512-sN/lu3TiRxmG2RFjZxo5c0/7Dr4RrEztl43jXrWwj5gFZ7vfa2iIxGfiPx485dm5QCazaIcKk+vNkUso8Aq0Ag==", "requires": { - "@babel/runtime": "^7.5.5", - "@videojs/vhs-utils": "^2.2.1", - "global": "^4.3.2" + "@babel/runtime": "^7.12.5", + "@videojs/vhs-utils": "^3.0.0", + "global": "^4.4.0" } }, "magic-string": { @@ -6511,28 +6199,36 @@ "dev": true }, "markdown-it": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.2.tgz", - "integrity": "sha512-GcRz3AWTqSUphY3vsUqQSFMbgR38a4Lh3GWlHRh/7MRwz8mcu9n2IO7HOh+bXHrR9kOPDl5RNCaEsrneb+xhHQ==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz", + "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==", "dev": true, "requires": { "argparse": "^1.0.7", - "entities": "~1.1.1", + "entities": "~2.0.0", "linkify-it": "^2.0.0", "mdurl": "^1.0.1", "uc.micro": "^1.0.5" + }, + "dependencies": { + "entities": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", + "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", + "dev": true + } } }, "markdown-it-anchor": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-5.0.2.tgz", - "integrity": "sha512-AFM/woBI8QDJMS/9+MmsBMT5/AR+ImfOsunQZTZhzcTmna3rIzAzbOh5E0l6mlFM/i9666BpUtkqQ9bS7WApCg==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-5.3.0.tgz", + "integrity": "sha512-/V1MnLL/rgJ3jkMWo84UR+K+jF1cxNG1a+KwqeXqTIJ+jtA8aWSHuigx8lTzauiIjBDbwF3NcWQMotd0Dm39jA==", "dev": true }, "marked": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/marked/-/marked-0.6.3.tgz", - "integrity": "sha512-Fqa7eq+UaxfMriqzYLayfqAE40WN03jf+zHjT18/uXNuzjq3TY0XTbrAoPeqSJrAmPz11VuUA+kBPYOhHt9oOQ==", + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.8.2.tgz", + "integrity": "sha512-EGwzEeCcLniFX51DhTpmTom+dSA/MG/OBUDjnWtHbEnjAH180VzUeAw+oE4+Zv+CoYBWyRlYOTR0N8SO9R1PVw==", "dev": true }, "matched": { @@ -6564,9 +6260,9 @@ "dev": true }, "meow": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-8.0.0.tgz", - "integrity": "sha512-nbsTRz2fwniJBFgUkcdISq8y/q9n9VbiHYbfwklFh5V4V2uAcxtKQkDc0yCLPM/kP0d+inZBewn3zJqewHE7kg==", + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", + "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", "dev": true, "requires": { "@types/minimist": "^1.2.0", @@ -6673,30 +6369,30 @@ } }, "mime": { - "version": "2.4.6", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", - "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==", + "version": "2.4.7", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.7.tgz", + "integrity": "sha512-dhNd1uA2u397uQk3Nv5LM4lm93WYDUXFn3Fu291FJerns4jyTudqhIWe4W04YLy7Uk1tm1Ore04NpjRvQp/NPA==", "dev": true }, "mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "version": "1.45.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", + "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==", "dev": true }, "mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "version": "2.1.28", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz", + "integrity": "sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==", "dev": true, "requires": { - "mime-db": "1.44.0" + "mime-db": "1.45.0" } }, "mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true }, "min-document": { @@ -6755,14 +6451,21 @@ "dev": true }, "mpd-parser": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/mpd-parser/-/mpd-parser-0.15.0.tgz", - "integrity": "sha512-GfspJVaEnVbWKZQASvh9nsJkvxWh3M/c5Kb2RPnN5ZXPZ7jWWfarWkNKTEuqvoaAKIT8IB/r6PFTWA1GY4fzGg==", + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/mpd-parser/-/mpd-parser-0.15.2.tgz", + "integrity": "sha512-bhvyzMkJVpxEcF33cngKEBexB6zARhoB6IPC/lh8kDzwmbmvhWFZYj/VG14FThPLvuXMuqB++sE/XcH35dxafA==", "requires": { - "@babel/runtime": "^7.5.5", - "@videojs/vhs-utils": "^2.2.1", - "global": "^4.3.2", - "xmldom": "^0.1.27" + "@babel/runtime": "^7.12.5", + "@videojs/vhs-utils": "^3.0.0", + "global": "^4.4.0", + "xmldom": "^0.4.0" + }, + "dependencies": { + "xmldom": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.4.0.tgz", + "integrity": "sha512-2E93k08T30Ugs+34HBSTQLVtpi6mCddaY8uO+pMNk1pqSjV5vElzn4mmh6KLxN3hki8rNcHSYzILoh3TEWORvA==" + } } }, "ms": { @@ -6821,9 +6524,9 @@ } }, "node-releases": { - "version": "1.1.67", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.67.tgz", - "integrity": "sha512-V5QF9noGFl3EymEwUYzO+3NTDpGfQB4ve6Qfnzf3UNydMhjQRVPR1DZTuvWiLzaFJYw2fmDwAfnRNEVb64hSIg==", + "version": "1.1.69", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.69.tgz", + "integrity": "sha512-DGIjo79VDEyAnRlfSqYTsy+yoHd2IOjJiKUozD2MV2D85Vso6Bug56mb9tT/fY5Urt0iqk01H7x+llAruDR2zA==", "dev": true }, "node-watch": { @@ -6970,15 +6673,66 @@ "read-pkg": "^3.0.0", "shell-quote": "^1.6.1", "string.prototype.padend": "^3.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } } }, "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dev": true, "requires": { - "path-key": "^2.0.0" + "path-key": "^3.0.0" } }, "npmlog": { @@ -7004,12 +6758,6 @@ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true }, - "object-component": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", - "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=", - "dev": true - }, "object-inspect": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz", @@ -7053,12 +6801,12 @@ } }, "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, "requires": { - "mimic-fn": "^1.0.0" + "mimic-fn": "^2.1.0" } }, "opencollective-postinstall": { @@ -7139,14 +6887,6 @@ "dev": true, "requires": { "callsites": "^3.0.0" - }, - "dependencies": { - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - } } }, "parse-entities": { @@ -7182,22 +6922,16 @@ } }, "parseqs": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", - "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", - "dev": true, - "requires": { - "better-assert": "~1.0.0" - } + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz", + "integrity": "sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w==", + "dev": true }, "parseuri": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", - "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", - "dev": true, - "requires": { - "better-assert": "~1.0.0" - } + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz", + "integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow==", + "dev": true }, "parseurl": { "version": "1.3.3", @@ -7224,9 +6958,9 @@ "dev": true }, "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true }, "path-parse": { @@ -7305,12 +7039,51 @@ } }, "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", + "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", "dev": true, "requires": { - "find-up": "^4.0.0" + "find-up": "^5.0.0" + }, + "dependencies": { + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + } } }, "please-upgrade-node": { @@ -7396,9 +7169,9 @@ "dev": true }, "qunit": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/qunit/-/qunit-2.13.0.tgz", - "integrity": "sha512-RvJquyNKbMSn5Qo28S2wKWxHl1Ku8m0zFLTKsXfq/WZkyM+b28gpEs6YkKN1fOCV4S+979+GnevD0FRgQayo3Q==", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/qunit/-/qunit-2.12.0.tgz", + "integrity": "sha512-Lu3tbKziVzXTfseoEtTiiSAbSPB6SGU4Emc2uo8n+fbsXuRCLzfqPwJfAVJwKu9NdukX1V/L0qWf2UvmPX+QeA==", "dev": true, "requires": { "commander": "6.2.0", @@ -7678,9 +7451,9 @@ "dev": true }, "regjsparser": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.4.tgz", - "integrity": "sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw==", + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.6.tgz", + "integrity": "sha512-jjyuCp+IEMIm3N1H1LLTJW1EISEJV9+5oHdEyrt43Pg9cDSb6rrLZei2cVWpl0xTjmmlpec/lEQGYgM7xfpGCQ==", "dev": true, "requires": { "jsesc": "~0.5.0" @@ -7792,12 +7565,12 @@ "dev": true }, "restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", "dev": true, "requires": { - "onetime": "^2.0.0", + "onetime": "^5.1.0", "signal-exit": "^3.0.2" } }, @@ -7808,21 +7581,30 @@ "dev": true }, "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, "requires": { "glob": "^7.1.3" } }, "rollup": { - "version": "2.34.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.34.2.tgz", - "integrity": "sha512-mvtQLqu3cNeoctS+kZ09iOPxrc1P1/Bt1z15enuQ5feyKOdM3MJAVFjjsygurDpSWn530xB4AlA83TWIzRstXA==", + "version": "2.36.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.36.1.tgz", + "integrity": "sha512-eAfqho8dyzuVvrGqpR0ITgEdq0zG2QJeWYh+HeuTbpcaXk8vNFc48B7bJa1xYosTCKx0CuW+447oQOW8HgBIZQ==", "dev": true, "requires": { "fsevents": "~2.1.2" + }, + "dependencies": { + "fsevents": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "dev": true, + "optional": true + } } }, "rollup-plugin-istanbul": { @@ -7873,6 +7655,19 @@ "execa": "^0.10.0" }, "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, "execa": { "version": "0.10.0", "resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz", @@ -7893,6 +7688,57 @@ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", "dev": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } } } }, @@ -7958,9 +7804,9 @@ "dev": true }, "semver-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-2.0.0.tgz", - "integrity": "sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-3.1.2.tgz", + "integrity": "sha512-bXWyL6EAKOJa81XG1OZ/Yyuq+oT0b2YLlxx7c+mrdYPaPbnj6WgVULXhinMIeZGufuUBu/eVRqXEhiv4imfwxA==", "dev": true }, "send": { @@ -8038,18 +7884,18 @@ "dev": true }, "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "requires": { - "shebang-regex": "^1.0.0" + "shebang-regex": "^3.0.0" } }, "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, "shell-quote": { @@ -8143,12 +7989,6 @@ "color-convert": "^2.0.1" } }, - "astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true - }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -8167,16 +8007,16 @@ } }, "socket.io": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.3.0.tgz", - "integrity": "sha512-2A892lrj0GcgR/9Qk81EaY2gYhCBxurV0PfmmESO6p27QPrUK1J3zdns+5QPqvUYK2q657nSj0guoIil9+7eFg==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.4.1.tgz", + "integrity": "sha512-Si18v0mMXGAqLqCVpTxBa8MGqriHGQh8ccEOhmsmNS3thNCGBwO8WGrwMibANsWtQQ5NStdZwHqZR3naJVFc3w==", "dev": true, "requires": { "debug": "~4.1.0", - "engine.io": "~3.4.0", + "engine.io": "~3.5.0", "has-binary2": "~1.0.2", "socket.io-adapter": "~1.1.0", - "socket.io-client": "2.3.0", + "socket.io-client": "2.4.0", "socket.io-parser": "~3.4.0" }, "dependencies": { @@ -8204,46 +8044,31 @@ "dev": true }, "socket.io-client": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.3.0.tgz", - "integrity": "sha512-cEQQf24gET3rfhxZ2jJ5xzAOo/xhZwK+mOqtGRg5IowZsMgwvHwnf/mCRapAAkadhM26y+iydgwsXGObBB5ZdA==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.4.0.tgz", + "integrity": "sha512-M6xhnKQHuuZd4Ba9vltCLT9oa+YvTsP8j9NcEiLElfIg8KeYPyhWOes6x4t+LTAC8enQbE/995AdTem2uNyKKQ==", "dev": true, "requires": { "backo2": "1.0.2", - "base64-arraybuffer": "0.1.5", "component-bind": "1.0.0", - "component-emitter": "1.2.1", - "debug": "~4.1.0", - "engine.io-client": "~3.4.0", + "component-emitter": "~1.3.0", + "debug": "~3.1.0", + "engine.io-client": "~3.5.0", "has-binary2": "~1.0.2", - "has-cors": "1.1.0", "indexof": "0.0.1", - "object-component": "0.0.3", - "parseqs": "0.0.5", - "parseuri": "0.0.5", + "parseqs": "0.0.6", + "parseuri": "0.0.6", "socket.io-parser": "~3.3.0", "to-array": "0.1.4" }, "dependencies": { - "base64-arraybuffer": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", - "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", - "dev": true - }, - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", - "dev": true - }, "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.0.0" } }, "isarray": { @@ -8252,44 +8077,15 @@ "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", "dev": true }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, "socket.io-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.1.tgz", - "integrity": "sha512-1QLvVAe8dTz+mKmZ07Swxt+LAo4Y1ff50rlyoEx00TQmDFVQYPfcqGvIDJLGaBdhdNCecXtyKpD+EgKGcmmbuQ==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.2.tgz", + "integrity": "sha512-FJvDBuOALxdCI9qwRrO/Rfp9yfndRtc1jSgVgV8FDraihmSP/MLGD5PEuJrNfjALvcQ+vMDM/33AWOYP/JSjDg==", "dev": true, "requires": { "component-emitter": "~1.3.0", "debug": "~3.1.0", "isarray": "2.0.1" - }, - "dependencies": { - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } } } } @@ -8533,26 +8329,11 @@ "strip-ansi": "^6.0.0" }, "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } } } }, @@ -8616,12 +8397,12 @@ } }, "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "^5.0.0" } }, "strip-bom": { @@ -8696,6 +8477,12 @@ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, "emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", @@ -8790,6 +8577,12 @@ "source-map-support": "~0.5.19" }, "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, "source-map": { "version": "0.7.3", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", @@ -8842,17 +8635,6 @@ "dev": true, "requires": { "rimraf": "^3.0.0" - }, - "dependencies": { - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } } }, "to-array": { @@ -8986,9 +8768,9 @@ "dev": true }, "uglify-js": { - "version": "3.12.1", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.12.1.tgz", - "integrity": "sha512-o8lHP20KjIiQe5b/67Rh68xEGRrc2SRsCuuoYclXXoC74AfSRGblU1HKzJWH3HxPZ+Ort85fWHpSX7KwBUC9CQ==", + "version": "3.12.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.12.4.tgz", + "integrity": "sha512-L5i5jg/SHkEqzN18gQMTWsZk3KelRsfD1wUVNqtq0kzqWQqcJjyL8yc1o8hJgRrWqrAl2mUFbhfznEIoi7zi2A==", "dev": true, "optional": true }, @@ -9163,9 +8945,9 @@ "dev": true }, "uri-js": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", - "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, "requires": { "punycode": "^2.1.0" @@ -9232,12 +9014,12 @@ } }, "video.js": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/video.js/-/video.js-7.11.0.tgz", - "integrity": "sha512-N10MQilHvCsrFa1hkbmTiLeyTEaJe70aIHX+WyafHtv+skBStCRoAfr3PFW9pDKxsXoBAI5NrLpocK/MT/SQhw==", + "version": "7.10.2", + "resolved": "https://registry.npmjs.org/video.js/-/video.js-7.10.2.tgz", + "integrity": "sha512-kJTTrqcQn2MhPzWR8zQs6W3HPJWpowO/ZGZcKt2dcJeJdJT0dEDLYtiFdjV37SylCmu66V0flRnV8cipbthveQ==", "requires": { "@babel/runtime": "^7.9.2", - "@videojs/http-streaming": "2.3.0", + "@videojs/http-streaming": "2.2.4", "@videojs/xhr": "2.5.1", "global": "4.3.2", "keycode": "^2.2.0", @@ -9288,9 +9070,9 @@ "integrity": "sha512-g8vHMKK2/JGorSfqAZQUmYYNnXmfec4MLhwtEFS+mMs2IDY398GLysy6BH6K+aS1KMNu/xWZ8Sue/X/mdQPliA==" }, "videojs-generate-karma-config": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/videojs-generate-karma-config/-/videojs-generate-karma-config-7.0.1.tgz", - "integrity": "sha512-XoyPtym+Wi86yZBVTkvljsPou6xzoeuWA4OVQviCjOyKsW+LQnYlVxmNZboAdT7w8ZuQ0HzvmLLHAnfaib7t3A==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/videojs-generate-karma-config/-/videojs-generate-karma-config-7.0.0.tgz", + "integrity": "sha512-nC3SZeVx3OtNiCtdjkC+GT4imfuDhGhpaxr/sfNJv2QmvzKhAhGkySRrh01+SLF85e+yAaCeitDYkXP5QlqtJg==", "dev": true, "requires": { "is-ci": "^2.0.0", @@ -9304,7 +9086,7 @@ "karma-safari-applescript-launcher": "~0.1.0", "karma-static-server": "^1.0.0", "karma-teamcity-reporter": "^1.1.0", - "qunit": "~2.13.0" + "qunit": "~2.12.0" } }, "videojs-generate-rollup-config": { @@ -9347,9 +9129,9 @@ } }, "videojs-standard": { - "version": "8.0.6", - "resolved": "https://registry.npmjs.org/videojs-standard/-/videojs-standard-8.0.6.tgz", - "integrity": "sha512-QA7kbInwDFaUa+zmJ93CxdC4Rzvt31eUg++jEmSaCzX/sER25LwkVnyY5eA1zBMLwMjLt/dn0yChLAuO+xvwQg==", + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/videojs-standard/-/videojs-standard-8.0.4.tgz", + "integrity": "sha512-IGv4gXB8osXZDsPqYNpWfcmAue/udVEr/Lxa4ewo1aR8s4KY5L6+6IQ+X1Ut9qQUVTSdJZ6QTYvthZzwcHbrkQ==", "dev": true, "requires": { "commander": "^2.17.1", @@ -9360,6 +9142,14 @@ "eslint-plugin-markdown": "^1.0.0", "find-root": "^1.0.0", "tsmlb": "^1.0.0" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + } } }, "videojs-vtt.js": { @@ -9377,9 +9167,9 @@ "dev": true }, "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "requires": { "isexe": "^2.0.0" @@ -9448,12 +9238,6 @@ "strip-ansi": "^6.0.0" }, "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -9477,15 +9261,6 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } } } }, @@ -9505,9 +9280,9 @@ } }, "ws": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.1.tgz", - "integrity": "sha512-pTsP8UAfhy3sk1lSk/O/s4tjD0CRwvMnzvwr4OKGX7ZvqZtUyx4KIJB5JWbkykPoc55tixMGgTNoh3k4FkNGFQ==", + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.2.tgz", + "integrity": "sha512-T4tewALS3+qsrpGI/8dqNMLIVdq/g/85U98HPMa6F0m6xTbvhXU6RCQLqPH3+SlomNV/LdY6RXEbBpMH6EOJnA==", "dev": true }, "x-is-string": { @@ -9517,9 +9292,9 @@ "dev": true }, "xmlcreate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-1.0.2.tgz", - "integrity": "sha1-+mv3YqYKQT+z3Y9LA8WyaSONMI8=", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.3.tgz", + "integrity": "sha512-HgS+X6zAztGa9zIK3Y3LXuJes33Lz9x+YyTxgrkIdabu2vqcGOWwdfCpf1hWLRrd553wd4QCDf6BBO6FfdsRiQ==", "dev": true }, "xmldom": { @@ -9576,44 +9351,6 @@ "yargs-parser": "^18.1.2" }, "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - }, "yargs-parser": { "version": "18.1.3", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", @@ -9637,6 +9374,12 @@ "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=", "dev": true + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true } } } diff --git a/package.json b/package.json index 989ae4c7b..db55e15f4 100644 --- a/package.json +++ b/package.json @@ -56,29 +56,30 @@ ], "dependencies": { "@babel/runtime": "^7.12.5", - "@videojs/vhs-utils": "^2.3.0", - "aes-decrypter": "3.1.0", + "@videojs/vhs-utils": "^3.0.0", + "aes-decrypter": "3.1.2", "global": "^4.4.0", - "m3u8-parser": "4.5.0", - "mpd-parser": "0.15.0", + "m3u8-parser": "4.5.2", + "mpd-parser": "0.15.2", "mux.js": "5.8.0", "video.js": "^6 || ^7" }, "devDependencies": { "@gkatsev/rollup-plugin-bundle-worker": "^1.0.2", + "@rollup/plugin-replace": "^2.3.4", "@videojs/generator-helpers": "~2.0.1", "d3": "^3.4.8", "es5-shim": "^4.5.13", "es6-shim": "^0.35.5", - "jsdoc": "BrandonOCasey/jsdoc#feat/plugin-from-cli", + "jsdoc": "~3.6.6", "karma": "^5.2.3", "lodash": "^4.17.4", "lodash-compat": "^3.10.0", "nomnoml": "^0.3.0", - "rollup": "^2.34.2", + "rollup": "^2.36.1", "shelljs": "^0.8.4", "sinon": "^8.1.1", - "url-toolkit": "^2.1.3", + "url-toolkit": "^2.2.1", "videojs-contrib-eme": "^3.8.0", "videojs-contrib-quality-levels": "^2.0.4", "videojs-generate-karma-config": "~7.0.0", diff --git a/scripts/rollup.config.js b/scripts/rollup.config.js index 12c072944..a12ee47b9 100644 --- a/scripts/rollup.config.js +++ b/scripts/rollup.config.js @@ -2,6 +2,7 @@ const generate = require('videojs-generate-rollup-config'); const worker = require('@gkatsev/rollup-plugin-bundle-worker'); const {terser} = require('rollup-plugin-terser'); const createTestData = require('./create-test-data.js'); +const replace = require('@rollup/plugin-replace'); // see https://github.com/videojs/videojs-generate-rollup-config // for options @@ -35,11 +36,18 @@ const options = { if (defaults.test.indexOf('istanbul') !== -1) { defaults.test.splice(defaults.test.indexOf('istanbul'), 1); } + defaults.module.unshift('replace'); return defaults; }, primedPlugins(defaults) { return Object.assign(defaults, { + replace: replace({ + // single quote replace + "require('@videojs/vhs-utils/es": "require('@videojs/vhs-utils/cjs", + // double quote replace + 'require("@videojs/vhs-utils/es': 'require("@videojs/vhs-utils/cjs' + }), worker: worker(), uglify: terser({ output: {comments: 'some'}, diff --git a/scripts/sources.json b/scripts/sources.json index aac4fbb3f..5b75abbe6 100644 --- a/scripts/sources.json +++ b/scripts/sources.json @@ -335,7 +335,7 @@ "features": [] }, { - "name": "(Not Working) ts one valid codec among many invalid", + "name": "ts one valid codec among many invalid", "uri": "https://d2zihajmogu5jn.cloudfront.net/ts-one-valid-many-invalid-codecs/master.m3u8", "mimetype": "application/x-mpegurl", "features": [] diff --git a/src/dash-playlist-loader.js b/src/dash-playlist-loader.js index 9ae3f8263..2fb50011e 100644 --- a/src/dash-playlist-loader.js +++ b/src/dash-playlist-loader.js @@ -17,7 +17,7 @@ import { addPropertiesToMaster } from './manifest'; import containerRequest from './util/container-request.js'; -import {toUint8} from '@videojs/vhs-utils/dist/byte-helpers'; +import {toUint8} from '@videojs/vhs-utils/es/byte-helpers'; const { EventTarget, mergeOptions } = videojs; diff --git a/src/master-playlist-controller.js b/src/master-playlist-controller.js index 4017667d4..971e6454d 100644 --- a/src/master-playlist-controller.js +++ b/src/master-playlist-controller.js @@ -21,8 +21,8 @@ import { muxerSupportsCodec, DEFAULT_AUDIO_CODEC, DEFAULT_VIDEO_CODEC -} from '@videojs/vhs-utils/dist/codecs.js'; -import { codecsForPlaylist } from './util/codecs.js'; +} from '@videojs/vhs-utils/es/codecs.js'; +import { codecsForPlaylist, unwrapCodecList, codecCount } from './util/codecs.js'; import { createMediaTypes, setupMediaGroups } from './media-groups'; import logger from './util/logger'; @@ -1562,8 +1562,8 @@ export class MasterPlaylistController extends videojs.EventTarget { const switchMessages = []; ['video', 'audio'].forEach((type) => { - const newCodec = (parseCodecs(this.sourceUpdater_.codecs[type] || '')[type] || {}).type; - const oldCodec = (parseCodecs(codecs[type] || '')[type] || {}).type; + const newCodec = (parseCodecs(this.sourceUpdater_.codecs[type] || '')[0] || {}).type; + const oldCodec = (parseCodecs(codecs[type] || '')[0] || {}).type; if (newCodec && oldCodec && newCodec.toLowerCase() !== oldCodec.toLowerCase()) { switchMessages.push(`"${this.sourceUpdater_.codecs[type]}" -> "${codecs[type]}"`); @@ -1642,22 +1642,20 @@ export class MasterPlaylistController extends videojs.EventTarget { const unsupported = []; if (codecs.audio && !muxerSupportsCodec(codecs.audio) && !browserSupportsCodec(codecs.audio)) { - variant.excludeUntil = Infinity; unsupported.push(`audio codec ${codecs.audio}`); } if (codecs.video && !muxerSupportsCodec(codecs.video) && !browserSupportsCodec(codecs.video)) { - variant.excludeUntil = Infinity; unsupported.push(`video codec ${codecs.video}`); } if (codecs.text && codecs.text === 'stpp.ttml.im1t') { - variant.excludeUntil = Infinity; unsupported.push(`text codec ${codecs.text}`); } if (unsupported.length) { - this.logger_(`excluding ${variant.id} as codecs ${unsupported.join(', ')} are unsupported`); + variant.excludeUntil = Infinity; + this.logger_(`excluding ${variant.id} for unsupported: ${unsupported.join(', ')}`); } }); } @@ -1677,67 +1675,61 @@ export class MasterPlaylistController extends videojs.EventTarget { * @private */ excludeIncompatibleVariants_(codecString) { - const codecs = parseCodecs(codecString); - const codecCount = Object.keys(codecs).length; + const ids = []; + const playlists = this.master().playlists; + const codecs = unwrapCodecList(parseCodecs(codecString)); + const codecCount_ = codecCount(codecs); + const videoDetails = codecs.video && parseCodecs(codecs.video)[0] || null; + const audioDetails = codecs.audio && parseCodecs(codecs.audio)[0] || null; + + Object.keys(playlists).forEach((key) => { + const variant = playlists[key]; - this.master().playlists.forEach((variant) => { - // skip variants that are already blacklisted forever - if (variant.excludeUntil === Infinity) { + // check if we already processed this playlist. + // or it if it is already excluded forever. + if (ids.indexOf(variant.id) !== -1 || variant.excludeUntil === Infinity) { return; } - /* TODO: Decide whether two codecs should be assumed here. - * Right now, for playlists that don't specify codecs, VHS assumes - * that there are two (one for audio and one for video). - * Although this is often the case, this may lead to broken behavior - * if the playlist only has one codec. It may be better in the future - * to decide at time of segment download how many tracks there are and - * determine the proper codecs. This will come at a cost of potentially - * more bandwidth, but will be a more robust approach than the assumption here. - */ - - let variantCodecs = {}; - let variantCodecCount = 2; + + ids.push(variant.id); const blacklistReasons = []; // get codecs from the playlist for this variant - const variantCodecStrings = codecsForPlaylist(this.masterPlaylistLoader_.master, variant); - - if (variantCodecStrings.audio || variantCodecStrings.video) { - const variantCodecString = [variantCodecStrings.video, variantCodecStrings.audio] - .filter(Boolean) - .join(','); + const variantCodecs = codecsForPlaylist(this.masterPlaylistLoader_.master, variant); + const variantCodecCount = codecCount(variantCodecs); - variantCodecs = parseCodecs(variantCodecString); - variantCodecCount = Object.keys(variantCodecs).length; + // if no codecs are listed, we cannot determine that this + // variant is incompatible. Wait for mux.js to probe + if (!variantCodecs.audio && !variantCodecs.video) { + return; } // TODO: we can support this by removing the // old media source and creating a new one, but it will take some work. // The number of streams cannot change - if (variantCodecCount !== codecCount) { - blacklistReasons.push(`codec count "${variantCodecCount}" !== "${codecCount}"`); - variant.excludeUntil = Infinity; + if (variantCodecCount !== codecCount_) { + blacklistReasons.push(`codec count "${variantCodecCount}" !== "${codecCount_}"`); } // only exclude playlists by codec change, if codecs cannot switch // during playback. if (!this.sourceUpdater_.canChangeType()) { + const variantVideoDetails = variantCodecs.video && parseCodecs(variantCodecs.video)[0] || null; + const variantAudioDetails = variantCodecs.audio && parseCodecs(variantCodecs.audio)[0] || null; + // the video codec cannot change - if (variantCodecs.video && codecs.video && - variantCodecs.video.type.toLowerCase() !== codecs.video.type.toLowerCase()) { - blacklistReasons.push(`video codec "${variantCodecs.video.type}" !== "${codecs.video.type}"`); - variant.excludeUntil = Infinity; + if (variantVideoDetails && videoDetails && variantVideoDetails.type.toLowerCase() !== videoDetails.type.toLowerCase()) { + blacklistReasons.push(`video codec "${variantVideoDetails.type}" !== "${videoDetails.type}"`); } // the audio codec cannot change - if (variantCodecs.audio && codecs.audio && - variantCodecs.audio.type.toLowerCase() !== codecs.audio.type.toLowerCase()) { - variant.excludeUntil = Infinity; - blacklistReasons.push(`audio codec "${variantCodecs.audio.type}" !== "${codecs.audio.type}"`); + if (variantAudioDetails && audioDetails && variantAudioDetails.type.toLowerCase() !== audioDetails.type.toLowerCase()) { + blacklistReasons.push(`audio codec "${variantAudioDetails.type}" !== "${audioDetails.type}"`); } } if (blacklistReasons.length) { + variant.excludeUntil = Infinity; this.logger_(`blacklisting ${variant.id}: ${blacklistReasons.join(' && ')}`); } }); diff --git a/src/media-segment-request.js b/src/media-segment-request.js index 009054013..749643ccc 100644 --- a/src/media-segment-request.js +++ b/src/media-segment-request.js @@ -8,7 +8,7 @@ import { segmentXhrHeaders } from './xhr'; import { detectContainerForBytes, isLikelyFmp4MediaSegment -} from '@videojs/vhs-utils/dist/containers'; +} from '@videojs/vhs-utils/es/containers'; export const REQUEST_ERRORS = { FAILURE: 2, diff --git a/src/resolve-url.js b/src/resolve-url.js index 91672eb12..901eb62d5 100644 --- a/src/resolve-url.js +++ b/src/resolve-url.js @@ -2,7 +2,7 @@ * @file resolve-url.js - Handling how URLs are resolved and manipulated */ -import _resolveUrl from '@videojs/vhs-utils/dist/resolve-url.js'; +import _resolveUrl from '@videojs/vhs-utils/es/resolve-url.js'; export const resolveUrl = _resolveUrl; diff --git a/src/source-updater.js b/src/source-updater.js index 68a8a175a..ec88f383c 100644 --- a/src/source-updater.js +++ b/src/source-updater.js @@ -5,7 +5,7 @@ import videojs from 'video.js'; import logger from './util/logger'; import noop from './util/noop'; import { bufferIntersection } from './ranges.js'; -import {getMimeForCodec} from '@videojs/vhs-utils/dist/codecs.js'; +import {getMimeForCodec} from '@videojs/vhs-utils/es/codecs.js'; import window from 'global/window'; import toTitleCase from './util/to-title-case.js'; diff --git a/src/util/codecs.js b/src/util/codecs.js index 2b2cdb5c6..103d3e2ea 100644 --- a/src/util/codecs.js +++ b/src/util/codecs.js @@ -7,7 +7,10 @@ import { translateLegacyCodec, parseCodecs, codecsFromDefault -} from '@videojs/vhs-utils/dist/codecs.js'; +} from '@videojs/vhs-utils/es/codecs.js'; +import logger from './logger.js'; + +const logFn = logger('CodecUtils'); /** * Returns a set of codec strings parsed from the playlist or the default @@ -55,6 +58,41 @@ export const isMuxed = (master, media) => { return false; }; +export const unwrapCodecList = function(codecList) { + const codecs = {}; + + codecList.forEach(({mediaType, type, details}) => { + codecs[mediaType] = codecs[mediaType] || []; + codecs[mediaType].push(translateLegacyCodec(`${type}${details}`)); + }); + + Object.keys(codecs).forEach(function(mediaType) { + if (codecs[mediaType].length > 1) { + logFn(`multiple ${mediaType} codecs found as attributes: ${codecs[mediaType].join(', ')}. Setting playlist codecs to null so that we wait for mux.js to probe segments for real codecs.`); + codecs[mediaType] = null; + return; + } + + codecs[mediaType] = codecs[mediaType][0]; + }); + + return codecs; +}; + +export const codecCount = function(codecObj) { + let count = 0; + + if (codecObj.audio) { + count++; + } + + if (codecObj.video) { + count++; + } + + return count; +}; + /** * Calculates the codec strings for a working configuration of * SourceBuffers to play variant streams in a master playlist. If @@ -69,7 +107,7 @@ export const isMuxed = (master, media) => { */ export const codecsForPlaylist = function(master, media) { const mediaAttributes = media.attributes || {}; - const codecInfo = getCodecs(media) || {}; + const codecInfo = unwrapCodecList(getCodecs(media) || []); // HLS with multiple-audio tracks must always get an audio codec. // Put another way, there is no way to have a video-only multiple-audio HLS! @@ -78,33 +116,13 @@ export const codecsForPlaylist = function(master, media) { // It is possible for codecs to be specified on the audio media group playlist but // not on the rendition playlist. This is mostly the case for DASH, where audio and // video are always separate (and separately specified). - const defaultCodecs = codecsFromDefault(master, mediaAttributes.AUDIO); + const defaultCodecs = unwrapCodecList(codecsFromDefault(master, mediaAttributes.AUDIO) || []); - if (defaultCodecs) { + if (defaultCodecs.audio) { codecInfo.audio = defaultCodecs.audio; } - } } - const codecs = {}; - - if (codecInfo.video) { - codecs.video = translateLegacyCodec(`${codecInfo.video.type}${codecInfo.video.details}`); - } - - if (codecInfo.audio) { - codecs.audio = translateLegacyCodec(`${codecInfo.audio.type}${codecInfo.audio.details}`); - } - - if (codecInfo.text) { - codecs.text = codecInfo.text.type; - } - - if (codecInfo.unknown) { - codecs.unknown = codecInfo.unknown; - } - - return codecs; + return codecInfo; }; - diff --git a/src/util/container-request.js b/src/util/container-request.js index da7064a22..8bd571936 100644 --- a/src/util/container-request.js +++ b/src/util/container-request.js @@ -1,5 +1,6 @@ -import {detectContainerForBytes, getId3Offset} from '@videojs/vhs-utils/dist/containers'; -import {stringToBytes, concatTypedArrays} from '@videojs/vhs-utils/dist/byte-helpers'; +import {getId3Offset} from '@videojs/vhs-utils/es/id3-helpers'; +import {detectContainerForBytes} from '@videojs/vhs-utils/es/containers'; +import {stringToBytes, concatTypedArrays} from '@videojs/vhs-utils/es/byte-helpers'; import {callbackWrapper} from '../xhr'; // calls back if the request is readyState DONE diff --git a/src/videojs-http-streaming.js b/src/videojs-http-streaming.js index 355d548a8..fa656f1a4 100644 --- a/src/videojs-http-streaming.js +++ b/src/videojs-http-streaming.js @@ -9,7 +9,7 @@ import window from 'global/window'; import PlaylistLoader from './playlist-loader'; import Playlist from './playlist'; import xhrFactory from './xhr'; -import { simpleTypeFromSourceType } from '@videojs/vhs-utils/dist/media-types.js'; +import { simpleTypeFromSourceType } from '@videojs/vhs-utils/es/media-types.js'; import * as utils from './bin-utils'; import { getProgramTime, @@ -30,7 +30,7 @@ import { comparePlaylistBandwidth, comparePlaylistResolution } from './playlist-selectors.js'; -import {isAudioCodec, isVideoCodec, browserSupportsCodec} from '@videojs/vhs-utils/dist/codecs.js'; +import {isAudioCodec, isVideoCodec, browserSupportsCodec} from '@videojs/vhs-utils/es/codecs.js'; import logger from './util/logger'; import {SAFE_TIME_DELTA} from './ranges'; diff --git a/test/master-playlist-controller.test.js b/test/master-playlist-controller.test.js index 7197a99dc..0a742e35d 100644 --- a/test/master-playlist-controller.test.js +++ b/test/master-playlist-controller.test.js @@ -14,7 +14,7 @@ import { import { DEFAULT_AUDIO_CODEC, DEFAULT_VIDEO_CODEC -} from '@videojs/vhs-utils/dist/codecs.js'; +} from '@videojs/vhs-utils/es/codecs.js'; import manifests from 'create-test-data!manifests'; import { MasterPlaylistController @@ -49,10 +49,12 @@ import { const sharedHooks = { beforeEach(assert) { + this.oldTypeSupported = window.MediaSource.isTypeSupported; + this.oldChangeType = window.SourceBuffer.prototype.changeType; + this.env = useFakeEnvironment(assert); this.clock = this.env.clock; this.requests = this.env.requests; - this.oldTypeSupported = window.MediaSource.isTypeSupported; this.mse = useFakeMediaSource(); if (!videojs.browser.IE_VERSION) { @@ -60,8 +62,6 @@ const sharedHooks = { window.devicePixelRatio = 1; } - this.oldChangeType = window.SourceBuffer.prototype.changeType; - // force the HLS tech to run this.origSupportsNativeHls = videojs.Vhs.supportsNativeHls; videojs.Vhs.supportsNativeHls = false; @@ -90,6 +90,8 @@ const sharedHooks = { this.masterPlaylistController.mainSegmentLoader_.addSegmentMetadataCue_ = () => {}; }, afterEach() { + window.MediaSource.isTypeSupported = this.oldTypeSupported; + window.SourceBuffer.prototype.changeType = this.oldChangeType; this.env.restore(); this.mse.restore(); videojs.Vhs.supportsNativeHls = this.origSupportsNativeHls; @@ -99,8 +101,6 @@ const sharedHooks = { } videojs.browser = this.oldBrowser; this.player.dispose(); - window.MediaSource.isTypeSupported = this.oldTypeSupported; - window.SourceBuffer.prototype.changeType = this.oldChangeType; } }; @@ -1275,6 +1275,7 @@ QUnit.test('blacklists switching from audio-only playlists to video+audio', func openMediaSource(this.player, this.clock); this.player.tech_.vhs.bandwidth = 1; + const mpc = this.masterPlaylistController; // master this.requests.shift().respond( @@ -1282,14 +1283,13 @@ QUnit.test('blacklists switching from audio-only playlists to video+audio', func '#EXTM3U\n' + '#EXT-X-STREAM-INF:BANDWIDTH=1,CODECS="mp4a.40.2"\n' + 'media.m3u8\n' + - '#EXT-X-STREAM-INF:BANDWIDTH=10,RESOLUTION=1x1\n' + + '#EXT-X-STREAM-INF:BANDWIDTH=10,RESOLUTION=1x1,CODECS="avc1.4d400d,mp4a.40.2"\n' + 'media1.m3u8\n' ); // media1 this.standardXHRResponse(this.requests.shift()); - const mpc = this.masterPlaylistController; let debugLogs = []; mpc.logger_ = (...logs) => { diff --git a/test/test-helpers.js b/test/test-helpers.js index 3b1044f01..67ec13cbd 100644 --- a/test/test-helpers.js +++ b/test/test-helpers.js @@ -6,8 +6,8 @@ import testDataManifests from 'create-test-data!manifests'; import xhrFactory from '../src/xhr'; import window from 'global/window'; import { muxed as muxedSegment } from 'create-test-data!segments'; -import {bytesToString, isTypedArray} from '@videojs/vhs-utils/dist/byte-helpers'; -import {isLikelyFmp4MediaSegment} from '@videojs/vhs-utils/dist/containers'; +import {bytesToString, isTypedArray} from '@videojs/vhs-utils/es/byte-helpers'; +import {isLikelyFmp4MediaSegment} from '@videojs/vhs-utils/es/containers'; // return an absolute version of a page-relative URL export const absoluteUrl = function(relativeUrl) { diff --git a/test/videojs-http-streaming.test.js b/test/videojs-http-streaming.test.js index 079d73b15..d20e48596 100644 --- a/test/videojs-http-streaming.test.js +++ b/test/videojs-http-streaming.test.js @@ -1805,6 +1805,9 @@ QUnit.test('blacklists incompatible playlists by codec, without codec switching' }); QUnit.test('does not blacklist incompatible codecs with codec switching', function(assert) { + const oldIsTypeSupported = window.MediaSource.isTypeSupported; + + window.MediaSource.isTypeSupported = (t) => (/avc1|mp4a/).test(t); this.player.src({ src: 'manifest/master.m3u8', type: 'application/vnd.apple.mpegurl' @@ -1857,11 +1860,12 @@ QUnit.test('does not blacklist incompatible codecs with codec switching', functi assert.strictEqual(playlists.length, 7, 'six playlists total'); assert.strictEqual(typeof playlists[0].excludeUntil, 'undefined', 'did not blacklist first playlist'); assert.strictEqual(typeof playlists[1].excludeUntil, 'undefined', 'did not blacklist second playlist'); - assert.strictEqual(typeof playlists[2].excludeUntil, 'undefined', 'blacklisted incompatible audio playlist'); - assert.strictEqual(typeof playlists[3].excludeUntil, 'undefined', 'blacklisted incompatible video playlist'); + assert.strictEqual(playlists[2].excludeUntil, Infinity, 'blacklisted incompatible audio playlist'); + assert.strictEqual(playlists[3].excludeUntil, Infinity, 'blacklisted incompatible video playlist'); assert.strictEqual(playlists[4].excludeUntil, Infinity, 'blacklisted audio only playlist'); assert.strictEqual(playlists[5].excludeUntil, Infinity, 'blacklisted video only playlist'); assert.strictEqual(typeof playlists[6].excludeUntil, 'undefined', 'did not blacklist seventh playlist'); + window.MediaSource.isTypeSupported = oldIsTypeSupported; }); QUnit.test('blacklists fmp4 playlists by browser support', function(assert) { @@ -1940,6 +1944,9 @@ QUnit.test('blacklists fmp4 playlists by browser support', function(assert) { }); QUnit.test('blacklists ts playlists by muxer support', function(assert) { + const oldIsTypeSupported = window.MediaSource.isTypeSupported; + + window.MediaSource.isTypeSupported = (t) => true; this.player.src({ src: 'manifest/master.m3u8', type: 'application/vnd.apple.mpegurl' @@ -2004,6 +2011,7 @@ QUnit.test('blacklists ts playlists by muxer support', function(assert) { `Internal problem encountered with playlist ${playlists[1].id}. muxer does not support codec(s): "ac-3". Switching to playlist ${playlists[2].id}.` ], 'debug log as expected'); + window.MediaSource.isTypeSupported = oldIsTypeSupported; }); QUnit.test('cancels outstanding XHRs when seeking', function(assert) { From ab5b4dc88aeabdaa1654a039477620447571bf1d Mon Sep 17 00:00:00 2001 From: Gary Katsevman Date: Wed, 20 Jan 2021 12:25:07 -0500 Subject: [PATCH 059/399] feat: add flag to turn off 708 captions (#1047) Add parse708captions as a VHS option to turn off 708 captions. --- README.md | 8 ++++++++ package-lock.json | 9 ++++++--- package.json | 2 +- src/master-playlist-controller.js | 1 + src/segment-loader.js | 2 ++ 5 files changed, 18 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 66742f91d..07696d0e9 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,7 @@ Video.js Compatibility: 6.0, 7.0 - [withCredentials](#withcredentials) - [handleManifestRedirects](#handlemanifestredirects) - [useCueTags](#usecuetags) + - [parse708captions](#parse708captions) - [overrideNative](#overridenative) - [blacklistDuration](#blacklistduration) - [bandwidth](#bandwidth) @@ -318,6 +319,13 @@ cuesTrack.addEventListener('cuechange', function() { }); ``` +##### parse708captions +* Type: `boolean` +* Default: `true` +* can be used as an initialization option + +When set to `false`, 708 captions in the stream are not parsed and will not show up in text track lists or the captions menu. + ##### overrideNative * Type: `boolean` * can be used as an initialization option diff --git a/package-lock.json b/package-lock.json index 2228c433e..bd319ce94 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6481,9 +6481,12 @@ "dev": true }, "mux.js": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/mux.js/-/mux.js-5.8.0.tgz", - "integrity": "sha512-v56I2YPyCq1bVbXW7vcuvQs8iHrDy7AeXsZyG1kxCxBUqUjZD0Xq/cU1wrd5dy9YTxRpvw37aTQ4ILwi40GXiw==" + "version": "5.9.1", + "resolved": "https://registry.npmjs.org/mux.js/-/mux.js-5.9.1.tgz", + "integrity": "sha512-EWDCIemLUoTriIQpEHEfKO8hldujpiBYIqC6ilsMaNbd+1hhGoh/w1MZIhP5wkq+tkS+HfnrnNtyfamyXWfnPg==", + "requires": { + "@babel/runtime": "^7.11.2" + } }, "natural-compare": { "version": "1.4.0", diff --git a/package.json b/package.json index db55e15f4..8a3128376 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "global": "^4.4.0", "m3u8-parser": "4.5.2", "mpd-parser": "0.15.2", - "mux.js": "5.8.0", + "mux.js": "5.9.1", "video.js": "^6 || ^7" }, "devDependencies": { diff --git a/src/master-playlist-controller.js b/src/master-playlist-controller.js index 971e6454d..58370d740 100644 --- a/src/master-playlist-controller.js +++ b/src/master-playlist-controller.js @@ -209,6 +209,7 @@ export class MasterPlaylistController extends videojs.EventTarget { const segmentLoaderSettings = { vhs: this.vhs_, + parse708captions: options.parse708captions, mediaSource: this.mediaSource, currentTime: this.tech_.currentTime.bind(this.tech_), seekable: () => this.seekable(), diff --git a/src/segment-loader.js b/src/segment-loader.js index ac689dad8..ce06f688c 100644 --- a/src/segment-loader.js +++ b/src/segment-loader.js @@ -475,6 +475,7 @@ export default class SegmentLoader extends videojs.EventTarget { this.handlePartialData_ = settings.handlePartialData; this.timelineChangeController_ = settings.timelineChangeController; this.shouldSaveSegmentTimingInfo_ = true; + this.parse708captions_ = settings.parse708captions; // private instance variables this.checkBufferTimeout_ = null; @@ -595,6 +596,7 @@ export default class SegmentLoader extends videojs.EventTarget { transmuxer.postMessage({ action: 'init', options: { + parse708captions: this.parse708captions_, remux: false, alignGopsAtEnd: this.safeAppend_, keepOriginalTimestamps: true, From 25c7f644d39a6511897b165af51cf179160101f0 Mon Sep 17 00:00:00 2001 From: Gary Katsevman Date: Wed, 20 Jan 2021 12:57:41 -0500 Subject: [PATCH 060/399] test: don't show QUnit UI in regular test runs (#1044) Also, switch to progress reporter by default --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index bd319ce94..38889f589 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7172,9 +7172,9 @@ "dev": true }, "qunit": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/qunit/-/qunit-2.12.0.tgz", - "integrity": "sha512-Lu3tbKziVzXTfseoEtTiiSAbSPB6SGU4Emc2uo8n+fbsXuRCLzfqPwJfAVJwKu9NdukX1V/L0qWf2UvmPX+QeA==", + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/qunit/-/qunit-2.13.0.tgz", + "integrity": "sha512-RvJquyNKbMSn5Qo28S2wKWxHl1Ku8m0zFLTKsXfq/WZkyM+b28gpEs6YkKN1fOCV4S+979+GnevD0FRgQayo3Q==", "dev": true, "requires": { "commander": "6.2.0", @@ -9073,9 +9073,9 @@ "integrity": "sha512-g8vHMKK2/JGorSfqAZQUmYYNnXmfec4MLhwtEFS+mMs2IDY398GLysy6BH6K+aS1KMNu/xWZ8Sue/X/mdQPliA==" }, "videojs-generate-karma-config": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/videojs-generate-karma-config/-/videojs-generate-karma-config-7.0.0.tgz", - "integrity": "sha512-nC3SZeVx3OtNiCtdjkC+GT4imfuDhGhpaxr/sfNJv2QmvzKhAhGkySRrh01+SLF85e+yAaCeitDYkXP5QlqtJg==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/videojs-generate-karma-config/-/videojs-generate-karma-config-7.1.0.tgz", + "integrity": "sha512-j3ed19T+Aidjho+KmzMNKc0k8ySXW45vX+ON3YWR0HOxRFF5VATokIyZv3z0Z/aR5ImoiQAANDs8/zuRafC/mw==", "dev": true, "requires": { "is-ci": "^2.0.0", @@ -9089,7 +9089,7 @@ "karma-safari-applescript-launcher": "~0.1.0", "karma-static-server": "^1.0.0", "karma-teamcity-reporter": "^1.1.0", - "qunit": "~2.12.0" + "qunit": "~2.13.0" } }, "videojs-generate-rollup-config": { diff --git a/package.json b/package.json index 8a3128376..99374578b 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,7 @@ "url-toolkit": "^2.2.1", "videojs-contrib-eme": "^3.8.0", "videojs-contrib-quality-levels": "^2.0.4", - "videojs-generate-karma-config": "~7.0.0", + "videojs-generate-karma-config": "^7.1.0", "videojs-generate-rollup-config": "~6.1.0", "videojs-generator-verify": "~3.0.1", "videojs-http-source-selector": "^1.1.6", From caa8ff28f35e326df852b969a6bbb1c892ff08e7 Mon Sep 17 00:00:00 2001 From: Gary Katsevman Date: Wed, 20 Jan 2021 14:53:15 -0500 Subject: [PATCH 061/399] 2.5.0 --- CHANGELOG.md | 16 ++++++++++++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f35bd7e87..2f190c3e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,19 @@ + +# [2.5.0](https://github.com/videojs/http-streaming/compare/v2.4.2...v2.5.0) (2021-01-20) + +### Features + +* add flag to turn off 708 captions ([#1047](https://github.com/videojs/http-streaming/issues/1047)) ([ab5b4dc](https://github.com/videojs/http-streaming/commit/ab5b4dc)) + +### Chores + +* update [@videojs](https://github.com/videojs)/vhs-utils to v3.0.0 ([#1036](https://github.com/videojs/http-streaming/issues/1036)) ([b072c93](https://github.com/videojs/http-streaming/commit/b072c93)) + +### Tests + +* clear segment transmuxer in media segment request tests ([#1043](https://github.com/videojs/http-streaming/issues/1043)) ([83057a8](https://github.com/videojs/http-streaming/commit/83057a8)) +* don't show QUnit UI in regular test runs ([#1044](https://github.com/videojs/http-streaming/issues/1044)) ([25c7f64](https://github.com/videojs/http-streaming/commit/25c7f64)) + ## [2.4.2](https://github.com/videojs/http-streaming/compare/v2.4.1...v2.4.2) (2021-01-07) diff --git a/package-lock.json b/package-lock.json index 38889f589..7c628fd4a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@videojs/http-streaming", - "version": "2.4.2", + "version": "2.5.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 99374578b..24d192f72 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@videojs/http-streaming", - "version": "2.4.2", + "version": "2.5.0", "description": "Play back HLS and DASH with Video.js, even where it's not natively supported", "main": "dist/videojs-http-streaming.cjs.js", "module": "dist/videojs-http-streaming.es.js", From 0e8bd4beb8009f9682ab325171c28ec97e38f527 Mon Sep 17 00:00:00 2001 From: Brandon Casey <2381475+brandonocasey@users.noreply.github.com> Date: Thu, 21 Jan 2021 11:39:33 -0500 Subject: [PATCH 062/399] feat: expose m3u8-parser logging in debug log (#1048) --- src/manifest.js | 9 +++++++++ src/playlist-loader.js | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/src/manifest.js b/src/manifest.js index 3d5423756..532d3e02a 100644 --- a/src/manifest.js +++ b/src/manifest.js @@ -22,12 +22,21 @@ export const createPlaylistID = (index, uri) => { * The manifest object */ export const parseManifest = ({ + onwarn, + oninfo, manifestString, customTagParsers = [], customTagMappers = [] }) => { const parser = new M3u8Parser(); + if (onwarn) { + parser.on('warn', onwarn); + } + if (oninfo) { + parser.on('info', oninfo); + } + customTagParsers.forEach(customParser => parser.addParser(customParser)); customTagMappers.forEach(mapper => parser.addTagMapper(mapper)); diff --git a/src/playlist-loader.js b/src/playlist-loader.js index 275985496..3ad659588 100644 --- a/src/playlist-loader.js +++ b/src/playlist-loader.js @@ -8,6 +8,7 @@ import { resolveUrl, resolveManifestRedirect } from './resolve-url'; import videojs from 'video.js'; import window from 'global/window'; +import logger from './util/logger'; import { parseManifest, addPropertiesToMaster, @@ -157,6 +158,7 @@ export default class PlaylistLoader extends EventTarget { if (!src) { throw new Error('A non-empty playlist URL or object is required'); } + this.logger_ = logger('PlaylistLoader'); const { withCredentials = false, handleManifestRedirects = false } = options; @@ -246,6 +248,8 @@ export default class PlaylistLoader extends EventTarget { this.state = 'HAVE_METADATA'; const playlist = playlistObject || parseManifest({ + onwarn: ({message}) => this.logger_(`m3u8-parser warn for ${id}: ${message}`), + oninfo: ({message}) => this.logger_(`m3u8-parser info for ${id}: ${message}`), manifestString: playlistString, customTagParsers: this.customTagParsers, customTagMappers: this.customTagMappers From 30f9b144071dcb06337c982b96416e9d17ceb051 Mon Sep 17 00:00:00 2001 From: Gary Katsevman Date: Thu, 10 Sep 2020 08:13:43 -0400 Subject: [PATCH 063/399] docs: sample-aes encryption isn't currently supported (#923) --- docs/supported-features.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/supported-features.md b/docs/supported-features.md index 7f8d293b1..7a24f9f56 100644 --- a/docs/supported-features.md +++ b/docs/supported-features.md @@ -63,7 +63,7 @@ not meant serve as an exhaustive list. * Video only (non DRM) * In-manifest [WebVTT] subtitles are automatically translated into standard HTML5 subtitle tracks -* [AES-128] and SAMPLE-AES segment encryption +* [AES-128] segment encryption ## Notable Missing Features @@ -126,6 +126,7 @@ not yet been implemented. VHS currently supports everything in the * Use of AVERAGE-BANDWIDTH in [EXT-X-STREAM-INF] (value parsed but not used) * Use of FRAME-RATE in [EXT-X-STREAM-INF] (value parsed but not used) * Use of HDCP-LEVEL in [EXT-X-STREAM-INF] +* SAMPLE-AES segment encryption In the event of encoding changes within a playlist (see https://tools.ietf.org/html/draft-pantos-http-live-streaming-23#section-6.3.3), the From b34a77063745eebd30bba4194f44ff2344cae63e Mon Sep 17 00:00:00 2001 From: Brandon Casey <2381475+brandonocasey@users.noreply.github.com> Date: Fri, 22 Jan 2021 11:08:54 -0500 Subject: [PATCH 064/399] chore: add legacy avc source (#1050) --- scripts/sources.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/scripts/sources.json b/scripts/sources.json index 5b75abbe6..546a7f11a 100644 --- a/scripts/sources.json +++ b/scripts/sources.json @@ -339,5 +339,11 @@ "uri": "https://d2zihajmogu5jn.cloudfront.net/ts-one-valid-many-invalid-codecs/master.m3u8", "mimetype": "application/x-mpegurl", "features": [] + }, + { + "name": "Legacy AVC Codec", + "uri": "https://d2zihajmogu5jn.cloudfront.net/legacy-avc-codec/master.m3u8", + "mimetype": "application/x-mpegurl", + "features": [] } ] From f0732afc4f42185fe38d90a51066981fd6dd4c01 Mon Sep 17 00:00:00 2001 From: Brandon Casey <2381475+brandonocasey@users.noreply.github.com> Date: Tue, 2 Feb 2021 12:16:34 -0500 Subject: [PATCH 065/399] chore: better worker build and synchronous web worker (#1033) --- index.html | 4 ++ package-lock.json | 15 ++++--- package.json | 2 +- scripts/index-demo-page.js | 18 ++++++-- scripts/rollup.config.js | 68 +++++++++++++++++------------- src/decrypter-worker.js | 67 +++++++++++++---------------- src/master-playlist-controller.js | 2 +- src/segment-loader.js | 2 +- src/transmuxer-worker.js | 28 ++++++------ test/loader-common.js | 2 +- test/media-segment-request.test.js | 5 +-- test/segment-transmuxer.test.js | 2 +- test/transmuxer-worker.test.js | 2 +- 13 files changed, 117 insertions(+), 100 deletions(-) diff --git a/index.html b/index.html index 03497569a..155407105 100644 --- a/index.html +++ b/index.html @@ -53,6 +53,10 @@

Options

Minified VHS (reloads player) + + + + - + +