rx-player 4.3.0-dev.2024112900 → 4.3.0-dev.2025012900
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/CHANGELOG.md +30 -8
- package/VERSION +1 -1
- package/dist/commonjs/__GENERATED_CODE/embedded_dash_wasm.d.ts +1 -1
- package/dist/commonjs/__GENERATED_CODE/embedded_dash_wasm.d.ts.map +1 -1
- package/dist/commonjs/__GENERATED_CODE/embedded_worker.d.ts.map +1 -1
- package/dist/commonjs/__GENERATED_CODE/embedded_worker.js +1 -1
- package/dist/commonjs/compat/browser_compatibility_types.d.ts +7 -2
- package/dist/commonjs/compat/browser_compatibility_types.d.ts.map +1 -1
- package/dist/commonjs/compat/browser_compatibility_types.js +0 -1
- package/dist/commonjs/compat/browser_detection.js +1 -1
- package/dist/commonjs/compat/event_listeners.d.ts.map +1 -1
- package/dist/commonjs/compat/event_listeners.js +2 -4
- package/dist/commonjs/compat/has_mse_in_worker.d.ts.map +1 -1
- package/dist/commonjs/core/cmcd/cmcd_data_builder.d.ts.map +1 -1
- package/dist/commonjs/core/cmcd/cmcd_data_builder.js +1 -2
- package/dist/commonjs/core/main/worker/send_message.d.ts.map +1 -1
- package/dist/commonjs/core/main/worker/send_message.js +0 -1
- package/dist/commonjs/core/main/worker/worker_main.js +1 -1
- package/dist/commonjs/core/stream/adaptation/adaptation_stream.d.ts.map +1 -1
- package/dist/commonjs/core/stream/adaptation/adaptation_stream.js +4 -8
- package/dist/commonjs/core/stream/period/period_stream.js +1 -3
- package/dist/commonjs/core/stream/period/utils/get_adaptation_switch_strategy.js +1 -2
- package/dist/commonjs/experimental/tools/mediaCapabilitiesProber/api/index.d.ts.map +1 -1
- package/dist/commonjs/main_thread/api/public_api.js +4 -4
- package/dist/commonjs/main_thread/decrypt/clear_on_stop.d.ts.map +1 -1
- package/dist/commonjs/main_thread/decrypt/clear_on_stop.js +60 -14
- package/dist/commonjs/main_thread/decrypt/content_decryptor.d.ts.map +1 -1
- package/dist/commonjs/main_thread/decrypt/content_decryptor.js +21 -9
- package/dist/commonjs/main_thread/decrypt/dispose_decryption_resources.d.ts.map +1 -1
- package/dist/commonjs/main_thread/decrypt/dispose_decryption_resources.js +2 -18
- package/dist/commonjs/main_thread/decrypt/find_key_system.d.ts.map +1 -1
- package/dist/commonjs/main_thread/decrypt/find_key_system.js +134 -68
- package/dist/commonjs/main_thread/decrypt/get_key_system_configuration.js +2 -2
- package/dist/commonjs/main_thread/decrypt/get_media_keys.js +5 -3
- package/dist/commonjs/main_thread/decrypt/init_media_keys.d.ts.map +1 -1
- package/dist/commonjs/main_thread/decrypt/init_media_keys.js +2 -2
- package/dist/{es2017/main_thread/decrypt/utils/media_keys_infos_store.d.ts → commonjs/main_thread/decrypt/utils/media_keys_attacher.d.ts} +31 -9
- package/dist/commonjs/main_thread/decrypt/utils/media_keys_attacher.d.ts.map +1 -0
- package/dist/commonjs/main_thread/decrypt/utils/media_keys_attacher.js +282 -0
- package/dist/commonjs/main_thread/init/utils/rebuffering_controller.d.ts.map +1 -1
- package/dist/commonjs/main_thread/init/utils/rebuffering_controller.js +20 -9
- package/dist/commonjs/main_thread/text_displayer/html/text_track_cues_store.js +1 -1
- package/dist/commonjs/main_thread/tracks_store/track_dispatcher.d.ts.map +1 -1
- package/dist/commonjs/main_thread/tracks_store/track_dispatcher.js +3 -4
- package/dist/commonjs/main_thread/tracks_store/tracks_store.d.ts.map +1 -1
- package/dist/commonjs/main_thread/tracks_store/tracks_store.js +1 -1
- package/dist/commonjs/manifest/classes/representation.d.ts +15 -1
- package/dist/commonjs/manifest/classes/representation.d.ts.map +1 -1
- package/dist/commonjs/manifest/classes/representation.js +17 -0
- package/dist/commonjs/manifest/utils.d.ts +15 -0
- package/dist/commonjs/manifest/utils.d.ts.map +1 -1
- package/dist/commonjs/manifest/utils.js +28 -5
- package/dist/commonjs/parsers/manifest/dash/common/parse_representations.js +2 -2
- package/dist/commonjs/playback_observer/media_element_playback_observer.js +1 -1
- package/dist/commonjs/public_types.d.ts +44 -0
- package/dist/commonjs/public_types.d.ts.map +1 -1
- package/dist/commonjs/utils/flat_map.d.ts +2 -2
- package/dist/commonjs/utils/flat_map.js +2 -2
- package/dist/commonjs/utils/url-utils.d.ts.map +1 -1
- package/dist/commonjs/utils/url-utils.js +11 -10
- package/dist/commonjs/utils/xml-parser.d.ts.map +1 -1
- package/dist/commonjs/utils/xml-parser.js +10 -8
- package/dist/es2017/__GENERATED_CODE/embedded_dash_wasm.d.ts +1 -1
- package/dist/es2017/__GENERATED_CODE/embedded_dash_wasm.d.ts.map +1 -1
- package/dist/es2017/__GENERATED_CODE/embedded_worker.d.ts.map +1 -1
- package/dist/es2017/__GENERATED_CODE/embedded_worker.js +1 -1
- package/dist/es2017/compat/browser_compatibility_types.d.ts +7 -2
- package/dist/es2017/compat/browser_compatibility_types.d.ts.map +1 -1
- package/dist/es2017/compat/browser_compatibility_types.js +0 -1
- package/dist/es2017/compat/browser_detection.js +1 -1
- package/dist/es2017/compat/event_listeners.d.ts.map +1 -1
- package/dist/es2017/compat/event_listeners.js +2 -4
- package/dist/es2017/compat/has_mse_in_worker.d.ts.map +1 -1
- package/dist/es2017/core/cmcd/cmcd_data_builder.d.ts.map +1 -1
- package/dist/es2017/core/cmcd/cmcd_data_builder.js +1 -2
- package/dist/es2017/core/main/worker/send_message.d.ts.map +1 -1
- package/dist/es2017/core/main/worker/send_message.js +0 -1
- package/dist/es2017/core/main/worker/worker_main.js +1 -1
- package/dist/es2017/core/stream/adaptation/adaptation_stream.d.ts.map +1 -1
- package/dist/es2017/core/stream/adaptation/adaptation_stream.js +4 -6
- package/dist/es2017/core/stream/period/period_stream.js +1 -3
- package/dist/es2017/core/stream/period/utils/get_adaptation_switch_strategy.js +1 -2
- package/dist/es2017/experimental/tools/mediaCapabilitiesProber/api/index.d.ts.map +1 -1
- package/dist/es2017/main_thread/api/public_api.js +4 -4
- package/dist/es2017/main_thread/decrypt/clear_on_stop.d.ts.map +1 -1
- package/dist/es2017/main_thread/decrypt/clear_on_stop.js +3 -3
- package/dist/es2017/main_thread/decrypt/content_decryptor.d.ts.map +1 -1
- package/dist/es2017/main_thread/decrypt/content_decryptor.js +21 -9
- package/dist/es2017/main_thread/decrypt/dispose_decryption_resources.d.ts.map +1 -1
- package/dist/es2017/main_thread/decrypt/dispose_decryption_resources.js +2 -12
- package/dist/es2017/main_thread/decrypt/find_key_system.d.ts.map +1 -1
- package/dist/es2017/main_thread/decrypt/find_key_system.js +102 -56
- package/dist/es2017/main_thread/decrypt/get_key_system_configuration.js +2 -2
- package/dist/es2017/main_thread/decrypt/get_media_keys.js +2 -2
- package/dist/es2017/main_thread/decrypt/init_media_keys.d.ts.map +1 -1
- package/dist/es2017/main_thread/decrypt/init_media_keys.js +2 -2
- package/dist/{commonjs/main_thread/decrypt/utils/media_keys_infos_store.d.ts → es2017/main_thread/decrypt/utils/media_keys_attacher.d.ts} +31 -9
- package/dist/es2017/main_thread/decrypt/utils/media_keys_attacher.d.ts.map +1 -0
- package/dist/es2017/main_thread/decrypt/utils/media_keys_attacher.js +180 -0
- package/dist/es2017/main_thread/init/utils/rebuffering_controller.d.ts.map +1 -1
- package/dist/es2017/main_thread/init/utils/rebuffering_controller.js +20 -9
- package/dist/es2017/main_thread/text_displayer/html/text_track_cues_store.js +1 -1
- package/dist/es2017/main_thread/tracks_store/track_dispatcher.d.ts.map +1 -1
- package/dist/es2017/main_thread/tracks_store/track_dispatcher.js +3 -4
- package/dist/es2017/main_thread/tracks_store/tracks_store.d.ts.map +1 -1
- package/dist/es2017/main_thread/tracks_store/tracks_store.js +2 -2
- package/dist/es2017/manifest/classes/representation.d.ts +15 -1
- package/dist/es2017/manifest/classes/representation.d.ts.map +1 -1
- package/dist/es2017/manifest/classes/representation.js +17 -0
- package/dist/es2017/manifest/utils.d.ts +15 -0
- package/dist/es2017/manifest/utils.d.ts.map +1 -1
- package/dist/es2017/manifest/utils.js +27 -5
- package/dist/es2017/parsers/manifest/dash/common/parse_representations.js +2 -2
- package/dist/es2017/playback_observer/media_element_playback_observer.js +1 -1
- package/dist/es2017/public_types.d.ts +44 -0
- package/dist/es2017/public_types.d.ts.map +1 -1
- package/dist/es2017/utils/flat_map.d.ts +2 -2
- package/dist/es2017/utils/flat_map.js +2 -2
- package/dist/es2017/utils/url-utils.d.ts.map +1 -1
- package/dist/es2017/utils/url-utils.js +11 -10
- package/dist/es2017/utils/xml-parser.d.ts.map +1 -1
- package/dist/es2017/utils/xml-parser.js +10 -8
- package/dist/rx-player.js +505 -372
- package/dist/rx-player.min.js +18 -18
- package/dist/worker.js +6 -6
- package/package.json +21 -19
- package/src/__GENERATED_CODE/embedded_worker.ts +1 -1
- package/src/compat/browser_compatibility_types.ts +22 -4
- package/src/compat/browser_detection.ts +1 -1
- package/src/compat/event_listeners.ts +2 -4
- package/src/compat/has_mse_in_worker.ts +1 -1
- package/src/core/cmcd/cmcd_data_builder.ts +1 -4
- package/src/core/main/worker/send_message.ts +4 -2
- package/src/core/main/worker/worker_main.ts +1 -1
- package/src/core/stream/adaptation/adaptation_stream.ts +4 -7
- package/src/core/stream/period/period_stream.ts +3 -3
- package/src/core/stream/period/utils/get_adaptation_switch_strategy.ts +1 -2
- package/src/main_thread/api/public_api.ts +4 -4
- package/src/main_thread/decrypt/__tests__/__global__/media_key_system_access.test.ts +239 -6
- package/src/main_thread/decrypt/__tests__/find_key_system.test.ts +325 -0
- package/src/main_thread/decrypt/clear_on_stop.ts +3 -3
- package/src/main_thread/decrypt/content_decryptor.ts +26 -8
- package/src/main_thread/decrypt/dispose_decryption_resources.ts +2 -13
- package/src/main_thread/decrypt/find_key_system.ts +120 -81
- package/src/main_thread/decrypt/get_key_system_configuration.ts +2 -2
- package/src/main_thread/decrypt/get_media_keys.ts +2 -2
- package/src/main_thread/decrypt/init_media_keys.ts +2 -2
- package/src/main_thread/decrypt/utils/media_keys_attacher.ts +284 -0
- package/src/main_thread/init/utils/rebuffering_controller.ts +20 -10
- package/src/main_thread/text_displayer/html/text_track_cues_store.ts +1 -1
- package/src/main_thread/tracks_store/track_dispatcher.ts +3 -6
- package/src/main_thread/tracks_store/tracks_store.ts +2 -1
- package/src/manifest/classes/representation.ts +18 -1
- package/src/manifest/utils.ts +30 -9
- package/src/parsers/manifest/dash/common/parse_representations.ts +2 -2
- package/src/playback_observer/media_element_playback_observer.ts +1 -1
- package/src/public_types.ts +45 -0
- package/src/utils/__tests__/flat_map.test.ts +7 -20
- package/src/utils/flat_map.ts +2 -2
- package/src/utils/url-utils.ts +11 -10
- package/src/utils/xml-parser.ts +13 -8
- package/vitest.config.mjs +9 -23
- package/dist/commonjs/main_thread/decrypt/attach_media_keys.d.ts +0 -60
- package/dist/commonjs/main_thread/decrypt/attach_media_keys.d.ts.map +0 -1
- package/dist/commonjs/main_thread/decrypt/attach_media_keys.js +0 -124
- package/dist/commonjs/main_thread/decrypt/utils/media_keys_infos_store.d.ts.map +0 -1
- package/dist/commonjs/main_thread/decrypt/utils/media_keys_infos_store.js +0 -45
- package/dist/es2017/main_thread/decrypt/attach_media_keys.d.ts +0 -60
- package/dist/es2017/main_thread/decrypt/attach_media_keys.d.ts.map +0 -1
- package/dist/es2017/main_thread/decrypt/attach_media_keys.js +0 -73
- package/dist/es2017/main_thread/decrypt/utils/media_keys_infos_store.d.ts.map +0 -1
- package/dist/es2017/main_thread/decrypt/utils/media_keys_infos_store.js +0 -43
- package/src/main_thread/decrypt/attach_media_keys.ts +0 -125
- package/src/main_thread/decrypt/utils/media_keys_infos_store.ts +0 -88
|
@@ -358,7 +358,7 @@ export default class TextTrackCuesStore {
|
|
|
358
358
|
}
|
|
359
359
|
}
|
|
360
360
|
|
|
361
|
-
if (cuesBuffer.length) {
|
|
361
|
+
if (cuesBuffer.length > 0) {
|
|
362
362
|
const lastCue = cuesBuffer[cuesBuffer.length - 1];
|
|
363
363
|
if (areNearlyEqual(lastCue.end, start, relativeDelta)) {
|
|
364
364
|
// Match the end of the previous cue to the start of the following one
|
|
@@ -4,6 +4,7 @@ import type {
|
|
|
4
4
|
ITrackSwitchingMode,
|
|
5
5
|
} from "../../core/types";
|
|
6
6
|
import type { IAdaptationMetadata, IRepresentationMetadata } from "../../manifest";
|
|
7
|
+
import { isRepresentationPlayable } from "../../manifest";
|
|
7
8
|
import type {
|
|
8
9
|
IAudioRepresentationsSwitchingMode,
|
|
9
10
|
IVideoRepresentationsSwitchingMode,
|
|
@@ -184,11 +185,7 @@ export default class TrackDispatcher extends EventEmitter<ITrackDispatcherEvent>
|
|
|
184
185
|
if (repSettings === null) {
|
|
185
186
|
// unlocking
|
|
186
187
|
playableRepresentations = trackInfo.adaptation.representations.filter(
|
|
187
|
-
(representation) =>
|
|
188
|
-
return (
|
|
189
|
-
representation.isSupported === true && representation.decipherable !== false
|
|
190
|
-
);
|
|
191
|
-
},
|
|
188
|
+
(representation) => isRepresentationPlayable(representation) === true,
|
|
192
189
|
);
|
|
193
190
|
|
|
194
191
|
// No need to remove the previous content when unlocking
|
|
@@ -200,7 +197,7 @@ export default class TrackDispatcher extends EventEmitter<ITrackDispatcherEvent>
|
|
|
200
197
|
arrayIncludes(representationIds, r.id),
|
|
201
198
|
);
|
|
202
199
|
playableRepresentations = representations.filter(
|
|
203
|
-
(
|
|
200
|
+
(representation) => isRepresentationPlayable(representation) === true,
|
|
204
201
|
);
|
|
205
202
|
if (playableRepresentations.length === 0) {
|
|
206
203
|
self.trigger("noPlayableLockedRepresentation", null);
|
|
@@ -30,6 +30,7 @@ import type {
|
|
|
30
30
|
} from "../../manifest";
|
|
31
31
|
import {
|
|
32
32
|
getSupportedAdaptations,
|
|
33
|
+
isRepresentationPlayable,
|
|
33
34
|
toAudioTrack,
|
|
34
35
|
toTextTrack,
|
|
35
36
|
toVideoTrack,
|
|
@@ -399,7 +400,7 @@ export default class TracksStore extends EventEmitter<ITracksStoreEvents> {
|
|
|
399
400
|
return false;
|
|
400
401
|
}
|
|
401
402
|
const playableRepresentations = adaptation.representations.filter(
|
|
402
|
-
(r) => r
|
|
403
|
+
(r) => isRepresentationPlayable(r) === true,
|
|
403
404
|
);
|
|
404
405
|
return playableRepresentations.length > 0;
|
|
405
406
|
},
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
import log from "../../log";
|
|
18
|
-
import type
|
|
18
|
+
import { isRepresentationPlayable, type IRepresentationMetadata } from "../../manifest";
|
|
19
19
|
import type {
|
|
20
20
|
ICdnMetadata,
|
|
21
21
|
IContentProtections,
|
|
@@ -429,6 +429,23 @@ class Representation implements IRepresentationMetadata {
|
|
|
429
429
|
return true;
|
|
430
430
|
}
|
|
431
431
|
|
|
432
|
+
/**
|
|
433
|
+
* Returns `true` if the `Representation` has a high chance of being playable on
|
|
434
|
+
* the current device (its codec seems supported and we don't consider it to be
|
|
435
|
+
* un-decipherable).
|
|
436
|
+
*
|
|
437
|
+
* Returns `false` if the `Representation` has a high chance of being unplayable
|
|
438
|
+
* on the current device (its codec seems unsupported and/or we consider it to
|
|
439
|
+
* be un-decipherable).
|
|
440
|
+
*
|
|
441
|
+
* Returns `undefined` if we don't know as the codec has not been checked yet.
|
|
442
|
+
*
|
|
443
|
+
* @returns {boolean|undefined}
|
|
444
|
+
*/
|
|
445
|
+
public isPlayable(): boolean | undefined {
|
|
446
|
+
return isRepresentationPlayable(this);
|
|
447
|
+
}
|
|
448
|
+
|
|
432
449
|
/**
|
|
433
450
|
* Format the current `Representation`'s properties into a
|
|
434
451
|
* `IRepresentationMetadata` format which can better be communicated through
|
package/src/manifest/utils.ts
CHANGED
|
@@ -237,9 +237,7 @@ export function toAudioTrack(
|
|
|
237
237
|
audioDescription: adaptation.isAudioDescription === true,
|
|
238
238
|
id: adaptation.id,
|
|
239
239
|
representations: (filterPlayable
|
|
240
|
-
? adaptation.representations.filter(
|
|
241
|
-
(r) => r.isSupported === true && r.decipherable !== false,
|
|
242
|
-
)
|
|
240
|
+
? adaptation.representations.filter((r) => isRepresentationPlayable(r))
|
|
243
241
|
: adaptation.representations
|
|
244
242
|
).map(toAudioRepresentation),
|
|
245
243
|
label: adaptation.label,
|
|
@@ -283,7 +281,7 @@ export function toVideoTrack(
|
|
|
283
281
|
const representations = (
|
|
284
282
|
filterPlayable
|
|
285
283
|
? trickModeAdaptation.representations.filter(
|
|
286
|
-
(r) => r
|
|
284
|
+
(r) => isRepresentationPlayable(r) === true,
|
|
287
285
|
)
|
|
288
286
|
: trickModeAdaptation.representations
|
|
289
287
|
).map(toVideoRepresentation);
|
|
@@ -302,9 +300,7 @@ export function toVideoTrack(
|
|
|
302
300
|
const videoTrack: IVideoTrack = {
|
|
303
301
|
id: adaptation.id,
|
|
304
302
|
representations: (filterPlayable
|
|
305
|
-
? adaptation.representations.filter(
|
|
306
|
-
(r) => r.isSupported === true && r.decipherable !== false,
|
|
307
|
-
)
|
|
303
|
+
? adaptation.representations.filter((r) => isRepresentationPlayable(r) === true)
|
|
308
304
|
: adaptation.representations
|
|
309
305
|
).map(toVideoRepresentation),
|
|
310
306
|
label: adaptation.label,
|
|
@@ -389,6 +385,29 @@ export function toTaggedTrack(adaptation: IAdaptation): ITaggedTrack {
|
|
|
389
385
|
}
|
|
390
386
|
}
|
|
391
387
|
|
|
388
|
+
/**
|
|
389
|
+
* Returns `true` if the `Representation` has a high chance of being playable on
|
|
390
|
+
* the current device (its codec seems supported and we don't consider it to be
|
|
391
|
+
* un-decipherable).
|
|
392
|
+
*
|
|
393
|
+
* Returns `false` if the `Representation` has a high chance of being unplayable
|
|
394
|
+
* on the current device (its codec seems unsupported and/or we consider it to
|
|
395
|
+
* be un-decipherable).
|
|
396
|
+
*
|
|
397
|
+
* Returns `undefined` if we don't know as the codec has not been checked yet.
|
|
398
|
+
*
|
|
399
|
+
* @param {Object} representation
|
|
400
|
+
* @returns {boolean|undefined}
|
|
401
|
+
*/
|
|
402
|
+
export function isRepresentationPlayable(
|
|
403
|
+
representation: IRepresentationMetadata,
|
|
404
|
+
): boolean | undefined {
|
|
405
|
+
if (representation.decipherable === false) {
|
|
406
|
+
return false;
|
|
407
|
+
}
|
|
408
|
+
return representation.isSupported;
|
|
409
|
+
}
|
|
410
|
+
|
|
392
411
|
/**
|
|
393
412
|
* Information on a Representation affected by a `decipherabilityUpdates` event.
|
|
394
413
|
*/
|
|
@@ -558,7 +577,8 @@ export function replicateUpdatesOnManifestMetadata(
|
|
|
558
577
|
) {
|
|
559
578
|
for (const prop of Object.keys(newManifest)) {
|
|
560
579
|
if (prop !== "periods") {
|
|
561
|
-
//
|
|
580
|
+
// trust me bro
|
|
581
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access
|
|
562
582
|
(baseManifest as any)[prop] = (newManifest as any)[prop];
|
|
563
583
|
}
|
|
564
584
|
}
|
|
@@ -579,7 +599,8 @@ export function replicateUpdatesOnManifestMetadata(
|
|
|
579
599
|
const basePeriod = baseManifest.periods[periodIdx];
|
|
580
600
|
for (const prop of Object.keys(newPeriod)) {
|
|
581
601
|
if (prop !== "adaptations") {
|
|
582
|
-
//
|
|
602
|
+
// trust me bro
|
|
603
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access
|
|
583
604
|
(basePeriod as any)[prop] = (newPeriod as any)[prop];
|
|
584
605
|
}
|
|
585
606
|
}
|
|
@@ -94,7 +94,7 @@ function getHDRInformation({
|
|
|
94
94
|
return { eotf: "hlg" };
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
|
-
if (codecs !== undefined && /^vp(08|09|10)/.
|
|
97
|
+
if (codecs !== undefined && /^vp(08|09|10)/.test(codecs)) {
|
|
98
98
|
return getWEBMHDRInformation(codecs);
|
|
99
99
|
}
|
|
100
100
|
}
|
|
@@ -205,7 +205,7 @@ export default function parseRepresentations(
|
|
|
205
205
|
(r) =>
|
|
206
206
|
r.schemeIdUri === "tag:dolby.com,2018:dash:EC3_ExtensionType:2018" &&
|
|
207
207
|
r.value === "JOC",
|
|
208
|
-
)
|
|
208
|
+
) !== undefined
|
|
209
209
|
) {
|
|
210
210
|
parsedRepresentation.isSpatialAudio = true;
|
|
211
211
|
}
|
|
@@ -837,7 +837,7 @@ function getFreezingStatus(
|
|
|
837
837
|
bufferGap: number | undefined,
|
|
838
838
|
): IFreezingStatus | null {
|
|
839
839
|
const { MINIMUM_BUFFER_AMOUNT_BEFORE_FREEZING } = config.getCurrent();
|
|
840
|
-
if (prevObservation.freezing) {
|
|
840
|
+
if (prevObservation.freezing !== null) {
|
|
841
841
|
if (
|
|
842
842
|
currentInfo.ended ||
|
|
843
843
|
currentInfo.paused ||
|
package/src/public_types.ts
CHANGED
|
@@ -558,6 +558,51 @@ export interface IKeySystemOption {
|
|
|
558
558
|
* `MediaKeySystemConfiguration` according to the EME API.
|
|
559
559
|
*/
|
|
560
560
|
distinctiveIdentifier?: MediaKeysRequirement | undefined;
|
|
561
|
+
|
|
562
|
+
/**
|
|
563
|
+
* Force a `sessionTypes` value for the corresponding
|
|
564
|
+
* `MediaKeySystemConfiguration` asked when creating a
|
|
565
|
+
* `MediaKeySystemAccess` (the EME API concept).
|
|
566
|
+
*
|
|
567
|
+
* If not set, the RxPlayer will automatically ask for the most adapted
|
|
568
|
+
* `sessionTypes` based on your configuration for the current content. As
|
|
569
|
+
* such, this option is only needed for very specific usages.
|
|
570
|
+
*
|
|
571
|
+
* A case where you might want to set this value is if for example you want
|
|
572
|
+
* the ability to be able to load both temporary and persistent licenses,
|
|
573
|
+
* regardless of the configuration applied to the current content.
|
|
574
|
+
* Setting in that case `wantedSessionTypes` to
|
|
575
|
+
* `["temporary", "persistent-license"]` will lead, if compatible, to the
|
|
576
|
+
* creation of a `MediaKeySystemAccess` able to handle both:
|
|
577
|
+
* - contents relying on temporary licenses, and:
|
|
578
|
+
* - contents relying on persistent licenses
|
|
579
|
+
*
|
|
580
|
+
* The RxPlayer will then be able to keep that same `MediaKeySystemAccess` on
|
|
581
|
+
* future `loadVideo` calls as long as they rely on either all or a subset of
|
|
582
|
+
* those session types - and as long as the rest of the new wanted
|
|
583
|
+
* configuration is also considered compatible with that `MediaKeySystemAccess`.
|
|
584
|
+
*
|
|
585
|
+
* Moreover, because our `MediaKeySession` cache (see `maxSessionCacheSize`)
|
|
586
|
+
* is linked to a `MediaKeySystemAccess`, keeping the same one allows the
|
|
587
|
+
* RxPlayer to also keep the same cache (whereas changing
|
|
588
|
+
* `MediaKeySystemAccess` when changing contents resets that cache).
|
|
589
|
+
*
|
|
590
|
+
* Note that the current device has to be compatible to _ALL_ `sessionTypes`
|
|
591
|
+
* for that configuration to go through.
|
|
592
|
+
*
|
|
593
|
+
* Notes
|
|
594
|
+
* -----
|
|
595
|
+
*
|
|
596
|
+
* If this value is set to an array which does not contain
|
|
597
|
+
* `"persistent-license"`, we will assume that no persistent license will be
|
|
598
|
+
* requested for the current content, regardless of the
|
|
599
|
+
* `persistentLicenseConfig` option.
|
|
600
|
+
*
|
|
601
|
+
* If this value only contains `"persistent-license"` but the
|
|
602
|
+
* `persistentLicenseConfig` option is not set, we will load persistent
|
|
603
|
+
* licenses yet not persist them.
|
|
604
|
+
*/
|
|
605
|
+
wantedSessionTypes?: string[] | undefined;
|
|
561
606
|
/**
|
|
562
607
|
* If true, all open `MediaKeySession` (JavaScript Objects linked to the keys
|
|
563
608
|
* used to decrypt the content) will be closed when the current playback
|
|
@@ -1,23 +1,12 @@
|
|
|
1
1
|
import { describe, beforeEach, afterEach, it, expect, vi } from "vitest";
|
|
2
2
|
import flatMap from "../flat_map";
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
flatMap?:
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
index: number,
|
|
11
|
-
array: unknown[],
|
|
12
|
-
) => U | U[],
|
|
13
|
-
thisArg?: This | undefined,
|
|
14
|
-
) => U[])
|
|
15
|
-
| undefined;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const proto = Array.prototype as unknown as IProtoWithFlatMap;
|
|
19
|
-
|
|
20
|
-
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
4
|
+
type ICustomArrayProto = Omit<typeof Array.prototype, "flatMap"> & {
|
|
5
|
+
flatMap?: typeof Array.prototype.flatMap | undefined;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
const proto: ICustomArrayProto = Array.prototype;
|
|
9
|
+
|
|
21
10
|
const initialFlatMap = proto.flatMap;
|
|
22
11
|
|
|
23
12
|
describe("utils - starts-with", () => {
|
|
@@ -39,9 +28,7 @@ describe("utils - starts-with", () => {
|
|
|
39
28
|
if (typeof initialFlatMap === "function") {
|
|
40
29
|
it("should call the original flatMap function if available", () => {
|
|
41
30
|
proto.flatMap = initialFlatMap;
|
|
42
|
-
|
|
43
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
44
|
-
const mockFlatMap = vi.spyOn(proto as any, "flatMap");
|
|
31
|
+
const mockFlatMap = vi.spyOn(Array.prototype, "flatMap");
|
|
45
32
|
const func1 = (x: number): number[] => [x, x + 1, x - 1];
|
|
46
33
|
const func2 = (x: number): string => String(x) + "a";
|
|
47
34
|
expect(flatMap([1, 2, 3], func1)).toEqual([1, 2, 0, 2, 3, 1, 3, 4, 2]);
|
package/src/utils/flat_map.ts
CHANGED
|
@@ -25,8 +25,8 @@ type ArrayWithFlatMap<T> = T[] & {
|
|
|
25
25
|
/**
|
|
26
26
|
* Map each element using a mapping function, then flat the result into
|
|
27
27
|
* a new array.
|
|
28
|
-
* @param {Array.<*>}
|
|
29
|
-
* @param {Function}
|
|
28
|
+
* @param {Array.<*>} originalArray
|
|
29
|
+
* @param {Function} fn
|
|
30
30
|
*/
|
|
31
31
|
export default function flatMap<T, U>(originalArray: T[], fn: (arg: T) => U[] | U): U[] {
|
|
32
32
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
package/src/utils/url-utils.ts
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
+
import isNonEmptyString from "./is_non_empty_string";
|
|
17
18
|
import startsWith from "./starts_with";
|
|
18
19
|
|
|
19
20
|
// Scheme part of an url (e.g. "http://").
|
|
@@ -135,12 +136,12 @@ function getRelativeUrl(baseUrl: string, newUrl: string): string | null {
|
|
|
135
136
|
let result = relativePath;
|
|
136
137
|
if (relativePath === "" && newParts.query === baseParts.query) {
|
|
137
138
|
// path and query is the same, we don't need to rewrite it
|
|
138
|
-
} else if (newParts.query) {
|
|
139
|
+
} else if (isNonEmptyString(newParts.query)) {
|
|
139
140
|
result += "?";
|
|
140
141
|
result += newParts.query;
|
|
141
142
|
}
|
|
142
143
|
|
|
143
|
-
if (newParts.fragment) {
|
|
144
|
+
if (isNonEmptyString(newParts.fragment)) {
|
|
144
145
|
result += "#";
|
|
145
146
|
result += newParts.fragment;
|
|
146
147
|
}
|
|
@@ -160,7 +161,7 @@ function _resolveURL(base: string, relative: string) {
|
|
|
160
161
|
const baseParts = parseURL(base);
|
|
161
162
|
const relativeParts = parseURL(relative);
|
|
162
163
|
|
|
163
|
-
if (relativeParts.scheme) {
|
|
164
|
+
if (isNonEmptyString(relativeParts.scheme)) {
|
|
164
165
|
return formatURL(relativeParts);
|
|
165
166
|
}
|
|
166
167
|
|
|
@@ -172,7 +173,7 @@ function _resolveURL(base: string, relative: string) {
|
|
|
172
173
|
fragment: relativeParts.fragment,
|
|
173
174
|
};
|
|
174
175
|
|
|
175
|
-
if (relativeParts.authority) {
|
|
176
|
+
if (isNonEmptyString(relativeParts.authority)) {
|
|
176
177
|
target.authority = relativeParts.authority;
|
|
177
178
|
target.path = removeDotSegment(relativeParts.path);
|
|
178
179
|
return formatURL(target);
|
|
@@ -180,7 +181,7 @@ function _resolveURL(base: string, relative: string) {
|
|
|
180
181
|
|
|
181
182
|
if (relativeParts.path === "") {
|
|
182
183
|
target.path = baseParts.path;
|
|
183
|
-
if (!relativeParts.query) {
|
|
184
|
+
if (!isNonEmptyString(relativeParts.query)) {
|
|
184
185
|
target.query = baseParts.query;
|
|
185
186
|
}
|
|
186
187
|
} else {
|
|
@@ -255,20 +256,20 @@ function parseURL(url: string): IParsedURL {
|
|
|
255
256
|
*/
|
|
256
257
|
function formatURL(parts: IParsedURL): string {
|
|
257
258
|
let url = "";
|
|
258
|
-
if (parts.scheme) {
|
|
259
|
+
if (isNonEmptyString(parts.scheme)) {
|
|
259
260
|
url += parts.scheme + ":";
|
|
260
261
|
}
|
|
261
262
|
|
|
262
|
-
if (parts.authority) {
|
|
263
|
+
if (isNonEmptyString(parts.authority)) {
|
|
263
264
|
url += "//" + parts.authority;
|
|
264
265
|
}
|
|
265
266
|
url += parts.path;
|
|
266
267
|
|
|
267
|
-
if (parts.query) {
|
|
268
|
+
if (isNonEmptyString(parts.query)) {
|
|
268
269
|
url += "?" + parts.query;
|
|
269
270
|
}
|
|
270
271
|
|
|
271
|
-
if (parts.fragment) {
|
|
272
|
+
if (isNonEmptyString(parts.fragment)) {
|
|
272
273
|
url += "#" + parts.fragment;
|
|
273
274
|
}
|
|
274
275
|
return url;
|
|
@@ -321,7 +322,7 @@ function removeDotSegment(path: string): string {
|
|
|
321
322
|
* @see https://datatracker.ietf.org/doc/html/rfc3986#section-5.2.3
|
|
322
323
|
*/
|
|
323
324
|
function mergePaths(baseParts: IParsedURL, relativePath: string): string {
|
|
324
|
-
if (baseParts.authority && baseParts.path === "") {
|
|
325
|
+
if (isNonEmptyString(baseParts.authority) && baseParts.path === "") {
|
|
325
326
|
return "/" + relativePath;
|
|
326
327
|
}
|
|
327
328
|
const basePath = baseParts.path;
|
package/src/utils/xml-parser.ts
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
* https://github.com/TobiasNickel/tXml
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import isNonEmptyString from "./is_non_empty_string";
|
|
10
|
+
|
|
9
11
|
// import arrayIncludes from "./array_includes";
|
|
10
12
|
|
|
11
13
|
/**
|
|
@@ -94,7 +96,7 @@ function parseXml(src: string, options: ITParseOptions = {}): Array<ITNode | str
|
|
|
94
96
|
out = parseChildren("");
|
|
95
97
|
}
|
|
96
98
|
|
|
97
|
-
if (options.filter) {
|
|
99
|
+
if (options.filter !== undefined) {
|
|
98
100
|
out = filter(out, options.filter);
|
|
99
101
|
}
|
|
100
102
|
return out;
|
|
@@ -106,7 +108,7 @@ function parseXml(src: string, options: ITParseOptions = {}): Array<ITNode | str
|
|
|
106
108
|
*/
|
|
107
109
|
function parseChildren(tagName: string): Array<ITNode | string> {
|
|
108
110
|
const children: Array<ITNode | string> = [];
|
|
109
|
-
while (src[pos]) {
|
|
111
|
+
while (src[pos] !== undefined) {
|
|
110
112
|
if (src.charCodeAt(pos) === openBracketCC) {
|
|
111
113
|
if (src.charCodeAt(pos + 1) === slashCC) {
|
|
112
114
|
const closeStart = pos + 2;
|
|
@@ -170,7 +172,10 @@ function parseXml(src: string, options: ITParseOptions = {}): Array<ITNode | str
|
|
|
170
172
|
const startDoctype = pos + 1;
|
|
171
173
|
pos += 2;
|
|
172
174
|
let encapsuled = false;
|
|
173
|
-
while (
|
|
175
|
+
while (
|
|
176
|
+
(src.charCodeAt(pos) !== closeBracketCC || encapsuled) &&
|
|
177
|
+
src[pos] !== undefined
|
|
178
|
+
) {
|
|
174
179
|
if (src.charCodeAt(pos) === openCornerBracketCC) {
|
|
175
180
|
encapsuled = true;
|
|
176
181
|
} else if (encapsuled && src.charCodeAt(pos) === closeCornerBracketCC) {
|
|
@@ -221,7 +226,7 @@ function parseXml(src: string, options: ITParseOptions = {}): Array<ITNode | str
|
|
|
221
226
|
|
|
222
227
|
function parseName(): string {
|
|
223
228
|
const start = pos;
|
|
224
|
-
while (nameSpacer.indexOf(src[pos]) === -1 && src[pos]) {
|
|
229
|
+
while (nameSpacer.indexOf(src[pos]) === -1 && src[pos] !== undefined) {
|
|
225
230
|
pos++;
|
|
226
231
|
}
|
|
227
232
|
return src.slice(start, pos);
|
|
@@ -235,7 +240,7 @@ function parseXml(src: string, options: ITParseOptions = {}): Array<ITNode | str
|
|
|
235
240
|
let children: Array<ITNode | string> = [];
|
|
236
241
|
|
|
237
242
|
// parsing attributes
|
|
238
|
-
while (src.charCodeAt(pos) !== closeBracketCC && src[pos]) {
|
|
243
|
+
while (src.charCodeAt(pos) !== closeBracketCC && src[pos] !== undefined) {
|
|
239
244
|
const c = src.charCodeAt(pos);
|
|
240
245
|
if ((c > 64 && c < 91) || (c > 96 && c < 123)) {
|
|
241
246
|
// if('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.indexOf(src[pos])!==-1 ){
|
|
@@ -243,7 +248,7 @@ function parseXml(src: string, options: ITParseOptions = {}): Array<ITNode | str
|
|
|
243
248
|
// search beginning of the string
|
|
244
249
|
let code = src.charCodeAt(pos);
|
|
245
250
|
while (
|
|
246
|
-
code &&
|
|
251
|
+
!isNaN(code) &&
|
|
247
252
|
code !== singleQuoteCC &&
|
|
248
253
|
code !== doubleQuoteCC &&
|
|
249
254
|
!((code > 64 && code < 91) || (code > 96 && code < 123)) &&
|
|
@@ -298,7 +303,7 @@ function parseXml(src: string, options: ITParseOptions = {}): Array<ITNode | str
|
|
|
298
303
|
const r = new RegExp(
|
|
299
304
|
"\\s" + options.attrName + "\\s*=['\"]" + options.attrValue + "['\"]",
|
|
300
305
|
).exec(src);
|
|
301
|
-
if (r) {
|
|
306
|
+
if (r !== null) {
|
|
302
307
|
return r.index;
|
|
303
308
|
} else {
|
|
304
309
|
return -1;
|
|
@@ -328,7 +333,7 @@ function filter(
|
|
|
328
333
|
child.children,
|
|
329
334
|
f,
|
|
330
335
|
dept + 1,
|
|
331
|
-
(path ? path + "." : "") + i + "." + child.tagName,
|
|
336
|
+
(isNonEmptyString(path) ? path + "." : "") + i + "." + child.tagName,
|
|
332
337
|
);
|
|
333
338
|
out = out.concat(kids);
|
|
334
339
|
}
|
package/vitest.config.mjs
CHANGED
|
@@ -1,22 +1,4 @@
|
|
|
1
1
|
import { defineConfig } from "vitest/config";
|
|
2
|
-
import { promises as fs } from "fs";
|
|
3
|
-
|
|
4
|
-
// https://github.com/tachibana-shin/vite-plugin-arraybuffer/blob/main/src/main.ts
|
|
5
|
-
function vitePluginArraybuffer() {
|
|
6
|
-
return {
|
|
7
|
-
name: "array-buffer-loader",
|
|
8
|
-
async load(id) {
|
|
9
|
-
if (id.endsWith("?arraybuffer")) {
|
|
10
|
-
const filePath = id.replace(/\?arraybuffer$/, "");
|
|
11
|
-
const fileBuffer = await fs.readFile(filePath);
|
|
12
|
-
return {
|
|
13
|
-
code: `export default new Uint8Array([${new Uint8Array(fileBuffer).join(",")}]).buffer`,
|
|
14
|
-
map: { mappings: "" },
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
},
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
2
|
|
|
21
3
|
function getBrowserConfig(browser) {
|
|
22
4
|
switch (browser) {
|
|
@@ -69,7 +51,6 @@ function getBrowserConfig(browser) {
|
|
|
69
51
|
}
|
|
70
52
|
|
|
71
53
|
export default defineConfig({
|
|
72
|
-
plugins: [vitePluginArraybuffer()],
|
|
73
54
|
define: {
|
|
74
55
|
// global variables
|
|
75
56
|
__TEST_CONTENT_SERVER__: {
|
|
@@ -90,9 +71,14 @@ export default defineConfig({
|
|
|
90
71
|
watch: false,
|
|
91
72
|
globals: false,
|
|
92
73
|
reporters: "dot",
|
|
93
|
-
include: [
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
74
|
+
include: [
|
|
75
|
+
// integration tests
|
|
76
|
+
"tests/integration/scenarios/**/*.[jt]s?(x)",
|
|
77
|
+
"tests/integration/**/*.test.[jt]s?(x)",
|
|
78
|
+
// memory tests
|
|
79
|
+
"tests/memory/**/*.[jt]s?(x)",
|
|
80
|
+
],
|
|
81
|
+
globalSetup: "tests/globalSetup.mjs",
|
|
82
|
+
browser: getBrowserConfig(process.env.BROWSER_CONFIG ?? "chrome"),
|
|
97
83
|
},
|
|
98
84
|
});
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright 2015 CANAL+ Group
|
|
3
|
-
*
|
|
4
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
* you may not use this file except in compliance with the License.
|
|
6
|
-
* You may obtain a copy of the License at
|
|
7
|
-
*
|
|
8
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
*
|
|
10
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
* See the License for the specific language governing permissions and
|
|
14
|
-
* limitations under the License.
|
|
15
|
-
*/
|
|
16
|
-
import type { IMediaElement } from "../../compat/browser_compatibility_types";
|
|
17
|
-
import type { ICustomMediaKeys, ICustomMediaKeySystemAccess, IEmeApiImplementation } from "../../compat/eme";
|
|
18
|
-
import type { IKeySystemOption } from "../../public_types";
|
|
19
|
-
import type { CancellationSignal } from "../../utils/task_canceller";
|
|
20
|
-
import type LoadedSessionsStore from "./utils/loaded_sessions_store";
|
|
21
|
-
/**
|
|
22
|
-
* Dispose of the MediaKeys instance attached to the given media element, if
|
|
23
|
-
* one.
|
|
24
|
-
* @param {Object} mediaElement
|
|
25
|
-
* @returns {Promise}
|
|
26
|
-
*/
|
|
27
|
-
export declare function disableMediaKeys(mediaElement: IMediaElement): Promise<unknown>;
|
|
28
|
-
/**
|
|
29
|
-
* Attach MediaKeys and its associated state to an HTMLMediaElement.
|
|
30
|
-
*
|
|
31
|
-
* /!\ Mutates heavily MediaKeysInfosStore
|
|
32
|
-
* @param {HTMLMediaElement} mediaElement
|
|
33
|
-
* @param {Object} mediaKeysInfos
|
|
34
|
-
* @param {Object} cancelSignal
|
|
35
|
-
* @returns {Promise}
|
|
36
|
-
*/
|
|
37
|
-
export default function attachMediaKeys(mediaElement: IMediaElement, { emeImplementation, keySystemOptions, askedConfiguration, loadedSessionsStore, mediaKeySystemAccess, mediaKeys, }: IMediaKeysState, cancelSignal: CancellationSignal): Promise<void>;
|
|
38
|
-
/** MediaKeys and associated state attached to a media element. */
|
|
39
|
-
export interface IMediaKeysState {
|
|
40
|
-
/** Options set when the MediaKeys has been attached. */
|
|
41
|
-
keySystemOptions: IKeySystemOption;
|
|
42
|
-
/** LoadedSessionsStore associated to the MediaKeys instance. */
|
|
43
|
-
loadedSessionsStore: LoadedSessionsStore;
|
|
44
|
-
/** The MediaKeySystemAccess allowing to create MediaKeys instances. */
|
|
45
|
-
mediaKeySystemAccess: MediaKeySystemAccess | ICustomMediaKeySystemAccess;
|
|
46
|
-
/** The MediaKeys instance to attach to the media element. */
|
|
47
|
-
mediaKeys: MediaKeys | ICustomMediaKeys;
|
|
48
|
-
/**
|
|
49
|
-
* The MediaKeySystemConfiguration that has been provided to the
|
|
50
|
-
* `requestMediaKeySystemAccess` API.
|
|
51
|
-
*/
|
|
52
|
-
askedConfiguration: MediaKeySystemConfiguration;
|
|
53
|
-
/**
|
|
54
|
-
* The chosen EME implementation abstraction linked to `mediaKeys`.
|
|
55
|
-
* Different EME implementation might for example be used while debugging or
|
|
56
|
-
* work-arounding EME-linked device issues.
|
|
57
|
-
*/
|
|
58
|
-
emeImplementation: IEmeApiImplementation;
|
|
59
|
-
}
|
|
60
|
-
//# sourceMappingURL=attach_media_keys.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"attach_media_keys.d.ts","sourceRoot":"","sources":["../../../../src/main_thread/decrypt/attach_media_keys.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0CAA0C,CAAC;AAC9E,OAAO,KAAK,EACV,gBAAgB,EAChB,2BAA2B,EAC3B,qBAAqB,EACtB,MAAM,kBAAkB,CAAC;AAK1B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,KAAK,mBAAmB,MAAM,+BAA+B,CAAC;AAGrE;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,CAI9E;AAED;;;;;;;;GAQG;AACH,wBAA8B,eAAe,CAC3C,YAAY,EAAE,aAAa,EAC3B,EACE,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,SAAS,GACV,EAAE,eAAe,EAClB,YAAY,EAAE,kBAAkB,GAC/B,OAAO,CAAC,IAAI,CAAC,CAsCf;AAED,kEAAkE;AAClE,MAAM,WAAW,eAAe;IAC9B,wDAAwD;IACxD,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,gEAAgE;IAChE,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,uEAAuE;IACvE,oBAAoB,EAAE,oBAAoB,GAAG,2BAA2B,CAAC;IACzE,6DAA6D;IAC7D,SAAS,EAAE,SAAS,GAAG,gBAAgB,CAAC;IACxC;;;OAGG;IACH,kBAAkB,EAAE,2BAA2B,CAAC;IAChD;;;;OAIG;IACH,iBAAiB,EAAE,qBAAqB,CAAC;CAC1C"}
|