hls.js 1.5.12-0.canary.10340 → 1.5.12-0.canary.10341

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/hls.light.js CHANGED
@@ -434,14 +434,90 @@
434
434
  return ErrorDetails;
435
435
  }({});
436
436
 
437
+ var Logger = function Logger(label, logger) {
438
+ this.trace = void 0;
439
+ this.debug = void 0;
440
+ this.log = void 0;
441
+ this.warn = void 0;
442
+ this.info = void 0;
443
+ this.error = void 0;
444
+ var lb = "[" + label + "]:";
445
+ this.trace = noop;
446
+ this.debug = logger.debug.bind(null, lb);
447
+ this.log = logger.log.bind(null, lb);
448
+ this.warn = logger.warn.bind(null, lb);
449
+ this.info = logger.info.bind(null, lb);
450
+ this.error = logger.error.bind(null, lb);
451
+ };
452
+ var noop = function noop() {};
453
+ var fakeLogger = {
454
+ trace: noop,
455
+ debug: noop,
456
+ log: noop,
457
+ warn: noop,
458
+ info: noop,
459
+ error: noop
460
+ };
461
+ function createLogger() {
462
+ return _extends({}, fakeLogger);
463
+ }
464
+
465
+ // let lastCallTime;
466
+ // function formatMsgWithTimeInfo(type, msg) {
467
+ // const now = Date.now();
468
+ // const diff = lastCallTime ? '+' + (now - lastCallTime) : '0';
469
+ // lastCallTime = now;
470
+ // msg = (new Date(now)).toISOString() + ' | [' + type + '] > ' + msg + ' ( ' + diff + ' ms )';
471
+ // return msg;
472
+ // }
473
+
474
+ function consolePrintFn(type, id) {
475
+ var func = self.console[type];
476
+ return func ? func.bind(self.console, ('') + "[" + type + "] >") : noop;
477
+ }
478
+ function getLoggerFn(key, debugConfig, id) {
479
+ return debugConfig[key] ? debugConfig[key].bind(debugConfig) : consolePrintFn(key);
480
+ }
481
+ var exportedLogger = createLogger();
482
+ function enableLogs(debugConfig, context, id) {
483
+ // check that console is available
484
+ var newLogger = createLogger();
485
+ if (typeof console === 'object' && debugConfig === true || typeof debugConfig === 'object') {
486
+ var keys = [
487
+ // Remove out from list here to hard-disable a log-level
488
+ // 'trace',
489
+ 'debug', 'log', 'info', 'warn', 'error'];
490
+ keys.forEach(function (key) {
491
+ newLogger[key] = getLoggerFn(key, debugConfig);
492
+ });
493
+ // Some browsers don't allow to use bind on console object anyway
494
+ // fallback to default if needed
495
+ try {
496
+ newLogger.log("Debug logs enabled for \"" + context + "\" in hls.js version " + "1.5.12-0.canary.10341");
497
+ } catch (e) {
498
+ /* log fn threw an exception. All logger methods are no-ops. */
499
+ return createLogger();
500
+ }
501
+ // global exported logger uses the same functions as new logger without `id`
502
+ keys.forEach(function (key) {
503
+ exportedLogger[key] = getLoggerFn(key, debugConfig);
504
+ });
505
+ } else {
506
+ // Reset global exported logger
507
+ _extends(exportedLogger, newLogger);
508
+ }
509
+ return newLogger;
510
+ }
511
+ var logger = exportedLogger;
512
+
437
513
  var DECIMAL_RESOLUTION_REGEX = /^(\d+)x(\d+)$/;
438
514
  var ATTR_LIST_REGEX = /(.+?)=(".*?"|.*?)(?:,|$)/g;
439
515
 
440
516
  // adapted from https://github.com/kanongil/node-m3u8parse/blob/master/attrlist.js
441
517
  var AttrList = /*#__PURE__*/function () {
442
- function AttrList(attrs) {
518
+ function AttrList(attrs, parsed) {
443
519
  if (typeof attrs === 'string') {
444
- attrs = AttrList.parseAttrList(attrs);
520
+ attrs = AttrList.parseAttrList(attrs, parsed);
445
521
  }
446
522
  _extends(this, attrs);
447
523
  }
@@ -483,6 +559,13 @@
483
559
  _proto.enumeratedString = function enumeratedString(attrName) {
484
560
  return this[attrName];
485
561
  };
562
+ _proto.enumeratedStringList = function enumeratedStringList(attrName, dict) {
563
+ var attrValue = this[attrName];
564
+ return (attrValue ? attrValue.split(/[ ,]+/) : []).reduce(function (result, identifier) {
565
+ result[identifier.toLowerCase()] = true;
566
+ return result;
567
+ }, dict);
568
+ };
486
569
  _proto.bool = function bool(attrName) {
487
570
  return this[attrName] === 'YES';
488
571
  };
@@ -496,17 +579,71 @@
496
579
  height: parseInt(res[2], 10)
497
580
  };
498
581
  };
