diff --git a/api-extractor/report/hls.js.api.md b/api-extractor/report/hls.js.api.md index 099c59241b3..2d780afb20b 100644 --- a/api-extractor/report/hls.js.api.md +++ b/api-extractor/report/hls.js.api.md @@ -2995,7 +2995,7 @@ export class KeyLoader implements ComponentAPI { // (undocumented) load(frag: Fragment): Promise; // (undocumented) - loadClear(loadingFrag: Fragment, encryptedFragments: Fragment[]): null | Promise; + loadClear(loadingFrag: Fragment, encryptedFragments: Fragment[], startFragRequested: boolean): null | Promise; // (undocumented) loadInternal(frag: Fragment, keySystemFormat?: KeySystemFormats): Promise; // (undocumented) @@ -3339,7 +3339,7 @@ export class LevelDetails { // // @public (undocumented) export class LevelKey implements DecryptData { - constructor(method: string, uri: string, format: string, formatversions?: number[], iv?: Uint8Array | null); + constructor(method: string, uri: string, format: string, formatversions?: number[], iv?: Uint8Array | null, keyId?: string); // (undocumented) static clearKeyUriToKeyIdMap(): void; // (undocumented) @@ -3361,6 +3361,8 @@ export class LevelKey implements DecryptData { // (undocumented) keyId: Uint8Array | null; // (undocumented) + matches(key: LevelKey): boolean; + // (undocumented) readonly method: string; // (undocumented) pssh: Uint8Array | null; diff --git a/package-lock.json b/package-lock.json index fcb83b43e83..a538965a2ee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,13 +7,13 @@ "name": "hls.js", "license": "Apache-2.0", "devDependencies": { - "@babel/core": "7.27.4", + "@babel/core": "7.28.0", "@babel/helper-module-imports": "7.27.1", "@babel/plugin-proposal-class-properties": "7.18.6", "@babel/plugin-proposal-object-rest-spread": "7.20.7", "@babel/plugin-proposal-optional-chaining": "7.21.0", "@babel/plugin-transform-object-assign": "7.27.1", - "@babel/preset-env": "7.27.2", + "@babel/preset-env": "7.28.0", "@babel/preset-typescript": "7.27.1", "@babel/register": "7.27.1", "@microsoft/api-documenter": "7.26.29", @@ -24,8 +24,8 @@ "@rollup/plugin-node-resolve": "16.0.1", "@rollup/plugin-replace": "6.0.2", "@rollup/plugin-terser": "0.4.4", - "@rollup/plugin-typescript": "12.1.3", - "@svta/common-media-library": "0.14.0", + "@rollup/plugin-typescript": "12.1.4", + "@svta/common-media-library": "0.15.1", "@types/chai": "4.3.20", "@types/chart.js": "2.9.41", "@types/mocha": "10.0.10", @@ -69,7 +69,7 @@ "rollup": "4.44.1", "rollup-plugin-istanbul": "5.0.0", "sauce-connect-launcher": "1.3.2", - "selenium-webdriver": "4.33.0", + "selenium-webdriver": "4.34.0", "semver": "7.7.2", "sinon": "19.0.5", "sinon-chai": "3.7.0", @@ -115,30 +115,30 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.2.tgz", - "integrity": "sha512-TUtMJYRPyUb/9aU8f3K0mjmjf6M9N5Woshn2CS6nqJSeJtTtQcpLUXjGt9vbF8ZGff0El99sWkLgzwW3VXnxZQ==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.0.tgz", + "integrity": "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.27.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.4.tgz", - "integrity": "sha512-bXYxrXFubeYdvB0NhD/NBB3Qi6aZeV20GOWVI47t2dkecCEoneR4NPVcb7abpXDEvejgrUfFtG6vG/zxAKmg+g==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.0.tgz", + "integrity": "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.27.3", + "@babel/generator": "^7.28.0", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-module-transforms": "^7.27.3", - "@babel/helpers": "^7.27.4", - "@babel/parser": "^7.27.4", + "@babel/helpers": "^7.27.6", + "@babel/parser": "^7.28.0", "@babel/template": "^7.27.2", - "@babel/traverse": "^7.27.4", - "@babel/types": "^7.27.3", + "@babel/traverse": "^7.28.0", + "@babel/types": "^7.28.0", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -163,15 +163,15 @@ } }, "node_modules/@babel/generator": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.3.tgz", - "integrity": "sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.0.tgz", + "integrity": "sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==", "dev": true, "dependencies": { - "@babel/parser": "^7.27.3", - "@babel/types": "^7.27.3", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", + "@babel/parser": "^7.28.0", + "@babel/types": "^7.28.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" }, "engines": { @@ -179,26 +179,22 @@ } }, "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "version": "0.3.12", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz", + "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==", "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" } }, "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.1.tgz", - "integrity": "sha512-WnuuDILl9oOBbKnb4L+DyODx7iC47XfzmNCpTttFsSp6hTG7XZxu60+4IO+2/hPfcGOoKbFiwoI/+zwARbNQow==", + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", + "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", "dev": true, "dependencies": { - "@babel/types": "^7.27.1" + "@babel/types": "^7.27.3" }, "engines": { "node": ">=6.9.0" @@ -301,21 +297,53 @@ } }, "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.3.tgz", - "integrity": "sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg==", + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.5.tgz", + "integrity": "sha512-uJnGFcPsWQK8fvjgGP5LZUZZsYGIoPeRjSF5PGwrelYgq7Q15/Ft9NGFp1zglwgIv//W0uG4BevRuSJRyylZPg==", "dev": true, "dependencies": { - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "debug": "^4.1.1", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-plugin-utils": "^7.27.1", + "debug": "^4.4.1", "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2" + "resolve": "^1.22.10" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, + "node_modules/@babel/helper-define-polyfill-provider/node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/helper-define-polyfill-provider/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-member-expression-to-functions": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.27.1.tgz", @@ -469,25 +497,25 @@ } }, "node_modules/@babel/helpers": { - "version": "7.27.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.4.tgz", - "integrity": "sha512-Y+bO6U+I7ZKaM5G5rDUZiYfUvQPUibYmAFe7EnKdnKBbVXDZxvp+MWOH5gYciY0EPk4EScsuFMQBbEfpdRKSCQ==", + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.6.tgz", + "integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==", "dev": true, "dependencies": { "@babel/template": "^7.27.2", - "@babel/types": "^7.27.3" + "@babel/types": "^7.27.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.27.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.4.tgz", - "integrity": "sha512-BRmLHGwpUqLFR2jzx9orBuX/ABDkj2jLKOXrHDTN2aOKL+jFDDKaRNo9nyYsIl9h/UE/7lMKdDjKQQyxKKDZ7g==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz", + "integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==", "dev": true, "dependencies": { - "@babel/types": "^7.27.3" + "@babel/types": "^7.28.0" }, "bin": { "parser": "bin/babel-parser.js" @@ -755,14 +783,14 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.27.1.tgz", - "integrity": "sha512-eST9RrwlpaoJBDHShc+DS2SG4ATTi2MYNb4OxYkf3n+7eb49LWpnS+HSpVfW4x927qQwgk8A2hGNVaajAEw0EA==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.28.0.tgz", + "integrity": "sha512-BEOdvX4+M765icNPZeidyADIvQ1m1gmunXufXxvRESy/jNNyfovIqUyE7MVgGBjWktCoJlzvFA1To2O4ymIO3Q==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-remap-async-to-generator": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/traverse": "^7.28.0" }, "engines": { "node": ">=6.9.0" @@ -804,9 +832,9 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.27.1.tgz", - "integrity": "sha512-QEcFlMl9nGTgh1rn2nIeU5bkfb9BAjaQcWbiP4LvKxUot52ABcTkpcyJ7f2Q2U2RuQ84BNLgts3jRme2dTx6Fw==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.0.tgz", + "integrity": "sha512-gKKnwjpdx5sER/wl0WN0efUBFzF/56YZO0RJrSYP4CljXnP31ByY7fol89AzomdlLNzI36AvOTmYHsnZTCkq8Q==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -851,17 +879,17 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.27.1.tgz", - "integrity": "sha512-7iLhfFAubmpeJe/Wo2TVuDrykh/zlWXLzPNdL0Jqn/Xu8R3QQ8h9ff8FQoISZOsw74/HFqFI7NX63HN7QFIHKA==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.0.tgz", + "integrity": "sha512-IjM1IoJNw72AZFlj33Cu8X0q2XK/6AaVC3jQu+cgQ5lThWD5ajnuUAml80dqRmOhmPkTH8uAwnpMu9Rvj0LTRA==", "dev": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-compilation-targets": "^7.27.1", + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-globals": "^7.28.0", "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-replace-supers": "^7.27.1", - "@babel/traverse": "^7.27.1", - "globals": "^11.1.0" + "@babel/traverse": "^7.28.0" }, "engines": { "node": ">=6.9.0" @@ -887,12 +915,13 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.27.1.tgz", - "integrity": "sha512-ttDCqhfvpE9emVkXbPD8vyxxh4TWYACVybGkDj+oReOGwnp066ITEivDlLwe0b1R0+evJ13IXQuLNB5w1fhC5Q==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.0.tgz", + "integrity": "sha512-v1nrSMBiKcodhsyJ4Gf+Z0U/yawmJDBOTpEB3mcQY52r9RIyPneGyAS/yM6seP/8I+mWI3elOMtT5dB8GJVs+A==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.28.0" }, "engines": { "node": ">=6.9.0" @@ -963,6 +992,22 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-explicit-resource-management": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.28.0.tgz", + "integrity": "sha512-K8nhUcn3f6iB+P3gwCv/no7OdzOZQcKchW6N389V6PD8NUWKZHzndOd9sPDVbMoBsbmjMqlB4L9fm+fEFNVlwQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-transform-destructuring": "^7.28.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-transform-exponentiation-operator": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.27.1.tgz", @@ -1229,15 +1274,16 @@ } }, "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.27.2.tgz", - "integrity": "sha512-AIUHD7xJ1mCrj3uPozvtngY3s0xpv7Nu7DoUSnzNY6Xam1Cy4rUznR//pvMHOhQ4AvbCexhbqXCtpxGHOGOO6g==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.0.tgz", + "integrity": "sha512-9VNGikXxzu5eCiQjdE4IZn8sb9q7Xsk5EXLDBKUYg1e/Tve8/05+KJEtcxGxAgCY5t/BpKQM+JEL/yT4tvgiUA==", "dev": true, "dependencies": { "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-plugin-utils": "^7.27.1", - "@babel/plugin-transform-destructuring": "^7.27.1", - "@babel/plugin-transform-parameters": "^7.27.1" + "@babel/plugin-transform-destructuring": "^7.28.0", + "@babel/plugin-transform-parameters": "^7.27.7", + "@babel/traverse": "^7.28.0" }, "engines": { "node": ">=6.9.0" @@ -1294,9 +1340,9 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.1.tgz", - "integrity": "sha512-018KRk76HWKeZ5l4oTj2zPpSh+NbGdt0st5S6x0pga6HgrjBOJb24mMDHorFopOOd6YHkLgOZ+zaCjZGPO4aKg==", + "version": "7.27.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.7.tgz", + "integrity": "sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1357,9 +1403,9 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.27.1.tgz", - "integrity": "sha512-B19lbbL7PMrKr52BNPjCqg1IyNUIjTcxKj8uX9zHO+PmWN93s19NDr/f69mIkEp2x9nmDJ08a7lgHaTTzvW7mw==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.28.0.tgz", + "integrity": "sha512-LOAozRVbqxEVjSKfhGnuLoE4Kz4Oc5UJzuvFUhSsQzdCdaAQu06mG8zDv2GFSerM62nImUZ7K92vxnQcLSDlCQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1561,12 +1607,12 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.27.2.tgz", - "integrity": "sha512-Ma4zSuYSlGNRlCLO+EAzLnCmJK2vdstgv+n7aUP+/IKZrOfWHOJVdSJtuub8RzHTj3ahD37k5OKJWvzf16TQyQ==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.28.0.tgz", + "integrity": "sha512-VmaxeGOwuDqzLl5JUkIRM1X2Qu2uKGxHEQWh+cvvbl7JuJRgKGJSfsEF/bUaxFhJl/XAyxBe7q7qSuTbKFuCyg==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.27.2", + "@babel/compat-data": "^7.28.0", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-validator-option": "^7.27.1", @@ -1580,19 +1626,20 @@ "@babel/plugin-syntax-import-attributes": "^7.27.1", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", "@babel/plugin-transform-arrow-functions": "^7.27.1", - "@babel/plugin-transform-async-generator-functions": "^7.27.1", + "@babel/plugin-transform-async-generator-functions": "^7.28.0", "@babel/plugin-transform-async-to-generator": "^7.27.1", "@babel/plugin-transform-block-scoped-functions": "^7.27.1", - "@babel/plugin-transform-block-scoping": "^7.27.1", + "@babel/plugin-transform-block-scoping": "^7.28.0", "@babel/plugin-transform-class-properties": "^7.27.1", "@babel/plugin-transform-class-static-block": "^7.27.1", - "@babel/plugin-transform-classes": "^7.27.1", + "@babel/plugin-transform-classes": "^7.28.0", "@babel/plugin-transform-computed-properties": "^7.27.1", - "@babel/plugin-transform-destructuring": "^7.27.1", + "@babel/plugin-transform-destructuring": "^7.28.0", "@babel/plugin-transform-dotall-regex": "^7.27.1", "@babel/plugin-transform-duplicate-keys": "^7.27.1", "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.27.1", "@babel/plugin-transform-dynamic-import": "^7.27.1", + "@babel/plugin-transform-explicit-resource-management": "^7.28.0", "@babel/plugin-transform-exponentiation-operator": "^7.27.1", "@babel/plugin-transform-export-namespace-from": "^7.27.1", "@babel/plugin-transform-for-of": "^7.27.1", @@ -1609,15 +1656,15 @@ "@babel/plugin-transform-new-target": "^7.27.1", "@babel/plugin-transform-nullish-coalescing-operator": "^7.27.1", "@babel/plugin-transform-numeric-separator": "^7.27.1", - "@babel/plugin-transform-object-rest-spread": "^7.27.2", + "@babel/plugin-transform-object-rest-spread": "^7.28.0", "@babel/plugin-transform-object-super": "^7.27.1", "@babel/plugin-transform-optional-catch-binding": "^7.27.1", "@babel/plugin-transform-optional-chaining": "^7.27.1", - "@babel/plugin-transform-parameters": "^7.27.1", + "@babel/plugin-transform-parameters": "^7.27.7", "@babel/plugin-transform-private-methods": "^7.27.1", "@babel/plugin-transform-private-property-in-object": "^7.27.1", "@babel/plugin-transform-property-literals": "^7.27.1", - "@babel/plugin-transform-regenerator": "^7.27.1", + "@babel/plugin-transform-regenerator": "^7.28.0", "@babel/plugin-transform-regexp-modifiers": "^7.27.1", "@babel/plugin-transform-reserved-words": "^7.27.1", "@babel/plugin-transform-shorthand-properties": "^7.27.1", @@ -1630,10 +1677,10 @@ "@babel/plugin-transform-unicode-regex": "^7.27.1", "@babel/plugin-transform-unicode-sets-regex": "^7.27.1", "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.11.0", - "babel-plugin-polyfill-regenerator": "^0.6.1", - "core-js-compat": "^3.40.0", + "babel-plugin-polyfill-corejs2": "^0.4.14", + "babel-plugin-polyfill-corejs3": "^0.13.0", + "babel-plugin-polyfill-regenerator": "^0.6.5", + "core-js-compat": "^3.43.0", "semver": "^6.3.1" }, "engines": { @@ -1719,27 +1766,27 @@ } }, "node_modules/@babel/traverse": { - "version": "7.27.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.4.tgz", - "integrity": "sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.0.tgz", + "integrity": "sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==", "dev": true, "dependencies": { "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.27.3", - "@babel/parser": "^7.27.4", + "@babel/generator": "^7.28.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.0", "@babel/template": "^7.27.2", - "@babel/types": "^7.27.3", - "debug": "^4.3.1", - "globals": "^11.1.0" + "@babel/types": "^7.28.0", + "debug": "^4.3.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/types": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.3.tgz", - "integrity": "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz", + "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==", "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.27.1", @@ -3022,9 +3069,9 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "version": "0.3.29", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz", + "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -3388,9 +3435,9 @@ } }, "node_modules/@rollup/plugin-typescript": { - "version": "12.1.3", - "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-12.1.3.tgz", - "integrity": "sha512-gAx0AYwkyjqOw4JrZV34N/abvAobLhczyLkZ7FVL2UXPrO4zv8oqTfYT3DLBRan1EXasp4SUuEJXqPTk0gnJzw==", + "version": "12.1.4", + "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-12.1.4.tgz", + "integrity": "sha512-s5Hx+EtN60LMlDBvl5f04bEiFZmAepk27Q+mr85L/00zPDn1jtzlTV6FWn81MaIwqfWzKxmOJrBWHU6vtQyedQ==", "dev": true, "dependencies": { "@rollup/pluginutils": "^5.1.0", @@ -3897,10 +3944,13 @@ "dev": true }, "node_modules/@svta/common-media-library": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@svta/common-media-library/-/common-media-library-0.14.0.tgz", - "integrity": "sha512-MJRmqRq/n96YZIVQxZbt1RlLCX10w2rLrw0IPNw0fCkaD9k1B97J+zDYwCTgAm7L54Qu6pDWTJ1wKoYb2e+pUw==", - "dev": true + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/@svta/common-media-library/-/common-media-library-0.15.1.tgz", + "integrity": "sha512-Ig26anQU/MVRxrikBv1cMmeJqhXG683jxA7q9iscoMygcYd4+XmLjM0kcshZ574izow4X+j/NcU5vTrvVXF9sQ==", + "dev": true, + "engines": { + "node": ">=20" + } }, "node_modules/@testim/chrome-version": { "version": "1.1.4", @@ -4974,13 +5024,13 @@ } }, "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.10", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.10.tgz", - "integrity": "sha512-rpIuu//y5OX6jVU+a5BCn1R5RSZYWAl2Nar76iwaOdycqb6JPxediskWFMMl7stfwNJR4b7eiQvh5fB5TEQJTQ==", + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.14.tgz", + "integrity": "sha512-Co2Y9wX854ts6U8gAAPXfn0GmAyctHuK8n0Yhfjd6t30g7yvKjspvvOo9yG+z52PZRgFErt7Ka2pYnXCjLKEpg==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.6.1", + "@babel/compat-data": "^7.27.7", + "@babel/helper-define-polyfill-provider": "^0.6.5", "semver": "^6.3.1" }, "peerDependencies": { @@ -4997,25 +5047,25 @@ } }, "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.11.1.tgz", - "integrity": "sha512-yGCqvBT4rwMczo28xkH/noxJ6MZ4nJfkVYdoDaC/utLtWrXxv27HVrzAeSbqR8SxDsp46n0YF47EbHoixy6rXQ==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.13.0.tgz", + "integrity": "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==", "dev": true, "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.3", - "core-js-compat": "^3.40.0" + "@babel/helper-define-polyfill-provider": "^0.6.5", + "core-js-compat": "^3.43.0" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.1.tgz", - "integrity": "sha512-JfTApdE++cgcTWjsiCQlLyFBMbTUft9ja17saCc93lgV33h4tuCVj7tlvu//qpLwaG+3yEz7/KhahGrUMkVq9g==", + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.5.tgz", + "integrity": "sha512-ISqQ2frbiNU9vIJkzg7dlPpznPZ4jOiUQ1uSmB0fEHeowtN3COYRsXr/xexn64NpU13P06jc/L5TgiJXOgrbEg==", "dev": true, "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.1" + "@babel/helper-define-polyfill-provider": "^0.6.5" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" @@ -5156,9 +5206,9 @@ "dev": true }, "node_modules/browserslist": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", - "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", + "version": "4.25.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz", + "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==", "dev": true, "funding": [ { @@ -5175,10 +5225,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001688", - "electron-to-chromium": "^1.5.73", + "caniuse-lite": "^1.0.30001726", + "electron-to-chromium": "^1.5.173", "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.1" + "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" @@ -5268,9 +5318,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001699", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001699.tgz", - "integrity": "sha512-b+uH5BakXZ9Do9iK+CkDmctUSEqZl+SP056vc5usa0PL+ev5OHw003rZXcnjNDv3L8P5j6rwT6C0BPKSikW08w==", + "version": "1.0.30001726", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001726.tgz", + "integrity": "sha512-VQAUIUzBiZ/UnlM28fSp2CRF3ivUn1BWEvxMcVTNwpw91Py1pGbPIyIKtd+tzct9C3ouceCVdGAXxZOpZAsgdw==", "dev": true, "funding": [ { @@ -5725,12 +5775,12 @@ } }, "node_modules/core-js-compat": { - "version": "3.40.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.40.0.tgz", - "integrity": "sha512-0XEDpr5y5mijvw8Lbc6E5AkjrHfp7eEoPlu36SWeAbcL8fn1G1ANe8DBlo2XoNN89oVpxWwOjYIPVzR4ZvsKCQ==", + "version": "3.43.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.43.0.tgz", + "integrity": "sha512-2GML2ZsCc5LR7hZYz4AXmjQw8zuy2T//2QntwdnpuYI7jteT6GVYJL7F6C2C57R7gSYrcqVW3lAALefdbhBLDA==", "dev": true, "dependencies": { - "browserslist": "^4.24.3" + "browserslist": "^4.25.0" }, "funding": { "type": "opencollective", @@ -6166,9 +6216,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.5.101", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.101.tgz", - "integrity": "sha512-L0ISiQrP/56Acgu4/i/kfPwWSgrzYZUnQrC0+QPFuhqlLP1Ir7qzPPDVS9BcKIyWTRU8+o6CC8dKw38tSWhYIA==", + "version": "1.5.179", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.179.tgz", + "integrity": "sha512-UWKi/EbBopgfFsc5k61wFpV7WrnnSlSzW/e2XcBmS6qKYTivZlLtoll5/rdqRTxGglGHkmkW0j0pFNJG10EUIQ==", "dev": true }, "node_modules/emoji-regex": { @@ -7897,15 +7947,6 @@ "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "dev": true }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/globalthis": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", @@ -12042,18 +12083,21 @@ "dev": true }, "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", "dev": true, "dependencies": { - "is-core-module": "^2.13.0", + "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -12346,9 +12390,9 @@ "dev": true }, "node_modules/selenium-webdriver": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-4.33.0.tgz", - "integrity": "sha512-5vRhk4iI0B9nYbEitfnCjPDXBfG6o9DNhj5DG2355eQo8idETknhj1tigqqlkHsGephSZwLZqEm/d+3e1stGUA==", + "version": "4.34.0", + "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-4.34.0.tgz", + "integrity": "sha512-zGfQFcsASAv3KrYzYh+iw4fFqB7iZAgHW7BU6rRz7isK1i1X4x3LvjmZad4bUUgHDwTnAhlqTzDh21byB+zHMg==", "dev": true, "funding": [ { @@ -12364,10 +12408,31 @@ "@bazel/runfiles": "^6.3.1", "jszip": "^3.10.1", "tmp": "^0.2.3", - "ws": "^8.18.0" + "ws": "^8.18.2" }, "engines": { - "node": ">= 18.20.5" + "node": ">= 20.0.0" + } + }, + "node_modules/selenium-webdriver/node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, "node_modules/semver": { @@ -13824,9 +13889,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz", - "integrity": "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", "dev": true, "funding": [ { @@ -14786,27 +14851,27 @@ } }, "@babel/compat-data": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.2.tgz", - "integrity": "sha512-TUtMJYRPyUb/9aU8f3K0mjmjf6M9N5Woshn2CS6nqJSeJtTtQcpLUXjGt9vbF8ZGff0El99sWkLgzwW3VXnxZQ==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.0.tgz", + "integrity": "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==", "dev": true }, "@babel/core": { - "version": "7.27.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.4.tgz", - "integrity": "sha512-bXYxrXFubeYdvB0NhD/NBB3Qi6aZeV20GOWVI47t2dkecCEoneR4NPVcb7abpXDEvejgrUfFtG6vG/zxAKmg+g==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.0.tgz", + "integrity": "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==", "dev": true, "requires": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.27.3", + "@babel/generator": "^7.28.0", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-module-transforms": "^7.27.3", - "@babel/helpers": "^7.27.4", - "@babel/parser": "^7.27.4", + "@babel/helpers": "^7.27.6", + "@babel/parser": "^7.28.0", "@babel/template": "^7.27.2", - "@babel/traverse": "^7.27.4", - "@babel/types": "^7.27.3", + "@babel/traverse": "^7.28.0", + "@babel/types": "^7.28.0", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -14823,38 +14888,37 @@ } }, "@babel/generator": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.3.tgz", - "integrity": "sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.0.tgz", + "integrity": "sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==", "dev": true, "requires": { - "@babel/parser": "^7.27.3", - "@babel/types": "^7.27.3", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", + "@babel/parser": "^7.28.0", + "@babel/types": "^7.28.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" }, "dependencies": { "@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "version": "0.3.12", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz", + "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==", "dev": true, "requires": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } } } }, "@babel/helper-annotate-as-pure": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.1.tgz", - "integrity": "sha512-WnuuDILl9oOBbKnb4L+DyODx7iC47XfzmNCpTttFsSp6hTG7XZxu60+4IO+2/hPfcGOoKbFiwoI/+zwARbNQow==", + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", + "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", "dev": true, "requires": { - "@babel/types": "^7.27.1" + "@babel/types": "^7.27.3" } }, "@babel/helper-compilation-targets": { @@ -14936,18 +15000,41 @@ } }, "@babel/helper-define-polyfill-provider": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.3.tgz", - "integrity": "sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg==", + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.5.tgz", + "integrity": "sha512-uJnGFcPsWQK8fvjgGP5LZUZZsYGIoPeRjSF5PGwrelYgq7Q15/Ft9NGFp1zglwgIv//W0uG4BevRuSJRyylZPg==", "dev": true, "requires": { - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "debug": "^4.1.1", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-plugin-utils": "^7.27.1", + "debug": "^4.4.1", "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2" + "resolve": "^1.22.10" + }, + "dependencies": { + "debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "dev": true, + "requires": { + "ms": "^2.1.3" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + } } }, + "@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true + }, "@babel/helper-member-expression-to-functions": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.27.1.tgz", @@ -15056,22 +15143,22 @@ } }, "@babel/helpers": { - "version": "7.27.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.4.tgz", - "integrity": "sha512-Y+bO6U+I7ZKaM5G5rDUZiYfUvQPUibYmAFe7EnKdnKBbVXDZxvp+MWOH5gYciY0EPk4EScsuFMQBbEfpdRKSCQ==", + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.6.tgz", + "integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==", "dev": true, "requires": { "@babel/template": "^7.27.2", - "@babel/types": "^7.27.3" + "@babel/types": "^7.27.6" } }, "@babel/parser": { - "version": "7.27.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.4.tgz", - "integrity": "sha512-BRmLHGwpUqLFR2jzx9orBuX/ABDkj2jLKOXrHDTN2aOKL+jFDDKaRNo9nyYsIl9h/UE/7lMKdDjKQQyxKKDZ7g==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz", + "integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==", "dev": true, "requires": { - "@babel/types": "^7.27.3" + "@babel/types": "^7.28.0" } }, "@babel/plugin-bugfix-firefox-class-in-computed-class-key": { @@ -15238,14 +15325,14 @@ } }, "@babel/plugin-transform-async-generator-functions": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.27.1.tgz", - "integrity": "sha512-eST9RrwlpaoJBDHShc+DS2SG4ATTi2MYNb4OxYkf3n+7eb49LWpnS+HSpVfW4x927qQwgk8A2hGNVaajAEw0EA==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.28.0.tgz", + "integrity": "sha512-BEOdvX4+M765icNPZeidyADIvQ1m1gmunXufXxvRESy/jNNyfovIqUyE7MVgGBjWktCoJlzvFA1To2O4ymIO3Q==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-remap-async-to-generator": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/traverse": "^7.28.0" } }, "@babel/plugin-transform-async-to-generator": { @@ -15269,9 +15356,9 @@ } }, "@babel/plugin-transform-block-scoping": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.27.1.tgz", - "integrity": "sha512-QEcFlMl9nGTgh1rn2nIeU5bkfb9BAjaQcWbiP4LvKxUot52ABcTkpcyJ7f2Q2U2RuQ84BNLgts3jRme2dTx6Fw==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.0.tgz", + "integrity": "sha512-gKKnwjpdx5sER/wl0WN0efUBFzF/56YZO0RJrSYP4CljXnP31ByY7fol89AzomdlLNzI36AvOTmYHsnZTCkq8Q==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.27.1" @@ -15298,17 +15385,17 @@ } }, "@babel/plugin-transform-classes": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.27.1.tgz", - "integrity": "sha512-7iLhfFAubmpeJe/Wo2TVuDrykh/zlWXLzPNdL0Jqn/Xu8R3QQ8h9ff8FQoISZOsw74/HFqFI7NX63HN7QFIHKA==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.0.tgz", + "integrity": "sha512-IjM1IoJNw72AZFlj33Cu8X0q2XK/6AaVC3jQu+cgQ5lThWD5ajnuUAml80dqRmOhmPkTH8uAwnpMu9Rvj0LTRA==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-compilation-targets": "^7.27.1", + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-globals": "^7.28.0", "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-replace-supers": "^7.27.1", - "@babel/traverse": "^7.27.1", - "globals": "^11.1.0" + "@babel/traverse": "^7.28.0" } }, "@babel/plugin-transform-computed-properties": { @@ -15322,12 +15409,13 @@ } }, "@babel/plugin-transform-destructuring": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.27.1.tgz", - "integrity": "sha512-ttDCqhfvpE9emVkXbPD8vyxxh4TWYACVybGkDj+oReOGwnp066ITEivDlLwe0b1R0+evJ13IXQuLNB5w1fhC5Q==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.0.tgz", + "integrity": "sha512-v1nrSMBiKcodhsyJ4Gf+Z0U/yawmJDBOTpEB3mcQY52r9RIyPneGyAS/yM6seP/8I+mWI3elOMtT5dB8GJVs+A==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.28.0" } }, "@babel/plugin-transform-dotall-regex": { @@ -15368,6 +15456,16 @@ "@babel/helper-plugin-utils": "^7.27.1" } }, + "@babel/plugin-transform-explicit-resource-management": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.28.0.tgz", + "integrity": "sha512-K8nhUcn3f6iB+P3gwCv/no7OdzOZQcKchW6N389V6PD8NUWKZHzndOd9sPDVbMoBsbmjMqlB4L9fm+fEFNVlwQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-transform-destructuring": "^7.28.0" + } + }, "@babel/plugin-transform-exponentiation-operator": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.27.1.tgz", @@ -15532,15 +15630,16 @@ } }, "@babel/plugin-transform-object-rest-spread": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.27.2.tgz", - "integrity": "sha512-AIUHD7xJ1mCrj3uPozvtngY3s0xpv7Nu7DoUSnzNY6Xam1Cy4rUznR//pvMHOhQ4AvbCexhbqXCtpxGHOGOO6g==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.0.tgz", + "integrity": "sha512-9VNGikXxzu5eCiQjdE4IZn8sb9q7Xsk5EXLDBKUYg1e/Tve8/05+KJEtcxGxAgCY5t/BpKQM+JEL/yT4tvgiUA==", "dev": true, "requires": { "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-plugin-utils": "^7.27.1", - "@babel/plugin-transform-destructuring": "^7.27.1", - "@babel/plugin-transform-parameters": "^7.27.1" + "@babel/plugin-transform-destructuring": "^7.28.0", + "@babel/plugin-transform-parameters": "^7.27.7", + "@babel/traverse": "^7.28.0" } }, "@babel/plugin-transform-object-super": { @@ -15573,9 +15672,9 @@ } }, "@babel/plugin-transform-parameters": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.1.tgz", - "integrity": "sha512-018KRk76HWKeZ5l4oTj2zPpSh+NbGdt0st5S6x0pga6HgrjBOJb24mMDHorFopOOd6YHkLgOZ+zaCjZGPO4aKg==", + "version": "7.27.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.7.tgz", + "integrity": "sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.27.1" @@ -15612,9 +15711,9 @@ } }, "@babel/plugin-transform-regenerator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.27.1.tgz", - "integrity": "sha512-B19lbbL7PMrKr52BNPjCqg1IyNUIjTcxKj8uX9zHO+PmWN93s19NDr/f69mIkEp2x9nmDJ08a7lgHaTTzvW7mw==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.28.0.tgz", + "integrity": "sha512-LOAozRVbqxEVjSKfhGnuLoE4Kz4Oc5UJzuvFUhSsQzdCdaAQu06mG8zDv2GFSerM62nImUZ7K92vxnQcLSDlCQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.27.1" @@ -15738,12 +15837,12 @@ } }, "@babel/preset-env": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.27.2.tgz", - "integrity": "sha512-Ma4zSuYSlGNRlCLO+EAzLnCmJK2vdstgv+n7aUP+/IKZrOfWHOJVdSJtuub8RzHTj3ahD37k5OKJWvzf16TQyQ==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.28.0.tgz", + "integrity": "sha512-VmaxeGOwuDqzLl5JUkIRM1X2Qu2uKGxHEQWh+cvvbl7JuJRgKGJSfsEF/bUaxFhJl/XAyxBe7q7qSuTbKFuCyg==", "dev": true, "requires": { - "@babel/compat-data": "^7.27.2", + "@babel/compat-data": "^7.28.0", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-validator-option": "^7.27.1", @@ -15757,19 +15856,20 @@ "@babel/plugin-syntax-import-attributes": "^7.27.1", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", "@babel/plugin-transform-arrow-functions": "^7.27.1", - "@babel/plugin-transform-async-generator-functions": "^7.27.1", + "@babel/plugin-transform-async-generator-functions": "^7.28.0", "@babel/plugin-transform-async-to-generator": "^7.27.1", "@babel/plugin-transform-block-scoped-functions": "^7.27.1", - "@babel/plugin-transform-block-scoping": "^7.27.1", + "@babel/plugin-transform-block-scoping": "^7.28.0", "@babel/plugin-transform-class-properties": "^7.27.1", "@babel/plugin-transform-class-static-block": "^7.27.1", - "@babel/plugin-transform-classes": "^7.27.1", + "@babel/plugin-transform-classes": "^7.28.0", "@babel/plugin-transform-computed-properties": "^7.27.1", - "@babel/plugin-transform-destructuring": "^7.27.1", + "@babel/plugin-transform-destructuring": "^7.28.0", "@babel/plugin-transform-dotall-regex": "^7.27.1", "@babel/plugin-transform-duplicate-keys": "^7.27.1", "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.27.1", "@babel/plugin-transform-dynamic-import": "^7.27.1", + "@babel/plugin-transform-explicit-resource-management": "^7.28.0", "@babel/plugin-transform-exponentiation-operator": "^7.27.1", "@babel/plugin-transform-export-namespace-from": "^7.27.1", "@babel/plugin-transform-for-of": "^7.27.1", @@ -15786,15 +15886,15 @@ "@babel/plugin-transform-new-target": "^7.27.1", "@babel/plugin-transform-nullish-coalescing-operator": "^7.27.1", "@babel/plugin-transform-numeric-separator": "^7.27.1", - "@babel/plugin-transform-object-rest-spread": "^7.27.2", + "@babel/plugin-transform-object-rest-spread": "^7.28.0", "@babel/plugin-transform-object-super": "^7.27.1", "@babel/plugin-transform-optional-catch-binding": "^7.27.1", "@babel/plugin-transform-optional-chaining": "^7.27.1", - "@babel/plugin-transform-parameters": "^7.27.1", + "@babel/plugin-transform-parameters": "^7.27.7", "@babel/plugin-transform-private-methods": "^7.27.1", "@babel/plugin-transform-private-property-in-object": "^7.27.1", "@babel/plugin-transform-property-literals": "^7.27.1", - "@babel/plugin-transform-regenerator": "^7.27.1", + "@babel/plugin-transform-regenerator": "^7.28.0", "@babel/plugin-transform-regexp-modifiers": "^7.27.1", "@babel/plugin-transform-reserved-words": "^7.27.1", "@babel/plugin-transform-shorthand-properties": "^7.27.1", @@ -15807,10 +15907,10 @@ "@babel/plugin-transform-unicode-regex": "^7.27.1", "@babel/plugin-transform-unicode-sets-regex": "^7.27.1", "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.11.0", - "babel-plugin-polyfill-regenerator": "^0.6.1", - "core-js-compat": "^3.40.0", + "babel-plugin-polyfill-corejs2": "^0.4.14", + "babel-plugin-polyfill-corejs3": "^0.13.0", + "babel-plugin-polyfill-regenerator": "^0.6.5", + "core-js-compat": "^3.43.0", "semver": "^6.3.1" }, "dependencies": { @@ -15871,24 +15971,24 @@ } }, "@babel/traverse": { - "version": "7.27.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.4.tgz", - "integrity": "sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.0.tgz", + "integrity": "sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==", "dev": true, "requires": { "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.27.3", - "@babel/parser": "^7.27.4", + "@babel/generator": "^7.28.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.0", "@babel/template": "^7.27.2", - "@babel/types": "^7.27.3", - "debug": "^4.3.1", - "globals": "^11.1.0" + "@babel/types": "^7.28.0", + "debug": "^4.3.1" } }, "@babel/types": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.3.tgz", - "integrity": "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz", + "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==", "dev": true, "requires": { "@babel/helper-string-parser": "^7.27.1", @@ -16544,9 +16644,9 @@ "dev": true }, "@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "version": "0.3.29", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz", + "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==", "dev": true, "requires": { "@jridgewell/resolve-uri": "^3.1.0", @@ -16791,9 +16891,9 @@ } }, "@rollup/plugin-typescript": { - "version": "12.1.3", - "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-12.1.3.tgz", - "integrity": "sha512-gAx0AYwkyjqOw4JrZV34N/abvAobLhczyLkZ7FVL2UXPrO4zv8oqTfYT3DLBRan1EXasp4SUuEJXqPTk0gnJzw==", + "version": "12.1.4", + "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-12.1.4.tgz", + "integrity": "sha512-s5Hx+EtN60LMlDBvl5f04bEiFZmAepk27Q+mr85L/00zPDn1jtzlTV6FWn81MaIwqfWzKxmOJrBWHU6vtQyedQ==", "dev": true, "requires": { "@rollup/pluginutils": "^5.1.0", @@ -17116,9 +17216,9 @@ "dev": true }, "@svta/common-media-library": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@svta/common-media-library/-/common-media-library-0.14.0.tgz", - "integrity": "sha512-MJRmqRq/n96YZIVQxZbt1RlLCX10w2rLrw0IPNw0fCkaD9k1B97J+zDYwCTgAm7L54Qu6pDWTJ1wKoYb2e+pUw==", + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/@svta/common-media-library/-/common-media-library-0.15.1.tgz", + "integrity": "sha512-Ig26anQU/MVRxrikBv1cMmeJqhXG683jxA7q9iscoMygcYd4+XmLjM0kcshZ574izow4X+j/NcU5vTrvVXF9sQ==", "dev": true }, "@testim/chrome-version": { @@ -17972,13 +18072,13 @@ } }, "babel-plugin-polyfill-corejs2": { - "version": "0.4.10", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.10.tgz", - "integrity": "sha512-rpIuu//y5OX6jVU+a5BCn1R5RSZYWAl2Nar76iwaOdycqb6JPxediskWFMMl7stfwNJR4b7eiQvh5fB5TEQJTQ==", + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.14.tgz", + "integrity": "sha512-Co2Y9wX854ts6U8gAAPXfn0GmAyctHuK8n0Yhfjd6t30g7yvKjspvvOo9yG+z52PZRgFErt7Ka2pYnXCjLKEpg==", "dev": true, "requires": { - "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.6.1", + "@babel/compat-data": "^7.27.7", + "@babel/helper-define-polyfill-provider": "^0.6.5", "semver": "^6.3.1" }, "dependencies": { @@ -17991,22 +18091,22 @@ } }, "babel-plugin-polyfill-corejs3": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.11.1.tgz", - "integrity": "sha512-yGCqvBT4rwMczo28xkH/noxJ6MZ4nJfkVYdoDaC/utLtWrXxv27HVrzAeSbqR8SxDsp46n0YF47EbHoixy6rXQ==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.13.0.tgz", + "integrity": "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==", "dev": true, "requires": { - "@babel/helper-define-polyfill-provider": "^0.6.3", - "core-js-compat": "^3.40.0" + "@babel/helper-define-polyfill-provider": "^0.6.5", + "core-js-compat": "^3.43.0" } }, "babel-plugin-polyfill-regenerator": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.1.tgz", - "integrity": "sha512-JfTApdE++cgcTWjsiCQlLyFBMbTUft9ja17saCc93lgV33h4tuCVj7tlvu//qpLwaG+3yEz7/KhahGrUMkVq9g==", + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.5.tgz", + "integrity": "sha512-ISqQ2frbiNU9vIJkzg7dlPpznPZ4jOiUQ1uSmB0fEHeowtN3COYRsXr/xexn64NpU13P06jc/L5TgiJXOgrbEg==", "dev": true, "requires": { - "@babel/helper-define-polyfill-provider": "^0.6.1" + "@babel/helper-define-polyfill-provider": "^0.6.5" } }, "babel-plugin-transform-remove-console": { @@ -18123,15 +18223,15 @@ "dev": true }, "browserslist": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", - "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", + "version": "4.25.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz", + "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001688", - "electron-to-chromium": "^1.5.73", + "caniuse-lite": "^1.0.30001726", + "electron-to-chromium": "^1.5.173", "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.1" + "update-browserslist-db": "^1.1.3" } }, "buffer-crc32": { @@ -18191,9 +18291,9 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30001699", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001699.tgz", - "integrity": "sha512-b+uH5BakXZ9Do9iK+CkDmctUSEqZl+SP056vc5usa0PL+ev5OHw003rZXcnjNDv3L8P5j6rwT6C0BPKSikW08w==", + "version": "1.0.30001726", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001726.tgz", + "integrity": "sha512-VQAUIUzBiZ/UnlM28fSp2CRF3ivUn1BWEvxMcVTNwpw91Py1pGbPIyIKtd+tzct9C3ouceCVdGAXxZOpZAsgdw==", "dev": true }, "ccount": { @@ -18553,12 +18653,12 @@ "dev": true }, "core-js-compat": { - "version": "3.40.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.40.0.tgz", - "integrity": "sha512-0XEDpr5y5mijvw8Lbc6E5AkjrHfp7eEoPlu36SWeAbcL8fn1G1ANe8DBlo2XoNN89oVpxWwOjYIPVzR4ZvsKCQ==", + "version": "3.43.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.43.0.tgz", + "integrity": "sha512-2GML2ZsCc5LR7hZYz4AXmjQw8zuy2T//2QntwdnpuYI7jteT6GVYJL7F6C2C57R7gSYrcqVW3lAALefdbhBLDA==", "dev": true, "requires": { - "browserslist": "^4.24.3" + "browserslist": "^4.25.0" } }, "core-util-is": { @@ -18872,9 +18972,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.5.101", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.101.tgz", - "integrity": "sha512-L0ISiQrP/56Acgu4/i/kfPwWSgrzYZUnQrC0+QPFuhqlLP1Ir7qzPPDVS9BcKIyWTRU8+o6CC8dKw38tSWhYIA==", + "version": "1.5.179", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.179.tgz", + "integrity": "sha512-UWKi/EbBopgfFsc5k61wFpV7WrnnSlSzW/e2XcBmS6qKYTivZlLtoll5/rdqRTxGglGHkmkW0j0pFNJG10EUIQ==", "dev": true }, "emoji-regex": { @@ -20137,12 +20237,6 @@ "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "dev": true }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, "globalthis": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", @@ -23154,12 +23248,12 @@ "dev": true }, "resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", "dev": true, "requires": { - "is-core-module": "^2.13.0", + "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" } @@ -23378,15 +23472,24 @@ "dev": true }, "selenium-webdriver": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-4.33.0.tgz", - "integrity": "sha512-5vRhk4iI0B9nYbEitfnCjPDXBfG6o9DNhj5DG2355eQo8idETknhj1tigqqlkHsGephSZwLZqEm/d+3e1stGUA==", + "version": "4.34.0", + "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-4.34.0.tgz", + "integrity": "sha512-zGfQFcsASAv3KrYzYh+iw4fFqB7iZAgHW7BU6rRz7isK1i1X4x3LvjmZad4bUUgHDwTnAhlqTzDh21byB+zHMg==", "dev": true, "requires": { "@bazel/runfiles": "^6.3.1", "jszip": "^3.10.1", "tmp": "^0.2.3", - "ws": "^8.18.0" + "ws": "^8.18.2" + }, + "dependencies": { + "ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "dev": true, + "requires": {} + } } }, "semver": { @@ -24437,9 +24540,9 @@ "dev": true }, "update-browserslist-db": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz", - "integrity": "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", "dev": true, "requires": { "escalade": "^3.2.0", diff --git a/package.json b/package.json index 463ac02eb4c..4b1cb1ff7db 100644 --- a/package.json +++ b/package.json @@ -65,13 +65,13 @@ "prepare": "husky" }, "devDependencies": { - "@babel/core": "7.27.4", + "@babel/core": "7.28.0", "@babel/helper-module-imports": "7.27.1", "@babel/plugin-proposal-class-properties": "7.18.6", "@babel/plugin-proposal-object-rest-spread": "7.20.7", "@babel/plugin-proposal-optional-chaining": "7.21.0", "@babel/plugin-transform-object-assign": "7.27.1", - "@babel/preset-env": "7.27.2", + "@babel/preset-env": "7.28.0", "@babel/preset-typescript": "7.27.1", "@babel/register": "7.27.1", "@microsoft/api-documenter": "7.26.29", @@ -82,8 +82,8 @@ "@rollup/plugin-node-resolve": "16.0.1", "@rollup/plugin-replace": "6.0.2", "@rollup/plugin-terser": "0.4.4", - "@rollup/plugin-typescript": "12.1.3", - "@svta/common-media-library": "0.14.0", + "@rollup/plugin-typescript": "12.1.4", + "@svta/common-media-library": "0.15.1", "@types/chai": "4.3.20", "@types/chart.js": "2.9.41", "@types/mocha": "10.0.10", @@ -127,7 +127,7 @@ "rollup": "4.44.1", "rollup-plugin-istanbul": "5.0.0", "sauce-connect-launcher": "1.3.2", - "selenium-webdriver": "4.33.0", + "selenium-webdriver": "4.34.0", "semver": "7.7.2", "sinon": "19.0.5", "sinon-chai": "3.7.0", diff --git a/src/controller/audio-stream-controller.ts b/src/controller/audio-stream-controller.ts index 3d3f13cf816..f3517c041c9 100644 --- a/src/controller/audio-stream-controller.ts +++ b/src/controller/audio-stream-controller.ts @@ -201,9 +201,7 @@ class AudioStreamController const syncFrag = findNearestWithCC(trackDetails, targetDiscontinuity, pos); // Only stop waiting for audioFrag.cc if an audio segment of the same discontinuity domain (cc) is found if (syncFrag) { - this.log( - `Waiting fragment cc (${waitingToAppend?.cc}) cancelled because video is at cc ${mainAnchor.cc}`, - ); + this.log(`Syncing with main frag at ${syncFrag.start} cc ${syncFrag.cc}`); this.startFragRequested = false; this.nextLoadPosition = syncFrag.start; this.resetLoadingState(); diff --git a/src/controller/base-stream-controller.ts b/src/controller/base-stream-controller.ts index 3f9c8c2f497..67a43d88ece 100644 --- a/src/controller/base-stream-controller.ts +++ b/src/controller/base-stream-controller.ts @@ -817,6 +817,7 @@ export default class BaseStreamController keyLoadingPromise = this.keyLoader.loadClear( frag, details.encryptedFragments, + this.startFragRequested, ); if (keyLoadingPromise) { this.log(`[eme] blocking frag load until media-keys acquired`); diff --git a/src/controller/eme-controller.ts b/src/controller/eme-controller.ts index 3379b6c3353..5ce41a32e2e 100644 --- a/src/controller/eme-controller.ts +++ b/src/controller/eme-controller.ts @@ -17,21 +17,11 @@ import { getKeySystemsForConfig, getSupportedMediaKeySystemConfigurations, isPersistentSessionType, + keySystemDomainToKeySystemFormat, keySystemFormatToKeySystemDomain, - keySystemIdToKeySystemDomain, KeySystems, - keySystemDomainToKeySystemFormat as keySystemToKeySystemFormat, - parsePlayReadyWRM, requestMediaKeySystemAccess, } from '../utils/mediakeys-helper'; -import { - bin2str, - parseMultiPssh, - parseSinf, - type PsshData, - type PsshInvalidResult, -} from '../utils/mp4-tools'; -import { base64Decode } from '../utils/numeric-encoding-utils'; import { stringify } from '../utils/safe-json-stringify'; import { strToUtf8array } from '../utils/utf8-utils'; import type { EMEControllerConfig, HlsConfig, LoadPolicy } from '../config'; @@ -119,7 +109,7 @@ class EMEController extends Logger implements ComponentAPI { // @ts-ignore this.hls = this.config = this.keyIdToKeySessionPromise = null; // @ts-ignore - this.onMediaEncrypted = this.onWaitingForKey = null; + this.onWaitingForKey = null; } private registerListeners() { @@ -398,7 +388,7 @@ class EMEController extends Logger implements ComponentAPI { hasMediaKeys: this.keySystemAccessPromises[keySystem].hasMediaKeys, })) .filter(({ hasMediaKeys }) => !!hasMediaKeys) - .map(({ keySystem }) => keySystemToKeySystemFormat(keySystem)) + .map(({ keySystem }) => keySystemDomainToKeySystemFormat(keySystem)) .filter((keySystem): keySystem is KeySystemFormats => !!keySystem); } @@ -416,7 +406,7 @@ class EMEController extends Logger implements ComponentAPI { return new Promise((resolve, reject) => { return this.getKeySystemSelectionPromise(keySystemsToAttempt) .then(({ keySystem }) => { - const keySystemFormat = keySystemToKeySystemFormat(keySystem); + const keySystemFormat = keySystemDomainToKeySystemFormat(keySystem); if (keySystemFormat) { resolve(keySystemFormat); } else { @@ -562,197 +552,6 @@ class EMEController extends Logger implements ComponentAPI { return this.attemptKeySystemAccess(keySystemsToAttempt); } - private onMediaEncrypted = (event: MediaEncryptedEvent) => { - const { initDataType, initData } = event; - const logMessage = `"${event.type}" event: init data type: "${initDataType}"`; - this.debug(logMessage); - - // Ignore event when initData is null - if (initData === null) { - return; - } - - if (!this.keyFormatPromise) { - let keySystems = Object.keys( - this.keySystemAccessPromises, - ) as KeySystems[]; - if (!keySystems.length) { - keySystems = getKeySystemsForConfig(this.config); - } - const keyFormats = keySystems - .map(keySystemToKeySystemFormat) - .filter((k) => !!k) as KeySystemFormats[]; - this.keyFormatPromise = this.getKeyFormatPromise(keyFormats); - } - - this.keyFormatPromise.then((keySystemFormat) => { - const keySystem = keySystemFormatToKeySystemDomain(keySystemFormat); - - let keyId: Uint8Array | null | undefined; - let keySystemDomain: KeySystems | undefined; - - if (initDataType === 'sinf') { - if (keySystem !== KeySystems.FAIRPLAY) { - this.warn( - `Ignoring unexpected "${event.type}" event with init data type: "${initDataType}" for selected key-system ${keySystem}`, - ); - return; - } - // Match sinf keyId to playlist skd://keyId= - const json = bin2str(new Uint8Array(initData)); - try { - const sinf = base64Decode(JSON.parse(json).sinf); - const tenc = parseSinf(sinf); - if (!tenc) { - throw new Error( - `'schm' box missing or not cbcs/cenc with schi > tenc`, - ); - } - keyId = new Uint8Array(tenc.subarray(8, 24)); - keySystemDomain = KeySystems.FAIRPLAY; - } catch (error) { - this.warn(`${logMessage} Failed to parse sinf: ${error}`); - return; - } - } else { - if ( - keySystem !== KeySystems.WIDEVINE && - keySystem !== KeySystems.PLAYREADY - ) { - this.warn( - `Ignoring unexpected "${event.type}" event with init data type: "${initDataType}" for selected key-system ${keySystem}`, - ); - return; - } - // Support Widevine/PlayReady clear-lead key-session creation (otherwise depend on playlist keys) - const psshResults = parseMultiPssh(initData); - - const psshInfos = psshResults.filter( - (pssh): pssh is PsshData => - !!pssh.systemId && - keySystemIdToKeySystemDomain(pssh.systemId) === keySystem, - ); - - if (psshInfos.length > 1) { - this.warn( - `${logMessage} Using first of ${psshInfos.length} pssh found for selected key-system ${keySystem}`, - ); - } - - const psshInfo = psshInfos[0]; - - if (!psshInfo) { - if ( - psshResults.length === 0 || - psshResults.some( - (pssh): pssh is PsshInvalidResult => !pssh.systemId, - ) - ) { - this.warn(`${logMessage} contains incomplete or invalid pssh data`); - } else { - this.log( - `ignoring ${logMessage} for ${(psshResults as PsshData[]) - .map((pssh) => keySystemIdToKeySystemDomain(pssh.systemId)) - .join(',')} pssh data in favor of playlist keys`, - ); - } - return; - } - - keySystemDomain = keySystemIdToKeySystemDomain(psshInfo.systemId); - if (psshInfo.version === 0 && psshInfo.data) { - if (keySystemDomain === KeySystems.WIDEVINE) { - const offset = psshInfo.data.length - 22; - keyId = new Uint8Array(psshInfo.data.subarray(offset, offset + 16)); - } else if (keySystemDomain === KeySystems.PLAYREADY) { - keyId = parsePlayReadyWRM(psshInfo.data); - } - } - } - - if (!keySystemDomain || !keyId) { - return; - } - - const keyIdHex = Hex.hexDump(keyId); - const { keyIdToKeySessionPromise, mediaKeySessions } = this; - - let keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex]; - for (let i = 0; i < mediaKeySessions.length; i++) { - // Match playlist key - const keyContext = mediaKeySessions[i]; - const decryptdata = keyContext.decryptdata; - if (!decryptdata.keyId) { - continue; - } - const oldKeyIdHex = Hex.hexDump(decryptdata.keyId); - if ( - keyIdHex === oldKeyIdHex || - decryptdata.uri.replace(/-/g, '').indexOf(keyIdHex) !== -1 - ) { - keySessionContextPromise = keyIdToKeySessionPromise[oldKeyIdHex]; - if (decryptdata.pssh) { - break; - } - delete keyIdToKeySessionPromise[oldKeyIdHex]; - decryptdata.pssh = new Uint8Array(initData); - decryptdata.keyId = keyId; - keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = - keySessionContextPromise.then(() => { - return this.generateRequestWithPreferredKeySession( - keyContext, - initDataType, - initData, - 'encrypted-event-key-match', - ); - }); - keySessionContextPromise.catch((error) => this.handleError(error)); - break; - } - } - - if (!keySessionContextPromise) { - if (keySystemDomain !== keySystem) { - this.log( - `Ignoring "${event.type}" event with ${keySystemDomain} init data for selected key-system ${keySystem}`, - ); - return; - } - // "Clear-lead" (misc key not encountered in playlist) - keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = - this.getKeySystemSelectionPromise([keySystemDomain]).then( - ({ keySystem, mediaKeys }) => { - this.throwIfDestroyed(); - - const decryptdata = new LevelKey( - 'ISO-23001-7', - keyIdHex, - keySystemToKeySystemFormat(keySystem) ?? '', - ); - decryptdata.pssh = new Uint8Array(initData); - decryptdata.keyId = keyId; - return this.attemptSetMediaKeys(keySystem, mediaKeys).then(() => { - this.throwIfDestroyed(); - const keySessionContext = this.createMediaKeySessionContext({ - decryptdata, - keySystem, - mediaKeys, - }); - return this.generateRequestWithPreferredKeySession( - keySessionContext, - initDataType, - initData, - 'encrypted-event-no-match', - ); - }); - }, - ); - - keySessionContextPromise.catch((error) => this.handleError(error)); - } - }); - }; - private onWaitingForKey = (event: Event) => { this.log(`"${event.type}" event`); }; @@ -1331,7 +1130,6 @@ class EMEController extends Logger implements ComponentAPI { // keep reference of media this.media = media; - addEventListener(media, 'encrypted', this.onMediaEncrypted); addEventListener(media, 'waitingforkey', this.onWaitingForKey); } @@ -1339,7 +1137,6 @@ class EMEController extends Logger implements ComponentAPI { const media = this.media; if (media) { - removeEventListener(media, 'encrypted', this.onMediaEncrypted); removeEventListener(media, 'waitingforkey', this.onWaitingForKey); this.media = null; this.mediaKeys = null; diff --git a/src/controller/id3-track-controller.ts b/src/controller/id3-track-controller.ts index 48692d81a7a..e3c022b239f 100644 --- a/src/controller/id3-track-controller.ts +++ b/src/controller/id3-track-controller.ts @@ -6,6 +6,7 @@ import { isSCTE35Attribute, } from '../loader/date-range'; import { MetadataSchema } from '../types/demuxer'; +import { hexToArrayBuffer } from '../utils/hex'; import { stringify } from '../utils/safe-json-stringify'; import { clearCurrentCues, @@ -73,15 +74,6 @@ const MAX_CUE_ENDTIME = (() => { return Number.POSITIVE_INFINITY; })(); -function hexToArrayBuffer(str): ArrayBuffer { - return Uint8Array.from( - str - .replace(/^0x/, '') - .replace(/([\da-fA-F]{2}) ?/g, '0x$1 ') - .replace(/ +$/, '') - .split(' '), - ).buffer; -} class ID3TrackController implements ComponentAPI { private hls: Hls; private id3Track: TextTrack | null = null; diff --git a/src/loader/key-loader.ts b/src/loader/key-loader.ts index de0b1b1315c..124e07bb20d 100644 --- a/src/loader/key-loader.ts +++ b/src/loader/key-loader.ts @@ -1,5 +1,6 @@ import { LoadError } from './fragment-loader'; import { ErrorDetails, ErrorTypes } from '../errors'; +import { type Fragment, isMediaFragment } from '../loader/fragment'; import { getKeySystemsForConfig, keySystemFormatToKeySystemDomain, @@ -8,7 +9,6 @@ import type { LevelKey } from './level-key'; import type { HlsConfig } from '../config'; import type EMEController from '../controller/eme-controller'; import type { MediaKeySessionContext } from '../controller/eme-controller'; -import type { Fragment } from '../loader/fragment'; import type { ComponentAPI } from '../types/component-api'; import type { KeyLoadedData } from '../types/events'; import type { @@ -94,39 +94,42 @@ export default class KeyLoader implements ComponentAPI { loadClear( loadingFrag: Fragment, encryptedFragments: Fragment[], + startFragRequested: boolean, ): null | Promise { if ( this.emeController && this.config.emeEnabled && !this.emeController.getSelectedKeySystemFormats().length ) { - // access key-system with nearest key on start (loading frag is unencrypted) + // Access key-system with nearest key on start (loading frag is unencrypted) if (encryptedFragments.length) { - const { sn, cc } = loadingFrag; - for (let i = 0; i < encryptedFragments.length; i++) { + for (let i = 0, l = encryptedFragments.length; i < l; i++) { const frag = encryptedFragments[i]; + // Loading at or before segment with EXT-X-KEY, or first frag loading and last EXT-X-KEY if ( - cc <= frag.cc && - (sn === 'initSegment' || frag.sn === 'initSegment' || sn < frag.sn) + (loadingFrag.cc <= frag.cc && + (!isMediaFragment(loadingFrag) || + !isMediaFragment(frag) || + loadingFrag.sn < frag.sn)) || + (!startFragRequested && i == l - 1) ) { return this.emeController .selectKeySystemFormat(frag) .then((keySystemFormat) => { + if (!this.emeController) { + return; + } frag.setKeyFormat(keySystemFormat); - if ( - this.emeController && - this.config.requireKeySystemAccessOnStart - ) { - const keySystem = - keySystemFormatToKeySystemDomain(keySystemFormat); - if (keySystem) { - return this.emeController.getKeySystemAccess([keySystem]); - } + const keySystem = + keySystemFormatToKeySystemDomain(keySystemFormat); + if (keySystem) { + return this.emeController.getKeySystemAccess([keySystem]); } }); } } - } else if (this.config.requireKeySystemAccessOnStart) { + } + if (this.config.requireKeySystemAccessOnStart) { const keySystemsInConfig = getKeySystemsForConfig(this.config); if (keySystemsInConfig.length) { return this.emeController.getKeySystemAccess(keySystemsInConfig); diff --git a/src/loader/level-key.ts b/src/loader/level-key.ts index 9cb5e73255d..49d4dd925f7 100644 --- a/src/loader/level-key.ts +++ b/src/loader/level-key.ts @@ -1,4 +1,5 @@ import { isFullSegmentEncryption } from '../utils/encryption-methods-util'; +import { hexToArrayBuffer } from '../utils/hex'; import { convertDataUriToArrayBytes } from '../utils/keysystem-util'; import { logger } from '../utils/logger'; import { KeySystemFormats, parsePlayReadyWRM } from '../utils/mediakeys-helper'; @@ -41,6 +42,7 @@ export class LevelKey implements DecryptData { format: string, formatversions: number[] = [1], iv: Uint8Array | null = null, + keyId?: string, ) { this.method = method; this.uri = uri; @@ -50,6 +52,20 @@ export class LevelKey implements DecryptData { this.encrypted = method ? method !== 'NONE' : false; this.isCommonEncryption = this.encrypted && !isFullSegmentEncryption(method); + if (keyId?.startsWith('0x')) { + this.keyId = new Uint8Array(hexToArrayBuffer(keyId)); + } + } + + public matches(key: LevelKey): boolean { + return ( + key.uri === this.uri && + key.method === this.method && + key.encrypted === this.encrypted && + key.keyFormat === this.keyFormat && + key.keyFormatVersions.join(',') === this.keyFormatVersions.join(',') && + key.iv?.join(',') === this.iv?.join(',') + ); } public isSupported(): boolean { @@ -113,6 +129,10 @@ export class LevelKey implements DecryptData { return this; } + if (this.pssh && this.keyId) { + return this; + } + // Initialize keyId if possible const keyBytes = convertDataUriToArrayBytes(this.uri); if (keyBytes) { @@ -121,12 +141,10 @@ export class LevelKey implements DecryptData { // Setting `pssh` on this LevelKey/DecryptData allows HLS.js to generate a session using // the playlist-key before the "encrypted" event. (Comment out to only use "encrypted" path.) this.pssh = keyBytes; - // In case of widevine keyID is embedded in PSSH box. Read Key ID. - if (keyBytes.length >= 22) { - this.keyId = keyBytes.subarray( - keyBytes.length - 22, - keyBytes.length - 6, - ); + // In case of Widevine, if KEYID is not in the playlist, assume only two fields in the pssh KEY tag URI. + if (!this.keyId && keyBytes.length >= 22) { + const offset = keyBytes.length - 22; + this.keyId = keyBytes.subarray(offset, offset + 16); } break; case KeySystemFormats.PLAYREADY: { diff --git a/src/loader/m3u8-parser.ts b/src/loader/m3u8-parser.ts index 1fc518421dc..36d42a5246c 100644 --- a/src/loader/m3u8-parser.ts +++ b/src/loader/m3u8-parser.ts @@ -572,10 +572,14 @@ export default class M3U8Parser { if (!levelkeys) { levelkeys = {}; } - if (levelkeys[levelKey.keyFormat]) { - levelkeys = Object.assign({}, levelkeys); + const currentKey = levelkeys[levelKey.keyFormat]; + // Ignore duplicate playlist KEY tags + if (!currentKey?.matches(levelKey)) { + if (currentKey) { + levelkeys = Object.assign({}, levelkeys); + } + levelkeys[levelKey.keyFormat] = levelKey; } - levelkeys[levelKey.keyFormat] = levelKey; } else { logger.warn(`[Keys] Ignoring invalid EXT-X-KEY tag: "${value1}"`); } @@ -856,6 +860,7 @@ function parseKey( decryptkeyformat, keyFormatVersions, decryptiv, + keyAttrs.KEYID, ); } diff --git a/src/utils/hex.ts b/src/utils/hex.ts index 703988cf601..a7db9633fea 100644 --- a/src/utils/hex.ts +++ b/src/utils/hex.ts @@ -3,7 +3,7 @@ */ const Hex = { - hexDump: function (array: Uint8Array) { + hexDump: function (array: Uint8Array) { let str = ''; for (let i = 0; i < array.length; i++) { let h = array[i].toString(16); @@ -17,4 +17,14 @@ const Hex = { }, }; +export function hexToArrayBuffer(str: string): ArrayBuffer { + return Uint8Array.from( + str + .replace(/^0x/, '') + .replace(/([\da-fA-F]{2}) ?/g, '0x$1 ') + .replace(/ +$/, '') + .split(' '), + ).buffer; +} + export default Hex; diff --git a/src/utils/mediakeys-helper.ts b/src/utils/mediakeys-helper.ts index b098f3ee47b..c32f2e9bce0 100755 --- a/src/utils/mediakeys-helper.ts +++ b/src/utils/mediakeys-helper.ts @@ -177,7 +177,7 @@ export function isPersistentSessionType( ); } -export function parsePlayReadyWRM(keyBytes: Uint8Array) { +export function parsePlayReadyWRM(keyBytes: Uint8Array) { const keyBytesUtf16 = new Uint16Array( keyBytes.buffer, keyBytes.byteOffset, diff --git a/src/utils/mp4-tools.ts b/src/utils/mp4-tools.ts index ee035547395..faf306c638f 100644 --- a/src/utils/mp4-tools.ts +++ b/src/utils/mp4-tools.ts @@ -590,7 +590,7 @@ export function patchEncyptionData( const tenc = parseSinf(sinf); if (tenc) { // Look for default key id (keyID offset is always 8 within the tenc box): - const tencKeyId = tenc.subarray(8, 24); + const tencKeyId = tenc.subarray(8, 24) as Uint8Array; if (!tencKeyId.some((b) => b !== 0)) { logger.log( `[eme] Patching keyId in 'enc${ @@ -1353,8 +1353,8 @@ export function mp4pssh( export type PsshData = { version: 0 | 1; systemId: KeySystemIds; - kids: null | Uint8Array[]; - data: null | Uint8Array; + kids: null | Uint8Array[]; + data: null | Uint8Array; offset: number; size: number; }; @@ -1382,7 +1382,7 @@ export function parseMultiPssh( return results; } -function parsePssh(view: DataView): PsshData | PsshInvalidResult { +function parsePssh(view: DataView): PsshData | PsshInvalidResult { const size = view.getUint32(0); const offset = view.byteOffset; const length = view.byteLength; @@ -1405,8 +1405,8 @@ function parsePssh(view: DataView): PsshData | PsshInvalidResult { new Uint8Array(buffer, offset + 12, 16), ) as KeySystemIds; - let kids: null | Uint8Array[] = null; - let data: null | Uint8Array = null; + let kids: null | Uint8Array[] = null; + let data: null | Uint8Array = null; let dataSizeOffset = 0; if (version === 0) {