shaka-player 3.2.1 → 3.2.2

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.
Files changed (96) hide show
  1. package/AUTHORS +3 -0
  2. package/CHANGELOG.md +57 -0
  3. package/CONTRIBUTORS +3 -0
  4. package/build/generateExterns.js +1 -1
  5. package/demo/common/assets.js +1 -1
  6. package/demo/index.html +1 -1
  7. package/dist/controls.css +2 -2
  8. package/dist/controls.css.map +1 -1
  9. package/dist/demo.compiled.debug.js +1 -1
  10. package/dist/demo.compiled.js +1 -1
  11. package/dist/deps.js +1 -1
  12. package/dist/locales.js +37 -37
  13. package/dist/receiver.compiled.debug.js +1 -1
  14. package/dist/receiver.compiled.js +1 -1
  15. package/dist/shaka-player.compiled.d.ts +1 -1
  16. package/dist/shaka-player.compiled.debug.d.ts +1 -1
  17. package/dist/shaka-player.compiled.debug.externs.js +1 -1
  18. package/dist/shaka-player.compiled.debug.js +188 -181
  19. package/dist/shaka-player.compiled.debug.map +3 -3
  20. package/dist/shaka-player.compiled.externs.js +1 -1
  21. package/dist/shaka-player.compiled.js +795 -790
  22. package/dist/shaka-player.compiled.map +3 -3
  23. package/dist/shaka-player.ui.d.ts +1 -1
  24. package/dist/shaka-player.ui.debug.d.ts +1 -1
  25. package/dist/shaka-player.ui.debug.externs.js +3 -3
  26. package/dist/shaka-player.ui.debug.js +217 -210
  27. package/dist/shaka-player.ui.debug.map +4 -4
  28. package/dist/shaka-player.ui.externs.js +3 -3
  29. package/dist/shaka-player.ui.js +945 -940
  30. package/dist/shaka-player.ui.map +4 -4
  31. package/docs/tutorials/fairplay.md +1 -1
  32. package/docs/tutorials/ui.md +5 -5
  33. package/karma.conf.js +1 -0
  34. package/lib/ads/client_side_ad_manager.js +46 -86
  35. package/lib/ads/server_side_ad_manager.js +7 -10
  36. package/lib/cast/cast_proxy.js +3 -2
  37. package/lib/cast/cast_receiver.js +2 -1
  38. package/lib/cast/cast_sender.js +2 -2
  39. package/lib/dash/dash_parser.js +93 -2
  40. package/lib/dash/segment_list.js +1 -1
  41. package/lib/dash/segment_template.js +1 -1
  42. package/lib/hls/hls_parser.js +30 -17
  43. package/lib/media/drm_engine.js +7 -0
  44. package/lib/media/gap_jumping_controller.js +4 -2
  45. package/lib/media/media_source_engine.js +1 -2
  46. package/lib/media/streaming_engine.js +2 -1
  47. package/lib/net/networking_engine.js +2 -1
  48. package/lib/player.js +26 -25
  49. package/lib/polyfill/media_capabilities.js +7 -1
  50. package/lib/polyfill/mediasource.js +6 -0
  51. package/lib/polyfill/orientation.js +1 -1
  52. package/lib/polyfill/patchedmediakeys_apple.js +4 -4
  53. package/lib/polyfill/patchedmediakeys_ms.js +4 -4
  54. package/lib/polyfill/patchedmediakeys_webkit.js +4 -4
  55. package/lib/text/mp4_ttml_parser.js +3 -0
  56. package/lib/text/text_engine.js +14 -2
  57. package/lib/text/ttml_text_parser.js +5 -0
  58. package/lib/text/ui_text_displayer.js +85 -37
  59. package/lib/util/fake_event.js +53 -7
  60. package/lib/util/periods.js +4 -1
  61. package/lib/util/platform.js +13 -1
  62. package/lib/util/stream_utils.js +13 -0
  63. package/package.json +1 -1
  64. package/test/cast/cast_proxy_unit.js +12 -6
  65. package/test/cast/cast_utils_unit.js +1 -1
  66. package/test/dash/dash_parser_manifest_unit.js +187 -1
  67. package/test/hls/hls_parser_unit.js +5 -1
  68. package/test/media/closed_caption_parser_unit.js +6 -1
  69. package/test/media/drm_engine_unit.js +44 -0
  70. package/test/player_integration.js +38 -0
  71. package/test/test/assets/3675/chunk-stream0-00001.m4s +0 -0
  72. package/test/test/assets/3675/chunk-stream0-00002.m4s +0 -0
  73. package/test/test/assets/3675/chunk-stream0-00003.m4s +0 -0
  74. package/test/test/assets/3675/chunk-stream0-00004.m4s +0 -0
  75. package/test/test/assets/3675/chunk-stream0-00005.m4s +0 -0
  76. package/test/test/assets/3675/chunk-stream0-00006.m4s +0 -0
  77. package/test/test/assets/3675/chunk-stream0-00007.m4s +0 -0
  78. package/test/test/assets/3675/dash_0.mpd +30 -0
  79. package/test/test/assets/3675/dash_1.mpd +30 -0
  80. package/test/test/assets/3675/dash_2.mpd +30 -0
  81. package/test/test/assets/3675/dash_3.mpd +30 -0
  82. package/test/test/assets/3675/dash_4.mpd +30 -0
  83. package/test/test/assets/3675/dash_5.mpd +26 -0
  84. package/test/test/assets/3675/init-stream0.m4s +0 -0
  85. package/test/test/util/fake_ad_manager.js +1 -1
  86. package/test/text/ttml_text_parser_unit.js +9 -0
  87. package/test/text/ui_text_displayer_unit.js +29 -17
  88. package/test/ui/localization_unit.js +15 -14
  89. package/test/ui/text_displayer_layout_unit.js +13 -1
  90. package/test/util/stream_utils_unit.js +35 -0
  91. package/ui/cast_button.js +2 -3
  92. package/ui/controls.js +4 -6
  93. package/ui/less/containers.less +3 -7
  94. package/ui/locales/ru.json +6 -6
  95. package/ui/localization.js +28 -51
  96. package/ui/pip_button.js +2 -3