499
- AttrList.parseAttrList = function parseAttrList(input) {
582
+ AttrList.parseAttrList = function parseAttrList(input, parsed) {
500
583
  var match;
501
584
  var attrs = {};
502
585
  var quote = '"';
503
586
  ATTR_LIST_REGEX.lastIndex = 0;
504
587
  while ((match = ATTR_LIST_REGEX.exec(input)) !== null) {
588
+ var name = match[1].trim();
505
589
  var value = match[2];
506
- if (value.indexOf(quote) === 0 && value.lastIndexOf(quote) === value.length - 1) {
590
+ var quotedString = value.indexOf(quote) === 0 && value.lastIndexOf(quote) === value.length - 1;
591
+ var hexadecimalSequence = false;
592
+ if (quotedString) {
507
593
  value = value.slice(1, -1);
594
+ } else {
595
+ switch (name) {
596
+ case 'IV':
597
+ case 'SCTE35-CMD':
598
+ case 'SCTE35-IN':
599
+ case 'SCTE35-OUT':
600
+ hexadecimalSequence = true;
601
+ }
602
+ }
603
+ if (parsed && (quotedString || hexadecimalSequence)) ; else if (!hexadecimalSequence && !quotedString) {
604
+ switch (name) {
605
+ case 'CLOSED-CAPTIONS':
606
+ if (value === 'NONE') {
607
+ break;
608
+ }
609
+ // falls through
610
+ case 'ALLOWED-CPC':
611
+ case 'CLASS':
612
+ case 'ASSOC-LANGUAGE':
613
+ case 'AUDIO':
614
+ case 'BYTERANGE':
615
+ case 'CHANNELS':
616
+ case 'CHARACTERISTICS':
617
+ case 'CODECS':
618
+ case 'DATA-ID':
619
+ case 'END-DATE':
620
+ case 'GROUP-ID':
621
+ case 'ID':
622
+ case 'IMPORT':
623
+ case 'INSTREAM-ID':
624
+ case 'KEYFORMAT':
625
+ case 'KEYFORMATVERSIONS':
626
+ case 'LANGUAGE':
627
+ case 'NAME':
628
+ case 'PATHWAY-ID':
629
+ case 'QUERYPARAM':
630
+ case 'RECENTLY-REMOVED-DATERANGES':
631
+ case 'SERVER-URI':
632
+ case 'STABLE-RENDITION-ID':
633
+ case 'STABLE-VARIANT-ID':
634
+ case 'START-DATE':
635
+ case 'SUBTITLES':
636
+ case 'SUPPLEMENTAL-CODECS':
637
+ case 'URI':
638
+ case 'VALUE':
639
+ case 'VIDEO':
640
+ case 'X-ASSET-LIST':
641
+ case 'X-ASSET-URI':
642
+ // Since we are not checking tag:attribute combination, just warn rather than ignoring attribute
643
+ logger.warn(input + ": attribute " + name + " is missing quotes");
644
+ // continue;
645
+ }
508
646
  }
509
- var name = match[1].trim();
510
647
  attrs[name] = value;
511
648
  }
512
649
  return attrs;
@@ -521,96 +658,30 @@
521
658
  }]);
522
659
  }();
523
660
 
524
- var Logger = function Logger(label, logger) {
525
- this.trace = void 0;
526
- this.debug = void 0;
527
- this.log = void 0;
528
- this.warn = void 0;
529
- this.info = void 0;
530
- this.error = void 0;
531
- var lb = "[" + label + "]:";
532
- this.trace = noop;
533
- this.debug = logger.debug.bind(null, lb);
534
- this.log = logger.log.bind(null, lb);
535
- this.warn = logger.warn.bind(null, lb);
536
- this.info = logger.info.bind(null, lb);
537
- this.error = logger.error.bind(null, lb);
538
- };
539
- var noop = function noop() {};
540
- var fakeLogger = {
541
- trace: noop,
542
- debug: noop,
543
- log: noop,
544
- warn: noop,
545
- info: noop,
546
- error: noop
547
- };
548
- function createLogger() {
549
- return _extends({}, fakeLogger);
550
- }
551
-
552
- // let lastCallTime;
553
- // function formatMsgWithTimeInfo(type, msg) {
554
- // const now = Date.now();
555
- // const diff = lastCallTime ? '+' + (now - lastCallTime) : '0';
556
- // lastCallTime = now;
557
- // msg = (new Date(now)).toISOString() + ' | [' + type + '] > ' + msg + ' ( ' + diff + ' ms )';
558
- // return msg;
559
- // }
560
-
561
- function consolePrintFn(type, id) {
562
- var func = self.console[type];
563
- return func ? func.bind(self.console, ('') + "[" + type + "] >") : noop;
564
- }
565
- function getLoggerFn(key, debugConfig, id) {
566
- return debugConfig[key] ? debugConfig[key].bind(debugConfig) : consolePrintFn(key);
567
- }
568
- var exportedLogger = createLogger();
569
- function enableLogs(debugConfig, context, id) {
570
- // check that console is available
571
- var newLogger = createLogger();
572
- if (typeof console === 'object' && debugConfig === true || typeof debugConfig === 'object') {
573
- var keys = [
574
- // Remove out from list here to hard-disable a log-level
575
- // 'trace',
576
- 'debug', 'log', 'info', 'warn', 'error'];
577
- keys.forEach(function (key) {
578
- newLogger[key] = getLoggerFn(key, debugConfig);
579
- });
580
- // Some browsers don't allow to use bind on console object anyway
581
- // fallback to default if needed
582
- try {
583
- newLogger.log("Debug logs enabled for \"" + context + "\" in hls.js version " + "1.5.12-0.canary.10340");
584
- } catch (e) {
585
- /* log fn threw an exception. All logger methods are no-ops. */
586
- return createLogger();
587
- }
588
- // global exported logger uses the same functions as new logger without `id`
589
- keys.forEach(function (key) {
590
- exportedLogger[key] = getLoggerFn(key, debugConfig);
591
- });
592
- } else {
593
- // Reset global exported logger
594
- _extends(exportedLogger, newLogger);
595
- }
596
- return newLogger;
597
- }
598
- var logger = exportedLogger;
599
-
600
661
  // Avoid exporting const enum so that these values can be inlined
601
662
 
663
+ var CLASS_INTERSTITIAL = 'com.apple.hls.interstitial';
602
664
  function isDateRangeCueAttribute(attrName) {
603
- return attrName !== "ID" && attrName !== "CLASS" && attrName !== "START-DATE" && attrName !== "DURATION" && attrName !== "END-DATE" && attrName !== "END-ON-NEXT";
665
+ return attrName !== "ID" && attrName !== "CLASS" && attrName !== "CUE" && attrName !== "START-DATE" && attrName !== "DURATION" && attrName !== "END-DATE" && attrName !== "END-ON-NEXT";
604
666
  }
605
667
  function isSCTE35Attribute(attrName) {
606
- return attrName === "SCTE35-OUT" || attrName === "SCTE35-IN";
668
+ return attrName === "SCTE35-OUT" || attrName === "SCTE35-IN" || attrName === "SCTE35-CMD";
607
669
  }
608
670
  var DateRange = /*#__PURE__*/function () {
609
- function DateRange(dateRangeAttr, dateRangeWithSameId) {
671
+ function DateRange(dateRangeAttr, dateRangeWithSameId, tagCount) {
672
+ var _dateRangeWithSameId$;
673
+ if (tagCount === void 0) {
674
+ tagCount = 0;
675
+ }
610
676
  this.attr = void 0;
677
+ this.tagAnchor = void 0;
678
+ this.tagOrder = void 0;
611
679
  this._startDate = void 0;
612
680
  this._endDate = void 0;
681
+ this._cue = void 0;
613
682
  this._badValueForSameId = void 0;
683
+ this.tagAnchor = (dateRangeWithSameId == null ? void 0 : dateRangeWithSameId.tagAnchor) || null;
684
+ this.tagOrder = (_dateRangeWithSameId$ = dateRangeWithSameId == null ? void 0 : dateRangeWithSameId.tagOrder) != null ? _dateRangeWithSameId$ : tagCount;
614
685
  if (dateRangeWithSameId) {
615
686
  var previousAttr = dateRangeWithSameId.attr;
616
687
  for (var key in previousAttr) {
@@ -624,9 +695,9 @@
624
695
  dateRangeAttr = _extends(new AttrList({}), previousAttr, dateRangeAttr);
625
696
  }
626
697
  this.attr = dateRangeAttr;
627
- this._startDate = new Date(dateRangeAttr["START-DATE"]);
698
+ this._startDate = dateRangeWithSameId ? dateRangeWithSameId.startDate : new Date(dateRangeAttr["START-DATE"]);
628
699
  if ("END-DATE" in this.attr) {
629
- var endDate = new Date(this.attr["END-DATE"]);
700
+ var endDate = (dateRangeWithSameId == null ? void 0 : dateRangeWithSameId.endDate) || new Date(this.attr["END-DATE"]);
630
701
  if (isFiniteNumber(endDate.getTime())) {
631
702
  this._endDate = endDate;
632
703
  }
@@ -642,6 +713,30 @@
642
713
  get: function get() {
643
714
  return this.attr.CLASS;
644
715
  }
716
+ }, {
717
+ key: "cue",
718
+ get: function get() {
719
+ var _cue = this._cue;
720
+ if (_cue === undefined) {
721
+ return this._cue = this.attr.enumeratedStringList(this.attr.CUE ? 'CUE' : 'X-CUE', {
722
+ pre: false,
723
+ post: false,
724
+ once: false
725
+ });
726
+ }
727
+ return _cue;
728
+ }
729
+ }, {
730
+ key: "startTime",
731
+ get: function get() {
732
+ var tagAnchor = this.tagAnchor;
733
+ // eslint-disable-next-line @typescript-eslint/prefer-optional-chain
734
+ if (tagAnchor === null || tagAnchor.programDateTime === null) {
735
+ logger.warn("Expected tagAnchor Fragment with PDT set for DateRange \"" + this.id + "\": " + tagAnchor);
736
+ return NaN;
737
+ }
738
+ return tagAnchor.start + (this.startDate.getTime() - tagAnchor.programDateTime) / 1000;
739
+ }
645
740
  }, {
646
741
  key: "startDate",
647
742
  get: function get() {
@@ -685,10 +780,15 @@
685
780
  get: function get() {
686
781
  return this.attr.bool("END-ON-NEXT");
687
782
  }
783
+ }, {
784
+ key: "isInterstitial",
785
+ get: function get() {
786
+ return this.class === CLASS_INTERSTITIAL;
787
+ }
688
788
  }, {
689
789
  key: "isValid",
690
790
  get: function get() {
691
- return !!this.id && !this._badValueForSameId && isFiniteNumber(this.startDate.getTime()) && (this.duration === null || this.duration >= 0) && (!this.endOnNext || !!this.class);
791
+ return !!this.id && !this._badValueForSameId && isFiniteNumber(this.startDate.getTime()) && (this.duration === null || this.duration >= 0) && (!this.endOnNext || !!this.class) && (!this.attr.CUE || !this.cue.pre && !this.cue.post || this.cue.pre !== this.cue.post) && (!this.isInterstitial || 'X-ASSET-URI' in this.attr || 'X-ASSET-LIST' in this.attr);
692
792
  }
693
793
  }]);
694
794
  }();
@@ -780,7 +880,6 @@
780
880
  }
781
881
  }]);
782
882
  }();
783
-
784
883
  /**
785
884
  * Object representing parsed data from an HLS Segment. Found in {@link hls.js#LevelDetails.fragments}.
786
885
  */
@@ -1011,6 +1110,7 @@
1011
1110
  this.fragmentHint = void 0;
1012
1111
  this.partList = null;
1013
1112
  this.dateRanges = void 0;
1113
+ this.dateRangeTagCount = 0;
1014
1114
  this.live = true;
1015
1115
  this.ageHeader = 0;
1016
1116
  this.advancedDateTime = void 0;