@@ -167,9 +167,14 @@ shaka.text.UITextDisplayer = class {
167
167
  }
168
168
 
169
169
  // Remove the cues out of the time range.
170
+ const oldNumCues = this.cues_.length;
170
171
  this.cues_ = this.cues_.filter(
171
172
  (cue) => cue.startTime < start || cue.endTime >= end);
172
- this.updateCaptions_();
173
+ // If anything was actually removed in this process, force the captions to
174
+ // update. This makes sure that the currently-displayed cues will stop
175
+ // displaying if removed (say, due to the user changing languages).
176
+ const forceUpdate = oldNumCues > this.cues_.length;
177
+ this.updateCaptions_(forceUpdate);
173
178
 
174
179
  return true;
175
180
  }
@@ -192,13 +197,13 @@ shaka.text.UITextDisplayer = class {
192
197
  }
193
198
 
194
199
  /**
195
- * @param {!Array.<!shaka.text.Cue>} cues
200
+ * @param {!Array.<!shaka.extern.Cue>} cues
196
201
  * @param {!HTMLElement} container
197
202
  * @param {number} currentTime
198
- * @param {boolean} isNested
203
+ * @param {!Array.<!shaka.extern.Cue>} parents
199
204
  * @private
200
205
  */
201
- updateCuesRecursive_(cues, container, currentTime, isNested) {
206
+ updateCuesRecursive_(cues, container, currentTime, parents) {
202
207
  // Set to true if the cues have changed in some way, which will require
203
208
  // DOM changes. E.g. if a cue was added or removed.
204
209
  let updateDOM = false;
@@ -214,10 +219,12 @@ shaka.text.UITextDisplayer = class {
214
219
  * The cues whose corresponding elements should be in the DOM.
215
220
  * Some of these might be new, some might have been displayed beforehand.
216
221
  * These will only be added if updateDOM is true.
217
- * @type {!Array.<!shaka.text.Cue>}
222
+ * @type {!Array.<!shaka.extern.Cue>}
218
223
  */
219
224
  const toPlant = [];
220
225
  for (const cue of cues) {
226
+ parents.push(cue);
227
+
221
228
  let cueRegistry = this.currentCuesMap_.get(cue);
222
229
  const shouldBeDisplayed =
223
230
  cue.startTime <= currentTime && cue.endTime > currentTime;
@@ -241,7 +248,7 @@ shaka.text.UITextDisplayer = class {
241
248
  toPlant.push(cue);
242
249
  if (!cueRegistry) {
243
250
  // The cue has to be made!
244
- this.createCue_(cue, isNested);
251
+ this.createCue_(cue, parents);
245
252
  cueRegistry = this.currentCuesMap_.get(cue);
246
253
  wrapper = cueRegistry.wrapper;
247
254
  updateDOM = true;
@@ -255,8 +262,11 @@ shaka.text.UITextDisplayer = class {
255
262
  // guaranteed that the children will neither need to be added nor removed.
256
263
  if (cue.nestedCues.length > 0 && wrapper) {
257
264
  this.updateCuesRecursive_(
258
- cue.nestedCues, wrapper, currentTime, /* isNested= */ true);
265
+ cue.nestedCues, wrapper, currentTime, parents);
259
266
  }
267
+
268
+ const topCue = parents.pop();
269
+ goog.asserts.assert(topCue == cue, 'Parent cues should be kept in order');
260
270
  }
261
271
  if (updateDOM) {
262
272
  for (const cueElement of toUproot) {
@@ -304,7 +314,7 @@ shaka.text.UITextDisplayer = class {
304
314
 
305
315
  // Update the cues.
306
316
  this.updateCuesRecursive_(
307
- this.cues_, this.textContainer_, currentTime, false);
317
+ this.cues_, this.textContainer_, currentTime, /* parents= */ []);
308
318
 
309
319
  if (goog.DEBUG) {
310
320
  // Previously, we had an issue (#2076) where cues sometimes were not
@@ -327,10 +337,11 @@ shaka.text.UITextDisplayer = class {
327
337
  * Creates the object for a cue.
328
338
  *
329
339
  * @param {!shaka.extern.Cue} cue
330
- * @param {boolean} isNested
340
+ * @param {!Array.<!shaka.extern.Cue>} parents
331
341
  * @private
332
342
  */
333
- createCue_(cue, isNested) {
343
+ createCue_(cue, parents) {
344
+ const isNested = parents.length > 1;
334
345
  let type = isNested ? 'span' : 'div';
335
346
  if (cue.lineBreak || cue.spacer) {
336
347
  if (cue.spacer) {
@@ -344,7 +355,7 @@ shaka.text.UITextDisplayer = class {
344
355
  // Nested cues are inline elements. Top-level cues are block elements.
345
356
  const cueElement = shaka.util.Dom.createHTMLElement(type);
346
357
  if (type != 'br') {
347
- this.setCaptionStyles_(cueElement, cue, isNested);
358
+ this.setCaptionStyles_(cueElement, cue, parents);
348
359
  }
349
360
 
350
361
  let wrapper = cueElement;
@@ -363,13 +374,16 @@ shaka.text.UITextDisplayer = class {
363
374
  /**
364
375
  * @param {!HTMLElement} cueElement
365
376
  * @param {!shaka.extern.Cue} cue
366
- * @param {boolean} isNested
377
+ * @param {!Array.<!shaka.extern.Cue>} parents
367
378
  * @private
368
379
  */
369
- setCaptionStyles_(cueElement, cue, isNested) {
380
+ setCaptionStyles_(cueElement, cue, parents) {
370
381
  const Cue = shaka.text.Cue;
371
- let style = cueElement.style;
382
+ const inherit =
383
+ (cb) => shaka.text.UITextDisplayer.inheritProperty_(parents, cb);
384
+ const style = cueElement.style;
372
385
  const isLeaf = cue.nestedCues.length == 0;
386
+ const isNested = parents.length > 1;
373
387
 
374
388
  // TODO: wrapLine is not yet supported. Lines always wrap.
375
389
 
@@ -388,16 +402,6 @@ shaka.text.UITextDisplayer = class {
388
402
  const nonBreakingSpace = '\xa0';
389
403
  return nonBreakingSpace.repeat(match.length);
390
404
  });
391
- if (isNested) {
392
- cueElement.textContent = text;
393
- } else if (text.length) {
394
- // If a top-level cue has text, move to a <span> so the background is
395
- // styled correctly.
396
- const span = shaka.util.Dom.createHTMLElement('span');
397
- span.textContent = text;
398
- cueElement.appendChild(span);
399
- style = span.style;
400
- }
401
405
 
402
406
  style.backgroundColor = cue.backgroundColor;
403
407
  style.border = cue.border;
@@ -406,20 +410,40 @@ shaka.text.UITextDisplayer = class {
406
410
  style.opacity = cue.opacity;
407
411
  style.paddingLeft = shaka.text.UITextDisplayer.convertLengthValue_(
408
412
  cue.linePadding, cue, this.videoContainer_);
409
- style.paddingRight = shaka.text.UITextDisplayer.convertLengthValue_(
410
- cue.linePadding, cue, this.videoContainer_);
413
+ style.paddingRight =
414
+ shaka.text.UITextDisplayer.convertLengthValue_(
415
+ cue.linePadding, cue, this.videoContainer_);
411
416
 
412
417
  if (cue.backgroundImage) {
413
418
  style.backgroundImage = 'url(\'' + cue.backgroundImage + '\')';
414
419
  style.backgroundRepeat = 'no-repeat';
415
420
  style.backgroundSize = 'contain';
416
421
  style.backgroundPosition = 'center';
422
+ } else {
423
+ // If we have both text and nested cues, then style everything; otherwise
424
+ // place the text in its own <span> so the background doesn't fill the
425
+ // whole region.
426
+ let elem;
427
+ if (cue.nestedCues.length) {
428
+ elem = cueElement;
429
+ } else {
430
+ elem = shaka.util.Dom.createHTMLElement('span');
431
+ cueElement.appendChild(elem);
432
+ }
417
433
 
418
- if (cue.backgroundColor == '') {
419
- // In text-based cues, background color can default in CSS.
420
- // In bitmap-based cues, we default to a transparent background color,
421
- // so that the bitmap can be the only background.
422
- style.backgroundColor = 'transparent';
434
+ if (cue.border) {
435
+ elem.style.border = cue.border;
436
+ }
437
+ const bgColor = inherit((c) => c.backgroundColor);
438
+ if (bgColor) {
439
+ elem.style.backgroundColor = bgColor;
440
+ } else if (text) {
441
+ // If there is no background, default to a semi-transparent black.
442
+ // Only do this for the text itself.
443
+ elem.style.backgroundColor = 'rgba(0, 0, 0, 0.8)';
444
+ }
445
+ if (text) {
446
+ elem.textContent = text;
423
447
  }
424
448
  }
425
449
 
@@ -472,20 +496,28 @@ shaka.text.UITextDisplayer = class {
472
496
  // TODO: Implement lineAlignment of 'CENTER'.
473
497
  if (cue.line) {
474
498
  if (cue.lineInterpretation == Cue.lineInterpretation.PERCENTAGE) {
499
+ // When setting absolute positioning, you need to set x/y/width/height
500
+ // so the element is positioned correctly. Set these as default and
501
+ // other settings will override them.
475
502
  style.position = 'absolute';
503
+ style.left = '0';
504
+ style.top = '0';
476
505
  if (cue.writingMode == Cue.writingMode.HORIZONTAL_TOP_TO_BOTTOM) {
506
+ style.width = '100%';
477
507
  if (cue.lineAlign == Cue.lineAlign.START) {
478
508
  style.top = cue.line + '%';
479
509
  } else if (cue.lineAlign == Cue.lineAlign.END) {
480
510
  style.bottom = cue.line + '%';
481
511
  }
482
512
  } else if (cue.writingMode == Cue.writingMode.VERTICAL_LEFT_TO_RIGHT) {
513
+ style.height = '100%';
483
514
  if (cue.lineAlign == Cue.lineAlign.START) {
484
515
  style.left = cue.line + '%';
485
516
  } else if (cue.lineAlign == Cue.lineAlign.END) {
486
517
  style.right = cue.line + '%';
487
518
  }
488
519
  } else {
520
+ style.height = '100%';
489
521
  if (cue.lineAlign == Cue.lineAlign.START) {
490
522
  style.right = cue.line + '%';
491
523
  } else if (cue.lineAlign == Cue.lineAlign.END) {
@@ -493,12 +525,7 @@ shaka.text.UITextDisplayer = class {
493
525
  }
494
526
  }
495
527
  }
496
- } else if (cue.region && cue.region.id &&
497
- ((!isNested && !isLeaf) || (cue.backgroundImage))) {
498
- // In text-base cues, regions are only applied to block container
499
- // (!isNested && !isLeaf).
500
- // In bitmap-based cues, region settings are used to specify the size and
501
- // position of the backgroundImage.
528
+ } else if (cue.region && cue.region.id) {
502
529
  const percentageUnit = shaka.text.CueRegion.units.PERCENTAGE;
503
530
  const heightUnit = cue.region.heightUnits == percentageUnit ? '%' : 'px';
504
531
  const widthUnit = cue.region.widthUnits == percentageUnit ? '%' : 'px';
@@ -631,4 +658,25 @@ shaka.text.UITextDisplayer = class {
631
658
 
632
659
  return (containerHeight * value / cue.cellResolution.rows) + 'px';
633
660
  }
661
+
662
+ /**
663
+ * Inherits a property from the parent Cue elements. If the value is falsy,
664
+ * it is assumed to be inherited from the parent. This returns null if the
665
+ * value isn't found.
666
+ *
667
+ * @param {!Array.<!shaka.extern.Cue>} parents
668
+ * @param {function(!shaka.extern.Cue):?T} cb
669
+ * @return {?T}
670
+ * @template T
671
+ * @private
672
+ */
673
+ static inheritProperty_(parents, cb) {
674
+ for (let i = parents.length - 1; i >= 0; i--) {
675
+ const val = cb(parents[i]);
676
+ if (val || val === 0) {
677
+ return val;
678
+ }
679
+ }
680
+ return null;
681
+ }
634
682
  };
@@ -6,6 +6,8 @@
6
6
 
7
7
  goog.provide('shaka.util.FakeEvent');
8
8
 
9
+ goog.require('goog.asserts');
10
+
9
11
 
10
12
  /**
11
13
  * @summary Create an Event work-alike object based on the provided dictionary.
@@ -16,18 +18,62 @@ goog.provide('shaka.util.FakeEvent');
16
18
  */
17
19
  shaka.util.FakeEvent = class {
18
20
  /**
19
- * @param {string} type
20
- * @param {Object=} dict
21
+ * @param {!Event} event
22
+ * @return {!shaka.util.FakeEvent}
21
23
  */
22
- constructor(type, dict = {}) {
23
- // Take properties from dict if present.
24
- for (const key in dict) {
25
- Object.defineProperty(this, key, {
26
- value: dict[key],
24
+ static fromRealEvent(event) {
25
+ const fakeEvent = new shaka.util.FakeEvent(event.type);
26
+ for (const key in event) {
27
+ Object.defineProperty(fakeEvent, key, {
28
+ value: event[key],
27
29
  writable: true,
28
30
  enumerable: true,
29
31
  });
30
32
  }
33
+ return fakeEvent;
34
+ }
35
+
36
+ /**
37
+ * Allows us to tell the compiler that the dictionary "map" is actually a
38
+ * generic object, for backwards compatibility.
39
+ * @param {!Map.<string, Object>} dict
40
+ * @return {!Object}
41
+ * @suppress {invalidCasts}
42
+ * @private
43
+ */
44
+ static recastDictAsObject_(dict) {
45
+ goog.asserts.assert(!(dict instanceof Map), 'dict should not be a map');
46
+ return /** @type {!Object} */ (dict);
47
+ }
48
+
49
+ /**
50
+ * @param {string} type
51
+ * @param {Map.<string, Object>=} dict
52
+ */
53
+ constructor(type, dict) {
54
+ if (dict) {
55
+ if (dict instanceof Map) {
56
+ // Take properties from dict if present.
57
+ for (const key of dict.keys()) {
58
+ Object.defineProperty(this, key, {
59
+ value: dict.get(key),
60
+ writable: true,
61
+ enumerable: true,
62
+ });
63
+ }
64
+ } else {
65
+ // For backwards compatibility with external apps that may make use of
66
+ // this public constructor, this should still accept generic objects.
67
+ const obj = shaka.util.FakeEvent.recastDictAsObject_(dict);
68
+ for (const key in obj) {
69
+ Object.defineProperty(this, key, {
70
+ value: obj[key],
71
+ writable: true,
72
+ enumerable: true,
73
+ });
74
+ }
75
+ }
76
+ }
31
77
 
32
78
  // The properties below cannot be set by the dict. They are all provided
33
79
  // for compatibility with native events.
@@ -80,7 +80,10 @@ shaka.util.PeriodCombiner = class {
80
80
 
81
81
  /** @return {!Array.<shaka.extern.Stream>} */
82
82
  getTextStreams() {
83
- return this.textStreams_;
83
+ // Return a copy of the array because makeTextStreamsForClosedCaptions
84
+ // may make changes to the contents of the array. Those changes should not
85
+ // propagate back to the PeriodCombiner.
86
+ return this.textStreams_.slice();
84
87
  }
85
88
 
86
89
  /** @return {!Array.<shaka.extern.Stream>} */
@@ -163,7 +163,6 @@ shaka.util.Platform = class {
163
163
  !shaka.util.Platform.isEdge();
164
164
  }
165
165
 
166
-
167
166
  /**
168
167
  * Check if the current platform is from Apple.
169
168
  *
@@ -179,6 +178,19 @@ shaka.util.Platform = class {
179
178
  && !shaka.util.Platform.isTizen();
180
179
  }
181
180
 
181
+ /**
182
+ * Check if the current platform is Playstation 5.
183
+ *
184
+ * Returns true on Playstation 5 browsers.
185
+ *
186
+ * Returns false for Playstation 5 browsers
187
+ *
188
+ * @return {boolean}
189
+ */
190
+ static isPS5() {
191
+ return shaka.util.Platform.userAgentContains_('PlayStation 5');
192
+ }
193
+
182
194
  /**
183
195
  * Returns a major version number for Safari, or Safari-based iOS browsers.
184
196
  *
@@ -547,6 +547,19 @@ shaka.util.StreamUtils = class {
547
547
  // framerate must be greater than 0, otherwise the config is invalid.
548
548
  framerate: video.frameRate || 1,
549
549
  };
550
+ if (video.hdr) {
551
+ switch (video.hdr) {
552
+ case 'SDR':
553
+ mediaDecodingConfig.video.transferFunction = 'srgb';
554
+ break;
555
+ case 'PQ':
556
+ mediaDecodingConfig.video.transferFunction = 'pq';
557
+ break;
558
+ case 'HLG':
559
+ mediaDecodingConfig.video.transferFunction = 'hlg';
560
+ break;
561
+ }
562
+ }
550
563
  }
551
564
  if (audio) {
552
565
  // Some Tizen devices seem to misreport AC-3 support, but correctly
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "shaka-player",
3
3
  "description": "DASH/EME video player library",
4
- "version": "3.2.1",
4
+ "version": "3.2.2",
5
5
  "homepage": "https://github.com/google/shaka-player",
6
6
  "author": "Google",
7
7
  "maintainers": [
@@ -297,7 +297,8 @@ describe('CastProxy', () => {
297
297
  'timeupdate', Util.spyFunc(proxyListener));
298
298
 
299
299
  expect(proxyListener).not.toHaveBeenCalled();
300
- const fakeEvent = new FakeEvent('timeupdate', {detail: 8675309});
300
+ const fakeEvent = new FakeEvent(
301
+ 'timeupdate', (new Map()).set('detail', 8675309));
301
302
  mockVideo.on['timeupdate'](fakeEvent);
302
303
  expect(proxyListener).toHaveBeenCalledWith(jasmine.objectContaining({
303
304
  type: 'timeupdate',
@@ -315,7 +316,8 @@ describe('CastProxy', () => {
315
316
  mockSender.hasRemoteProperties.and.returnValue(true);
316
317
 
317
318
  expect(proxyListener).not.toHaveBeenCalled();
318
- const fakeEvent = new FakeEvent('timeupdate', {detail: 8675309});
319
+ const fakeEvent = new FakeEvent(
320
+ 'timeupdate', (new Map()).set('detail', 8675309));
319
321
  mockVideo.on['timeupdate'](fakeEvent);
320
322
  expect(proxyListener).not.toHaveBeenCalled();
321
323
  });
@@ -332,7 +334,8 @@ describe('CastProxy', () => {
332
334
  mockSender.hasRemoteProperties.and.returnValue(true);
333
335
 
334
336
  expect(proxyListener).not.toHaveBeenCalled();
335
- const fakeEvent = new FakeEvent('timeupdate', {detail: 8675309});
337
+ const fakeEvent = new FakeEvent(
338
+ 'timeupdate', (new Map()).set('detail', 8675309));
336
339
  mockSender.onRemoteEvent('video', fakeEvent);
337
340
  expect(proxyListener).toHaveBeenCalledWith(jasmine.objectContaining({
338
341
  type: 'timeupdate',
@@ -446,7 +449,8 @@ describe('CastProxy', () => {
446
449
  'buffering', Util.spyFunc(proxyListener));
447
450
 
448
451
  expect(proxyListener).not.toHaveBeenCalled();
449
- const fakeEvent = new FakeEvent('buffering', {detail: 8675309});
452
+ const fakeEvent = new FakeEvent(
453
+ 'buffering', (new Map()).set('detail', 8675309));
450
454
  mockPlayer.listeners['buffering'](fakeEvent);
451
455
  expect(proxyListener).toHaveBeenCalledWith(jasmine.objectContaining({
452
456
  type: 'buffering',
@@ -464,7 +468,8 @@ describe('CastProxy', () => {
464
468
  mockSender.hasRemoteProperties.and.returnValue(true);
465
469
 
466
470
  expect(proxyListener).not.toHaveBeenCalled();
467
- const fakeEvent = new FakeEvent('buffering', {detail: 8675309});
471
+ const fakeEvent = new FakeEvent(
472
+ 'buffering', (new Map()).set('detail', 8675309));
468
473
  mockPlayer.listeners['buffering'](fakeEvent);
469
474
  expect(proxyListener).not.toHaveBeenCalled();
470
475
  });
@@ -481,7 +486,8 @@ describe('CastProxy', () => {
481
486
  mockSender.hasRemoteProperties.and.returnValue(true);
482
487
 
483
488
  expect(proxyListener).not.toHaveBeenCalled();
484
- const fakeEvent = new FakeEvent('buffering', {detail: 8675309});
489
+ const fakeEvent = new FakeEvent(
490
+ 'buffering', (new Map()).set('detail', 8675309));
485
491
  mockSender.onRemoteEvent('player', fakeEvent);
486
492
  expect(proxyListener).toHaveBeenCalledWith(jasmine.objectContaining({
487
493
  type: 'buffering',
@@ -123,7 +123,7 @@ describe('CastUtils', () => {
123
123
  expect(typeof deserialized).toBe('object');
124
124
 
125
125
  // The object can be used to construct a FakeEvent.
126
- const fakeEvent = new FakeEvent(deserialized['type'], deserialized);
126
+ const fakeEvent = FakeEvent.fromRealEvent(deserialized);
127
127
 
128
128
  // The fake event has the same type and properties as the original.
129
129
  const asObj = /** @type {!Object} */ (fakeEvent);