@@ -2659,7 +2759,7 @@
2659
2759
  if (result[1]) {
2660
2760
  var _level$unknownCodecs;
2661
2761
  // '#EXT-X-STREAM-INF' is found, parse level tag in group 1
2662
- var attrs = new AttrList(result[1]);
2762
+ var attrs = new AttrList(result[1], parsed);
2663
2763
  var uri = result[2];
2664
2764
  var level = {
2665
2765
  attrs: attrs,
@@ -2684,7 +2784,7 @@
2684
2784
  case 'SESSION-DATA':
2685
2785
  {
2686
2786
  // #EXT-X-SESSION-DATA
2687
- var sessionAttrs = new AttrList(attributes);
2787
+ var sessionAttrs = new AttrList(attributes, parsed);
2688
2788
  var dataId = sessionAttrs['DATA-ID'];
2689
2789
  if (dataId) {
2690
2790
  if (parsed.sessionData === null) {
@@ -2697,7 +2797,7 @@
2697
2797
  case 'SESSION-KEY':
2698
2798
  {
2699
2799
  // #EXT-X-SESSION-KEY
2700
- var sessionKey = parseKey(attributes, baseurl);
2800
+ var sessionKey = parseKey(attributes, baseurl, parsed);
2701
2801
  if (sessionKey.encrypted && sessionKey.isSupported()) {
2702
2802
  if (parsed.sessionKeys === null) {
2703
2803
  parsed.sessionKeys = [];
@@ -2715,7 +2815,7 @@
2715
2815
  case 'CONTENT-STEERING':
2716
2816
  {
2717
2817
  // #EXT-X-CONTENT-STEERING
2718
- var contentSteeringAttributes = new AttrList(attributes);
2818
+ var contentSteeringAttributes = new AttrList(attributes, parsed);
2719
2819
  parsed.contentSteering = {
2720
2820
  uri: M3U8Parser.resolve(contentSteeringAttributes['SERVER-URI'], baseurl),
2721
2821
  pathwayId: contentSteeringAttributes['PATHWAY-ID'] || '.'
@@ -2761,7 +2861,7 @@
2761
2861
  var id = 0;
2762
2862
  MASTER_PLAYLIST_MEDIA_REGEX.lastIndex = 0;
2763
2863
  while ((result = MASTER_PLAYLIST_MEDIA_REGEX.exec(string)) !== null) {
2764
- var attrs = new AttrList(result[1]);
2864
+ var attrs = new AttrList(result[1], parsed);
2765
2865
  var type = attrs.TYPE;
2766
2866
  if (type) {
2767
2867
  var groups = groupsByType[type];
@@ -2813,6 +2913,7 @@
2813
2913
  M3U8Parser.parseLevelPlaylist = function parseLevelPlaylist(string, baseurl, id, type, levelUrlId, multivariantVariableList) {
2814
2914
  var level = new LevelDetails(baseurl);
2815
2915
  var fragments = level.fragments;
2916
+ var programDateTimes = [];
2816
2917
  // The most recent init segment seen (applies to all subsequent segments)
2817
2918
  var currentInitSegment = null;
2818
2919
  var currentSN = 0;
@@ -2871,7 +2972,7 @@
2871
2972
  // avoid sliced strings https://github.com/video-dev/hls.js/issues/939
2872
2973
  var uri = (' ' + result[3]).slice(1);
2873
2974
  frag.relurl = uri;
2874
- assignProgramDateTime(frag, prevFrag);
2975
+ assignProgramDateTime(frag, prevFrag, programDateTimes);
2875
2976
  prevFrag = frag;
2876
2977
  totalduration += frag.duration;
2877
2978
  currentSN++;
@@ -2919,19 +3020,22 @@
2919
3020
  break;
2920
3021
  case 'SKIP':
2921
3022
  {
2922
- var skipAttrs = new AttrList(value1);
3023
+ if (level.skippedSegments) {
3024
+ level.playlistParsingError = new Error("#EXT-X-SKIP MUST NOT appear more than once in a Playlist");
3025
+ }
3026
+ var skipAttrs = new AttrList(value1, level);
2923
3027
  var skippedSegments = skipAttrs.decimalInteger('SKIPPED-SEGMENTS');
2924
3028
  if (isFiniteNumber(skippedSegments)) {
2925
- level.skippedSegments = skippedSegments;
3029
+ level.skippedSegments += skippedSegments;
2926
3030
  // This will result in fragments[] containing undefined values, which we will fill in with `mergeDetails`
2927
3031
  for (var _i = skippedSegments; _i--;) {
2928
- fragments.unshift(null);
3032
+ fragments.push(null);
2929
3033
  }
2930
3034
  currentSN += skippedSegments;
2931
3035
  }
2932
3036
  var recentlyRemovedDateranges = skipAttrs.enumeratedString('RECENTLY-REMOVED-DATERANGES');
2933
3037
  if (recentlyRemovedDateranges) {
2934
- level.recentlyRemovedDateranges = recentlyRemovedDateranges.split('\t');
3038
+ level.recentlyRemovedDateranges = (level.recentlyRemovedDateranges || []).concat(recentlyRemovedDateranges.split('\t'));
2935
3039
  }
2936
3040
  break;
2937
3041
  }
@@ -2965,8 +3069,9 @@
2965
3069
  break;
2966
3070
  case 'DATERANGE':
2967
3071
  {
2968
- var dateRangeAttr = new AttrList(value1);
2969
- var dateRange = new DateRange(dateRangeAttr, level.dateRanges[dateRangeAttr.ID]);
3072
+ var dateRangeAttr = new AttrList(value1, level);
3073
+ var dateRange = new DateRange(dateRangeAttr, level.dateRanges[dateRangeAttr.ID], level.dateRangeTagCount);
3074
+ level.dateRangeTagCount++;
2970
3075
  if (dateRange.isValid || level.skippedSegments) {
2971
3076
  level.dateRanges[dateRange.id] = dateRange;
2972
3077
  } else {
@@ -2985,7 +3090,7 @@
2985
3090
  break;
2986
3091
  case 'KEY':
2987
3092
  {
2988
- var levelKey = parseKey(value1, baseurl);
3093
+ var levelKey = parseKey(value1, baseurl, level);
2989
3094
  if (levelKey.isSupported()) {
2990
3095
  if (levelKey.method === 'NONE') {
2991
3096
  levelkeys = undefined;
@@ -3008,7 +3113,7 @@
3008
3113
  break;
3009
3114
  case 'MAP':
3010
3115
  {
3011
- var mapAttrs = new AttrList(value1);
3116
+ var mapAttrs = new AttrList(value1, level);
3012
3117
  if (frag.duration) {
3013
3118
  // Initial segment tag is after segment duration tag.
3014
3119
  // #EXTINF: 6.0
@@ -3034,6 +3139,7 @@
3034
3139
  currentInitSegment = frag;
3035
3140
  createNextFrag = true;
3036
3141
  }
3142
+ currentInitSegment.cc = discontinuityCounter;
3037
3143
  break;
3038
3144
  }
3039
3145
  case 'SERVER-CONTROL':
@@ -3060,7 +3166,7 @@
3060
3166
  }
3061
3167
  var previousFragmentPart = currentPart > 0 ? partList[partList.length - 1] : undefined;
3062
3168
  var index = currentPart++;
3063
- var partAttrs = new AttrList(value1);
3169
+ var partAttrs = new AttrList(value1, level);
3064
3170
  var part = new Part(partAttrs, frag, baseurl, index, previousFragmentPart);
3065
3171
  partList.push(part);
3066
3172
  frag.duration += part.duration;
@@ -3068,13 +3174,13 @@
3068
3174
  }
3069
3175
  case 'PRELOAD-HINT':
3070
3176
  {
3071
- var preloadHintAttrs = new AttrList(value1);
3177
+ var preloadHintAttrs = new AttrList(value1, level);
3072
3178
  level.preloadHint = preloadHintAttrs;
3073
3179
  break;
3074
3180
  }
3075
3181
  case 'RENDITION-REPORT':
3076
3182
  {
3077
- var renditionReportAttrs = new AttrList(value1);
3183
+ var renditionReportAttrs = new AttrList(value1, level);
3078
3184
  level.renditionReports = level.renditionReports || [];
3079
3185
  level.renditionReports.push(renditionReportAttrs);
3080
3186
  break;
@@ -3092,7 +3198,7 @@
3092
3198
  level.fragmentHint = prevFrag;
3093
3199
  }
3094
3200
  } else if (level.partList) {
3095
- assignProgramDateTime(frag, prevFrag);
3201
+ assignProgramDateTime(frag, prevFrag, programDateTimes);
3096
3202
  frag.cc = discontinuityCounter;
3097
3203
  level.fragmentHint = frag;
3098
3204
  if (levelkeys) {
@@ -3113,6 +3219,21 @@
3113
3219
  if (firstFragment) {
3114
3220
  level.startCC = firstFragment.cc;
3115
3221
  }
3222
+ /**
3223
+ * Backfill any missing PDT values
3224
+ * "If the first EXT-X-PROGRAM-DATE-TIME tag in a Playlist appears after
3225
+ * one or more Media Segment URIs, the client SHOULD extrapolate
3226
+ * backward from that tag (using EXTINF durations and/or media
3227
+ * timestamps) to associate dates with those segments."
3228
+ * We have already extrapolated forward, but all fragments up to the first instance of PDT do not have their PDTs
3229
+ * computed.
3230
+ */
3231
+ if (firstPdtIndex > 0) {
3232
+ backfillProgramDateTimes(fragments, firstPdtIndex);
3233
+ if (firstFragment) {
3234
+ programDateTimes.unshift(firstFragment);
3235
+ }
3236
+ }
3116
3237
  } else {
3117
3238
  level.endSN = 0;
3118
3239
  level.startCC = 0;
@@ -3121,28 +3242,63 @@
3121
3242
  totalduration += level.fragmentHint.duration;
3122
3243
  }
3123
3244
  level.totalduration = totalduration;
3124
- level.endCC = discontinuityCounter;
3125
-
3126
- /**
3127
- * Backfill any missing PDT values
3128
- * "If the first EXT-X-PROGRAM-DATE-TIME tag in a Playlist appears after
3129
- * one or more Media Segment URIs, the client SHOULD extrapolate
3130
- * backward from that tag (using EXTINF durations and/or media
3131
- * timestamps) to associate dates with those segments."
3132
- * We have already extrapolated forward, but all fragments up to the first instance of PDT do not have their PDTs
3133
- * computed.
3134
- */
3135
- if (firstPdtIndex > 0) {
3136
- backfillProgramDateTimes(fragments, firstPdtIndex);
3245
+ if (programDateTimes.length && level.dateRangeTagCount && firstFragment) {
3246
+ mapDateRanges(programDateTimes, level);
3137
3247
  }
3248
+ level.endCC = discontinuityCounter;
3138
3249
  return level;
3139
3250
  };
3140
3251
  return M3U8Parser;
3141
3252
  }();
3253
+ function mapDateRanges(programDateTimes, details) {
3254
+ // Make sure DateRanges are mapped to a ProgramDateTime tag that applies a date to a segment that overlaps with its start date
3255
+ var programDateTimeCount = programDateTimes.length;
3256
+ var lastProgramDateTime = programDateTimes[programDateTimeCount - 1];
3257
+ var playlistEnd = details.live ? Infinity : details.totalduration;
3258
+ var dateRangeIds = Object.keys(details.dateRanges);
3259
+ for (var i = dateRangeIds.length; i--;) {
3260
+ var dateRange = details.dateRanges[dateRangeIds[i]];
3261
+ var startDateTime = dateRange.startDate.getTime();
3262
+ dateRange.tagAnchor = lastProgramDateTime;
3263
+ for (var j = programDateTimeCount; j--;) {
3264
+ var fragIndex = findFragmentWithStartDate(details, startDateTime, programDateTimes, j, playlistEnd);
3265
+ if (fragIndex !== -1) {
3266
+ dateRange.tagAnchor = details.fragments[fragIndex];
3267
+ break;
3268
+ }
3269
+ }
3270
+ }
3271
+ }
3272
+ function findFragmentWithStartDate(details, startDateTime, programDateTimes, index, endTime) {
3273
+ var pdtFragment = programDateTimes[index];
3274
+ if (pdtFragment) {
3275
+ var _programDateTimes;
3276
+ // find matching range between PDT tags
3277
+ var durationBetweenPdt = (((_programDateTimes = programDateTimes[index + 1]) == null ? void 0 : _programDateTimes.start) || endTime) - pdtFragment.start;
3278
+ var pdtStart = pdtFragment.programDateTime;
3279
+ if ((startDateTime >= pdtStart || index === 0) && startDateTime <= pdtStart + durationBetweenPdt * 1000) {
3280
+ // map to fragment with date-time range
3281
+ var startIndex = programDateTimes[index].sn - details.startSN;
3282
+ var fragments = details.fragments;
3283
+ if (fragments.length > programDateTimes.length) {
3284
+ var endSegment = programDateTimes[index + 1] || fragments[fragments.length - 1];
3285
+ var endIndex = endSegment.sn - details.startSN;
3286
+ for (var i = endIndex; i > startIndex; i--) {
3287
+ var fragStartDateTime = fragments[i].programDateTime;
3288
+ if (startDateTime >= fragStartDateTime && startDateTime < fragStartDateTime + fragments[i].duration * 1000) {
3289
+ return i;
3290
+ }
3291
+ }
3292
+ }
3293
+ return startIndex;
3294
+ }
3295
+ }
3296
+ return -1;
3297
+ }
3142
3298
  function parseKey(keyTagAttributes, baseurl, parsed) {
3143
3299
  var _keyAttrs$METHOD, _keyAttrs$KEYFORMAT;
3144
3300
  // https://tools.ietf.org/html/rfc8216#section-4.3.2.4
3145
- var keyAttrs = new AttrList(keyTagAttributes);
3301
+ var keyAttrs = new AttrList(keyTagAttributes, parsed);
3146
3302
  var decryptmethod = (_keyAttrs$METHOD = keyAttrs.METHOD) != null ? _keyAttrs$METHOD : '';
3147
3303
  var decrypturi = keyAttrs.URI;
3148
3304
  var decryptiv = keyAttrs.hexadecimalInteger('IV');
@@ -3203,16 +3359,18 @@
3203
3359
  fragPrev = frag;
3204
3360
  }
3205
3361
  }
3206
- function assignProgramDateTime(frag, prevFrag) {
3362
+ function assignProgramDateTime(frag, prevFrag, programDateTimes) {
3207
3363
  if (frag.rawProgramDateTime) {
3208
3364
  frag.programDateTime = Date.parse(frag.rawProgramDateTime);
3365
+ if (!isFiniteNumber(frag.programDateTime)) {
3366
+ frag.programDateTime = null;
3367
+ frag.rawProgramDateTime = null;
3368
+ return;
3369
+ }
3370
+ programDateTimes.push(frag);
3209
3371
  } else if (prevFrag != null && prevFrag.programDateTime) {
3210
3372
  frag.programDateTime = prevFrag.endProgramDateTime;
3211
3373
  }
3212
- if (!isFiniteNumber(frag.programDateTime)) {
3213
- frag.programDateTime = null;
3214
- frag.rawProgramDateTime = null;
3215
- }
3216
3374
  }
3217
3375
  function setInitSegment(frag, mapAttrs, id, levelkeys) {
3218
3376
  frag.relurl = mapAttrs.URI;
@@ -4292,9 +4450,6 @@
4292
4450
  }
4293
4451
  return Number.POSITIVE_INFINITY;
4294
4452
  }();
4295
- function dateRangeDateToTimelineSeconds(date, offset) {
4296
- return date.getTime() / 1000 - offset;
4297
- }
4298
4453
  function hexToArrayBuffer(str) {
4299
4454
  return Uint8Array.from(str.replace(/^0x/, '').replace(/([\da-fA-F]{2}) ?/g, '0x$1 ').replace(/ +$/, '').split(' ')).buffer;
4300
4455
  }
@@ -4324,6 +4479,7 @@
4324
4479
  hls.on(Events.FRAG_PARSING_METADATA, this.onFragParsingMetadata, this);
4325
4480
  hls.on(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);
4326
4481
  hls.on(Events.LEVEL_UPDATED, this.onLevelUpdated, this);
4482
+ hls.on(Events.LEVEL_PTS_UPDATED, this.onLevelPtsUpdated, this);
4327
4483
  };
4328
4484
  _proto._unregisterListeners = function _unregisterListeners() {
4329
4485
  var hls = this.hls;
@@ -4333,6 +4489,7 @@
4333
4489
  hls.off(Events.FRAG_PARSING_METADATA, this.onFragParsingMetadata, this);
4334
4490
  hls.off(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);
4335
4491
  hls.off(Events.LEVEL_UPDATED, this.onLevelUpdated, this);
4492
+ hls.off(Events.LEVEL_PTS_UPDATED, this.onLevelPtsUpdated, this);
4336
4493
  }
4337
4494
 
4338
4495
  // Add ID3 metatadata text track.
@@ -4465,8 +4622,16 @@
4465
4622
  }
4466
4623
  };
4467
4624
  _proto.onLevelUpdated = function onLevelUpdated(event, _ref2) {
4468
- var _this = this;
4469
4625
  var details = _ref2.details;
4626
+ this.updateDateRangeCues(details, true);
4627
+ };
4628
+ _proto.onLevelPtsUpdated = function onLevelPtsUpdated(event, data) {
4629
+ if (Math.abs(data.drift) > 0.01) {
4630
+ this.updateDateRangeCues(data.details);
4631
+ }
4632
+ };
4633
+ _proto.updateDateRangeCues = function updateDateRangeCues(details, removeOldCues) {
4634
+ var _this = this;
4470
4635
  if (!this.media || !details.hasProgramDateTime || !this.hls.config.enableDateRangeMetadataCues) {
4471
4636
  return;
4472
4637
  }
@@ -4475,7 +4640,7 @@
4475
4640
  var dateRanges = details.dateRanges;
4476
4641
  var ids = Object.keys(dateRanges);
4477
4642
  // Remove cues from track not found in details.dateRanges
4478
- if (id3Track) {
4643
+ if (id3Track && removeOldCues) {
4479
4644
  var idsToRemove = Object.keys(dateRangeCuesAppended).filter(function (id) {
4480
4645
  return !ids.includes(id);
4481
4646
  });
@@ -4498,21 +4663,21 @@
4498
4663
  if (!this.id3Track) {
4499
4664
  this.id3Track = this.createTrack(this.media);
4500
4665
  }
4501
- var dateTimeOffset = lastFragment.programDateTime / 1000 - lastFragment.start;
4502
4666
  var Cue = getCueClass();
4503
4667
  var _loop2 = function _loop2() {
4504
4668
  var id = ids[_i];
4505
4669
  var dateRange = dateRanges[id];
4506
- var startTime = dateRangeDateToTimelineSeconds(dateRange.startDate, dateTimeOffset);
4670
+ var startTime = dateRange.startTime;
4507
4671
 
4508
4672
  // Process DateRanges to determine end-time (known DURATION, END-DATE, or END-ON-NEXT)
4509
4673
  var appendedDateRangeCues = dateRangeCuesAppended[id];
4510
4674
  var cues = (appendedDateRangeCues == null ? void 0 : appendedDateRangeCues.cues) || {};
4511
4675
  var durationKnown = (appendedDateRangeCues == null ? void 0 : appendedDateRangeCues.durationKnown) || false;
4512
4676
  var endTime = MAX_CUE_ENDTIME;
4513
- var endDate = dateRange.endDate;
4514
- if (endDate) {
4515
- endTime = dateRangeDateToTimelineSeconds(endDate, dateTimeOffset);
4677
+ var duration = dateRange.duration,
4678
+ endDate = dateRange.endDate;
4679
+ if (endDate && duration !== null) {
4680
+ endTime = startTime + duration;
4516
4681
  durationKnown = true;
4517
4682
  } else if (dateRange.endOnNext && !durationKnown) {
4518
4683
  var nextDateRangeWithSameClass = ids.reduce(function (candidateDateRange, id) {
@@ -4525,7 +4690,7 @@
4525
4690
  return candidateDateRange;
4526
4691
  }, null);
4527
4692
  if (nextDateRangeWithSameClass) {
4528
- endTime = dateRangeDateToTimelineSeconds(nextDateRangeWithSameClass.startDate, dateTimeOffset);
4693
+ endTime = nextDateRangeWithSameClass.startTime;
4529
4694
  durationKnown = true;
4530
4695
  }
4531
4696
  }
@@ -4542,6 +4707,9 @@
4542
4707
  if (cue) {
4543
4708
  if (durationKnown && !appendedDateRangeCues.durationKnown) {
4544
4709
  cue.endTime = endTime;
4710
+ } else if (Math.abs(cue.startTime - startTime) > 0.01) {
4711
+ cue.startTime = startTime;
4712
+ cue.endTime = endTime;
4545
4713
  }
4546
4714
  } else if (Cue) {
4547
4715
  var data = dateRange.attr[key];
@@ -5072,7 +5240,7 @@
5072
5240
  frag.endPTS = endPTS;
5073
5241
  frag.minEndPTS = minEndPTS;
5074
5242
  frag.endDTS = endDTS;
5075
- var sn = frag.sn; // 'initSegment'
5243
+ var sn = frag.sn;
5076
5244
  // exit if sn out of range
5077
5245
  if (!details || sn < details.startSN || sn > details.endSN) {
5078
5246
  return 0;
@@ -5150,8 +5318,8 @@
5150
5318
  currentInitSegment = oldFrag.initSegment;
5151
5319
  }
5152
5320
  });
5321
+ var fragmentsToCheck = newDetails.fragmentHint ? newDetails.fragments.concat(newDetails.fragmentHint) : newDetails.fragments;
5153
5322
  if (currentInitSegment) {
5154
- var fragmentsToCheck = newDetails.fragmentHint ? newDetails.fragments.concat(newDetails.fragmentHint) : newDetails.fragments;
5155
5323
  fragmentsToCheck.forEach(function (frag) {
5156
5324
  var _currentInitSegment;
5157
5325
  if (frag && (!frag.initSegment || frag.initSegment.relurl === ((_currentInitSegment = currentInitSegment) == null ? void 0 : _currentInitSegment.relurl))) {
@@ -5170,15 +5338,28 @@
5170
5338
  }
5171
5339
  newDetails.startSN = newDetails.fragments[0].sn;
5172
5340
  newDetails.startCC = newDetails.fragments[0].cc;
5173
- } else if (newDetails.canSkipDateRanges) {
5174
- newDetails.dateRanges = mergeDateRanges(oldDetails.dateRanges, newDetails.dateRanges, newDetails.recentlyRemovedDateranges);
5341
+ } else {
5342
+ if (newDetails.canSkipDateRanges) {
5343
+ newDetails.dateRanges = mergeDateRanges(oldDetails.dateRanges, newDetails);
5344
+ }
5345
+ var programDateTimes = oldDetails.fragments.filter(function (frag) {
5346
+ return frag.rawProgramDateTime;
5347
+ });
5348
+ if (oldDetails.hasProgramDateTime && !newDetails.hasProgramDateTime) {
5349
+ for (var _i2 = 1; _i2 < fragmentsToCheck.length; _i2++) {
5350
+ if (fragmentsToCheck[_i2].programDateTime === null) {
5351
+ assignProgramDateTime(fragmentsToCheck[_i2], fragmentsToCheck[_i2 - 1], programDateTimes);
5352
+ }
5353
+ }
5354
+ }
5355
+ mapDateRanges(programDateTimes, newDetails);
5175
5356
  }
5176
5357
  }
5177
5358
  var newFragments = newDetails.fragments;
5178
5359
  if (ccOffset) {
5179
5360
  logger.warn('discontinuity sliding from playlist, take drift into account');
5180
- for (var _i2 = 0; _i2 < newFragments.length; _i2++) {
5181
- newFragments[_i2].cc += ccOffset;
5361
+ for (var _i3 = 0; _i3 < newFragments.length; _i3++) {
5362
+ newFragments[_i3].cc += ccOffset;
5182
5363
  }
5183
5364
  }
5184
5365
  if (newDetails.skippedSegments) {
@@ -5220,21 +5401,31 @@
5220
5401
  newDetails.advancedDateTime = oldDetails.advancedDateTime;
5221
5402
  }
5222
5403
  }
5223
- function mergeDateRanges(oldDateRanges, deltaDateRanges, recentlyRemovedDateranges) {
5404
+ function mergeDateRanges(oldDateRanges, newDetails) {
5405
+ var deltaDateRanges = newDetails.dateRanges,
5406
+ recentlyRemovedDateranges = newDetails.recentlyRemovedDateranges;
5224
5407
  var dateRanges = _extends({}, oldDateRanges);
5225
5408
  if (recentlyRemovedDateranges) {
5226
5409
  recentlyRemovedDateranges.forEach(function (id) {
5227
5410
  delete dateRanges[id];
5228
5411
  });
5229
5412
  }
5230
- Object.keys(deltaDateRanges).forEach(function (id) {
5231
- var dateRange = new DateRange(deltaDateRanges[id].attr, dateRanges[id]);
5232
- if (dateRange.isValid) {
5233
- dateRanges[id] = dateRange;
5234
- } else {
5235
- logger.warn("Ignoring invalid Playlist Delta Update DATERANGE tag: \"" + JSON.stringify(deltaDateRanges[id].attr) + "\"");
5236
- }
5237
- });
5413
+ var mergeIds = Object.keys(dateRanges);
5414
+ var mergeCount = mergeIds.length;
5415
+ if (mergeCount) {
5416
+ Object.keys(deltaDateRanges).forEach(function (id) {
5417
+ var mergedDateRange = dateRanges[id];
5418
+ var dateRange = new DateRange(deltaDateRanges[id].attr, mergedDateRange);
5419
+ if (dateRange.isValid) {
5420
+ dateRanges[id] = dateRange;
5421
+ if (!mergedDateRange) {
5422
+ dateRange.tagOrder += mergeCount;
5423
+ }
5424
+ } else {
5425
+ logger.warn("Ignoring invalid Playlist Delta Update DATERANGE tag: \"" + JSON.stringify(deltaDateRanges[id].attr) + "\"");
5426
+ }
5427
+ });
5428
+ }
5238
5429
  return dateRanges;
5239
5430
  }
5240
5431
  function mapPartIntersection(oldParts, newParts, intersectionFn) {
@@ -5261,7 +5452,7 @@
5261
5452
  for (var i = start; i <= end; i++) {
5262
5453
  var _oldFrag = oldFrags[delta + i];
5263
5454
  var _newFrag = newFrags[i];
5264
- if (skippedSegments && !_newFrag && i < skippedSegments) {
5455
+ if (skippedSegments && !_newFrag && _oldFrag) {
5265
5456
  // Fill in skipped segments in delta playlist
5266
5457
  _newFrag = newDetails.fragments[i] = _oldFrag;
5267
5458
  }
@@ -5314,19 +5505,19 @@
5314
5505
  return Math.round(reloadInterval);
5315
5506
  }
5316
5507
  function getFragmentWithSN(level, sn, fragCurrent) {
5317
- if (!(level != null && level.details)) {
5508
+ var details = level == null ? void 0 : level.details;
5509
+ if (!details) {
5318
5510
  return null;
5319
5511
  }
5320
- var levelDetails = level.details;
5321
- var fragment = levelDetails.fragments[sn - levelDetails.startSN];
5512
+ var fragment = details.fragments[sn - details.startSN];
5322
5513
  if (fragment) {
5323
5514
  return fragment;
5324
5515
  }
5325
- fragment = levelDetails.fragmentHint;
5516
+ fragment = details.fragmentHint;
5326
5517
  if (fragment && fragment.sn === sn) {
5327
5518
  return fragment;
5328
5519
  }
5329
- if (sn < levelDetails.startSN && fragCurrent && fragCurrent.sn === sn) {
5520
+ if (sn < details.startSN && fragCurrent && fragCurrent.sn === sn) {
5330
5521
  return fragCurrent;
5331
5522
  }
5332
5523
  return null;
@@ -10872,11 +11063,10 @@
10872
11063
  _proto.detectPartialFragments = function detectPartialFragments(data) {
10873
11064
  var _this2 = this;
10874
11065
  var timeRanges = this.timeRanges;
10875
- var frag = data.frag,
10876
- part = data.part;
10877
- if (!timeRanges || frag.sn === 'initSegment') {
11066
+ if (!timeRanges || data.frag.sn === 'initSegment') {
10878
11067
  return;
10879
11068
  }
11069
+ var frag = data.frag;
10880
11070
  var fragKey = getFragmentKey(frag);
10881
11071
  var fragmentEntity = this.fragments[fragKey];
10882
11072
  if (!fragmentEntity || fragmentEntity.buffered && frag.gap) {
@@ -10890,7 +11080,7 @@
10890
11080
  }
10891
11081
  var timeRange = timeRanges[elementaryStream];
10892
11082
  var partial = isFragHint || streamInfo.partial === true;
10893
- fragmentEntity.range[elementaryStream] = _this2.getBufferedTimes(frag, part, partial, timeRange);
11083
+ fragmentEntity.range[elementaryStream] = _this2.getBufferedTimes(frag, data.part, partial, timeRange);
10894
11084
  });
10895
11085
  fragmentEntity.loaded = null;
10896
11086
  if (Object.keys(fragmentEntity.range).length) {
@@ -11043,16 +11233,14 @@
11043
11233
  return false;
11044
11234
  };
11045
11235
  _proto.onFragLoaded = function onFragLoaded(event, data) {
11046
- var frag = data.frag,
11047
- part = data.part;
11048
11236
  // don't track initsegment (for which sn is not a number)
11049
11237
  // don't track frags used for bitrateTest, they're irrelevant.
11050
- if (frag.sn === 'initSegment' || frag.bitrateTest) {
11238
+ if (data.frag.sn === 'initSegment' || data.frag.bitrateTest) {
11051
11239
  return;
11052
11240
  }
11053
-
11241
+ var frag = data.frag;
11054
11242
  // Fragment entity `loaded` FragLoadedData is null when loading parts
11055
- var loaded = part ? null : data;
11243
+ var loaded = data.part ? null : data;
11056
11244
  var fragKey = getFragmentKey(frag);
11057
11245
  this.fragments[fragKey] = {
11058
11246
  body: frag,
@@ -13184,14 +13372,12 @@
13184
13372
  part.stats.parsing.end = now;
13185
13373
  }
13186
13374
  // See if part loading should be disabled/enabled based on buffer and playback position.
13187
- if (frag.sn !== 'initSegment') {
13188
- var levelDetails = this.getLevelDetails();
13189
- var loadingPartsAtEdge = levelDetails && frag.sn > levelDetails.endSN;
13190
- var shouldLoadParts = loadingPartsAtEdge || this.shouldLoadParts(levelDetails, frag.end);
13191
- if (shouldLoadParts !== this.loadingParts) {
13192
- this.log("LL-Part loading " + (shouldLoadParts ? 'ON' : 'OFF') + " after parsing segment ending @" + frag.end.toFixed(2));
13193
- this.loadingParts = shouldLoadParts;
13194
- }
13375
+ var levelDetails = this.getLevelDetails();
13376
+ var loadingPartsAtEdge = levelDetails && frag.sn > levelDetails.endSN;
13377
+ var shouldLoadParts = loadingPartsAtEdge || this.shouldLoadParts(levelDetails, frag.end);
13378
+ if (shouldLoadParts !== this.loadingParts) {
13379
+ this.log("LL-Part loading " + (shouldLoadParts ? 'ON' : 'OFF') + " after parsing segment ending @" + frag.end.toFixed(2));
13380
+ this.loadingParts = shouldLoadParts;
13195
13381
  }
13196
13382
  this.updateLevelTiming(frag, part, level, chunkMeta.partial);
13197
13383
  };
@@ -20199,8 +20385,8 @@
20199
20385
  };
20200
20386
  _proto._handleFragmentLoadProgress = function _handleFragmentLoadProgress(data) {
20201
20387
  var _frag$initSegment;
20202
- var frag = data.frag,
20203
- part = data.part,
20388
+ var frag = data.frag;
20389
+ var part = data.part,
20204
20390
  payload = data.payload;
20205
20391
  var levels = this.levels;
20206
20392
  if (!levels) {
@@ -20540,7 +20726,7 @@
20540
20726
  }
20541
20727
 
20542
20728
  // Avoid buffering if backtracking this fragment
20543
- if (video && details && frag.sn !== 'initSegment') {
20729
+ if (video && details) {
20544
20730
  var prevFrag = details.fragments[frag.sn - 1 - details.startSN];
20545
20731
  var isFirstFragment = frag.sn === details.startSN;
20546
20732
  var isFirstInDiscontinuity = !prevFrag || frag.cc > prevFrag.cc;
@@ -21709,7 +21895,7 @@
21709
21895
  * Get the video-dev/hls.js package version.
21710
21896
  */
21711
21897
  function get() {
21712
- return "1.5.12-0.canary.10340";
21898
+ return "1.5.12-0.canary.10341";
21713
21899
  }
21714
21900
  }, {
21715
21901
  key: "Events",