From a302756ee5be55ea604d5b6403f5d8a50faf3c8a Mon Sep 17 00:00:00 2001 From: Santiago Puppo Date: Fri, 9 Jan 2026 15:21:52 -0300 Subject: [PATCH 01/12] Added some functions to cleanup hanging memory --- examples/vanilla/memory-leak-tester.html | 75 ++++++++++++++++++++++++ src/js/media-chrome-range.ts | 4 ++ src/js/media-controller.ts | 2 + src/js/media-time-display.ts | 25 ++++---- src/js/media-volume-range.ts | 31 ++++++---- src/js/menu/media-chrome-menu.ts | 2 + 6 files changed, 116 insertions(+), 23 deletions(-) create mode 100644 examples/vanilla/memory-leak-tester.html diff --git a/examples/vanilla/memory-leak-tester.html b/examples/vanilla/memory-leak-tester.html new file mode 100644 index 000000000..82b63a2b0 --- /dev/null +++ b/examples/vanilla/memory-leak-tester.html @@ -0,0 +1,75 @@ + + + + + <mux-video> example + + + + + + + + + +
+ + + + diff --git a/src/js/media-chrome-range.ts b/src/js/media-chrome-range.ts index f3333dad1..bcbdae37f 100644 --- a/src/js/media-chrome-range.ts +++ b/src/js/media-chrome-range.ts @@ -373,6 +373,9 @@ class MediaChromeRange extends globalThis.HTMLElement { * {value: number, min: number, max: number}} */ this.range = this.shadowRoot.querySelector('#range'); this.appearance = this.shadowRoot.querySelector('#appearance'); + + this.#onFocusIn = this.#onFocusIn.bind(this); + this.#onFocusOut = this.#onFocusOut.bind(this); } #onFocusIn = (): void => { @@ -577,6 +580,7 @@ class MediaChromeRange extends globalThis.HTMLElement { this.removeEventListener('input', this); this.removeEventListener('pointerdown', this); this.removeEventListener('pointerenter', this); + this.removeEventListener('pointerleave', this); globalThis.window?.removeEventListener('pointerup', this); globalThis.window?.removeEventListener('pointermove', this); } diff --git a/src/js/media-controller.ts b/src/js/media-controller.ts index 0c637b4ea..697d3f1a4 100644 --- a/src/js/media-controller.ts +++ b/src/js/media-controller.ts @@ -490,6 +490,8 @@ class MediaController extends MediaContainer { this.#mediaStoreUnsubscribe?.(); this.#mediaStoreUnsubscribe = undefined; } + + this.unassociateElement(this); } /** diff --git a/src/js/media-time-display.ts b/src/js/media-time-display.ts index a438586cf..de24c125e 100644 --- a/src/js/media-time-display.ts +++ b/src/js/media-time-display.ts @@ -109,6 +109,14 @@ class MediaTimeDisplay extends MediaTextDisplay { #slot: HTMLSlotElement; #keyUpHandler: ((evt: KeyboardEvent) => void) | null = null; + #keyDownHandler = (evt: KeyboardEvent) => { + const { metaKey, altKey, key } = evt; + if (metaKey || altKey || !ButtonPressedKeys.includes(key)) { + this.removeEventListener('keyup', this.#keyUpHandler); + return; + } + this.addEventListener('keyup', this.#keyUpHandler); + } static get observedAttributes(): string[] { return [...super.observedAttributes, ...CombinedAttributes, 'disabled']; @@ -119,6 +127,7 @@ class MediaTimeDisplay extends MediaTextDisplay { this.#slot = this.shadowRoot.querySelector('slot'); this.#slot.innerHTML = `${formatTimesLabel(this)}`; + this.#keyDownHandler = this.#keyDownHandler.bind(this); } connectedCallback(): void { @@ -146,28 +155,21 @@ class MediaTimeDisplay extends MediaTextDisplay { this.#keyUpHandler = (evt: KeyboardEvent) => { const { key } = evt; if (!ButtonPressedKeys.includes(key)) { - this.removeEventListener('keyup', this.#keyUpHandler!); + this.removeEventListener('keyup', this.#keyUpHandler); return; } this.toggleTimeDisplay(); }; - - this.addEventListener('keydown', (evt: KeyboardEvent) => { - const { metaKey, altKey, key } = evt; - if (metaKey || altKey || !ButtonPressedKeys.includes(key)) { - this.removeEventListener('keyup', this.#keyUpHandler!); - return; - } - this.addEventListener('keyup', this.#keyUpHandler!); - }); - + this.#keyUpHandler = this.#keyUpHandler.bind(this); + this.addEventListener('keydown', this.#keyDownHandler); this.addEventListener('click', this.toggleTimeDisplay); } #removeEventListeners(): void { if (this.#keyUpHandler) { this.removeEventListener('keyup', this.#keyUpHandler); + this.removeEventListener('keydown', this.#keyDownHandler); this.removeEventListener('click', this.toggleTimeDisplay); this.#keyUpHandler = null; } @@ -202,6 +204,7 @@ class MediaTimeDisplay extends MediaTextDisplay { disconnectedCallback(): void { this.disable(); + this.#removeEventListeners(); super.disconnectedCallback(); } diff --git a/src/js/media-volume-range.ts b/src/js/media-volume-range.ts index 0de215546..fa05a1404 100644 --- a/src/js/media-volume-range.ts +++ b/src/js/media-volume-range.ts @@ -40,24 +40,31 @@ class MediaVolumeRange extends MediaChromeRange { constructor() { super(); + this.#handleRangeInput = this.#handleRangeInput.bind(this); + } - this.range.addEventListener('input', () => { - const detail = this.range.value; - const evt = new globalThis.CustomEvent( - MediaUIEvents.MEDIA_VOLUME_REQUEST, - { - composed: true, - bubbles: true, - detail, - } - ); - this.dispatchEvent(evt); - }); + #handleRangeInput: () => void = () => { + const detail = this.range.value; + const evt = new globalThis.CustomEvent( + MediaUIEvents.MEDIA_VOLUME_REQUEST, + { + composed: true, + bubbles: true, + detail, + } + ); + this.dispatchEvent(evt); } connectedCallback(): void { super.connectedCallback(); this.range.setAttribute('aria-label', t('volume')); + this.range.addEventListener('input', this.#handleRangeInput); + } + + disconnectedCallback(): void { + this.range.removeEventListener('input', this.#handleRangeInput); + super.disconnectedCallback(); } attributeChangedCallback( diff --git a/src/js/menu/media-chrome-menu.ts b/src/js/menu/media-chrome-menu.ts index 74cc3316c..658e5c639 100644 --- a/src/js/menu/media-chrome-menu.ts +++ b/src/js/menu/media-chrome-menu.ts @@ -422,6 +422,8 @@ class MediaChromeMenu extends globalThis.HTMLElement { } disconnectedCallback(): void { + this.#mutationObserver.disconnect(); + unobserveResize(getBoundsElement(this), this.#handleBoundsResize); unobserveResize(this, this.#handleMenuResize); From 2c631ea9128238942495265dcdface1aa710a431 Mon Sep 17 00:00:00 2001 From: Santiago Puppo Date: Fri, 9 Jan 2026 15:22:29 -0300 Subject: [PATCH 02/12] Updated next version to fix broken example --- examples/nextjs-with-typescript/next-env.d.ts | 2 +- .../nextjs-with-typescript/package-lock.json | 126 ++++++++---------- examples/nextjs-with-typescript/package.json | 2 +- examples/nextjs-with-typescript/tsconfig.json | 5 +- src/js/media-store/util.ts | 1 + 5 files changed, 61 insertions(+), 75 deletions(-) diff --git a/examples/nextjs-with-typescript/next-env.d.ts b/examples/nextjs-with-typescript/next-env.d.ts index 3cd7048ed..c4b7818fb 100644 --- a/examples/nextjs-with-typescript/next-env.d.ts +++ b/examples/nextjs-with-typescript/next-env.d.ts @@ -1,6 +1,6 @@ /// /// -/// +import "./.next/dev/types/routes.d.ts"; // NOTE: This file should not be edited // see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/examples/nextjs-with-typescript/package-lock.json b/examples/nextjs-with-typescript/package-lock.json index 214b89572..236bc46c6 100644 --- a/examples/nextjs-with-typescript/package-lock.json +++ b/examples/nextjs-with-typescript/package-lock.json @@ -14,7 +14,7 @@ "@mui/material": "^7.0.2", "@mux/mux-video": "^0.17.5", "media-chrome": "file:../../", - "next": "15.3.8", + "next": "~16.1.1", "react": "19.2.2", "react-dom": "19.2.2" }, @@ -31,7 +31,7 @@ } }, "../..": { - "version": "4.17.0", + "version": "4.17.2", "license": "MIT", "dependencies": { "ce-la-react": "^0.3.2" @@ -53,6 +53,7 @@ "react": "19.2.2", "resolve.exports": "^2.0.3", "rimraf": "^3.0.2", + "shx": "^0.4.0", "sinon": "^14.0.1", "typescript": "^5.5.2", "typescript-eslint": "^7.14.1", @@ -1328,9 +1329,9 @@ } }, "node_modules/@next/env": { - "version": "15.3.8", - "resolved": "https://registry.npmjs.org/@next/env/-/env-15.3.8.tgz", - "integrity": "sha512-SAfHg0g91MQVMPioeFeDjE+8UPF3j3BvHjs8ZKJAUz1BG7eMPvfCKOAgNWJ6s1MLNeP6O2InKQRTNblxPWuq+Q==", + "version": "16.1.1", + "resolved": "https://registry.npmjs.org/@next/env/-/env-16.1.1.tgz", + "integrity": "sha512-3oxyM97Sr2PqiVyMyrZUtrtM3jqqFxOQJVuKclDsgj/L728iZt/GyslkN4NwarledZATCenbk4Offjk1hQmaAA==", "license": "MIT" }, "node_modules/@next/eslint-plugin-next": { @@ -1344,9 +1345,9 @@ } }, "node_modules/@next/swc-darwin-arm64": { - "version": "15.3.5", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.3.5.tgz", - "integrity": "sha512-lM/8tilIsqBq+2nq9kbTW19vfwFve0NR7MxfkuSUbRSgXlMQoJYg+31+++XwKVSXk4uT23G2eF/7BRIKdn8t8w==", + "version": "16.1.1", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.1.1.tgz", + "integrity": "sha512-JS3m42ifsVSJjSTzh27nW+Igfha3NdBOFScr9C80hHGrWx55pTrVL23RJbqir7k7/15SKlrLHhh/MQzqBBYrQA==", "cpu": [ "arm64" ], @@ -1360,9 +1361,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "15.3.5", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.3.5.tgz", - "integrity": "sha512-WhwegPQJ5IfoUNZUVsI9TRAlKpjGVK0tpJTL6KeiC4cux9774NYE9Wu/iCfIkL/5J8rPAkqZpG7n+EfiAfidXA==", + "version": "16.1.1", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.1.1.tgz", + "integrity": "sha512-hbyKtrDGUkgkyQi1m1IyD3q4I/3m9ngr+V93z4oKHrPcmxwNL5iMWORvLSGAf2YujL+6HxgVvZuCYZfLfb4bGw==", "cpu": [ "x64" ], @@ -1376,9 +1377,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "15.3.5", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.3.5.tgz", - "integrity": "sha512-LVD6uMOZ7XePg3KWYdGuzuvVboxujGjbcuP2jsPAN3MnLdLoZUXKRc6ixxfs03RH7qBdEHCZjyLP/jBdCJVRJQ==", + "version": "16.1.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.1.1.tgz", + "integrity": "sha512-/fvHet+EYckFvRLQ0jPHJCUI5/B56+2DpI1xDSvi80r/3Ez+Eaa2Yq4tJcRTaB1kqj/HrYKn8Yplm9bNoMJpwQ==", "cpu": [ "arm64" ], @@ -1392,9 +1393,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "15.3.5", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.3.5.tgz", - "integrity": "sha512-k8aVScYZ++BnS2P69ClK7v4nOu702jcF9AIHKu6llhHEtBSmM2zkPGl9yoqbSU/657IIIb0QHpdxEr0iW9z53A==", + "version": "16.1.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.1.1.tgz", + "integrity": "sha512-MFHrgL4TXNQbBPzkKKur4Fb5ICEJa87HM7fczFs2+HWblM7mMLdco3dvyTI+QmLBU9xgns/EeeINSZD6Ar+oLg==", "cpu": [ "arm64" ], @@ -1408,9 +1409,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "15.3.5", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.3.5.tgz", - "integrity": "sha512-2xYU0DI9DGN/bAHzVwADid22ba5d/xrbrQlr2U+/Q5WkFUzeL0TDR963BdrtLS/4bMmKZGptLeg6282H/S2i8A==", + "version": "16.1.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.1.1.tgz", + "integrity": "sha512-20bYDfgOQAPUkkKBnyP9PTuHiJGM7HzNBbuqmD0jiFVZ0aOldz+VnJhbxzjcSabYsnNjMPsE0cyzEudpYxsrUQ==", "cpu": [ "x64" ], @@ -1424,9 +1425,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "15.3.5", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.3.5.tgz", - "integrity": "sha512-TRYIqAGf1KCbuAB0gjhdn5Ytd8fV+wJSM2Nh2is/xEqR8PZHxfQuaiNhoF50XfY90sNpaRMaGhF6E+qjV1b9Tg==", + "version": "16.1.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.1.1.tgz", + "integrity": "sha512-9pRbK3M4asAHQRkwaXwu601oPZHghuSC8IXNENgbBSyImHv/zY4K5udBusgdHkvJ/Tcr96jJwQYOll0qU8+fPA==", "cpu": [ "x64" ], @@ -1440,9 +1441,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "15.3.5", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.3.5.tgz", - "integrity": "sha512-h04/7iMEUSMY6fDGCvdanKqlO1qYvzNxntZlCzfE8i5P0uqzVQWQquU1TIhlz0VqGQGXLrFDuTJVONpqGqjGKQ==", + "version": "16.1.1", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.1.1.tgz", + "integrity": "sha512-bdfQkggaLgnmYrFkSQfsHfOhk/mCYmjnrbRCGgkMcoOBZ4n+TRRSLmT/CU5SATzlBJ9TpioUyBW/vWFXTqQRiA==", "cpu": [ "arm64" ], @@ -1456,9 +1457,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "15.3.5", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.3.5.tgz", - "integrity": "sha512-5fhH6fccXxnX2KhllnGhkYMndhOiLOLEiVGYjP2nizqeGWkN10sA9taATlXwake2E2XMvYZjjz0Uj7T0y+z1yw==", + "version": "16.1.1", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.1.1.tgz", + "integrity": "sha512-Ncwbw2WJ57Al5OX0k4chM68DKhEPlrXBaSXDCi2kPi5f4d8b3ejr3RRJGfKBLrn2YJL5ezNS7w2TZLHSti8CMw==", "cpu": [ "x64" ], @@ -1554,12 +1555,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@swc/counter": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", - "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", - "license": "Apache-2.0" - }, "node_modules/@swc/helpers": { "version": "0.5.15", "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", @@ -2526,6 +2521,15 @@ "dev": true, "license": "MIT" }, + "node_modules/baseline-browser-mapping": { + "version": "2.9.14", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.14.tgz", + "integrity": "sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg==", + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -2596,17 +2600,6 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", - "dependencies": { - "streamsearch": "^1.1.0" - }, - "engines": { - "node": ">=10.16.0" - } - }, "node_modules/call-bind": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", @@ -5148,15 +5141,14 @@ "license": "MIT" }, "node_modules/next": { - "version": "15.3.8", - "resolved": "https://registry.npmjs.org/next/-/next-15.3.8.tgz", - "integrity": "sha512-L+4c5Hlr84fuaNADZbB9+ceRX9/CzwxJ+obXIGHupboB/Q1OLbSUapFs4bO8hnS/E6zV/JDX7sG1QpKVR2bguA==", + "version": "16.1.1", + "resolved": "https://registry.npmjs.org/next/-/next-16.1.1.tgz", + "integrity": "sha512-QI+T7xrxt1pF6SQ/JYFz95ro/mg/1Znk5vBebsWwbpejj1T0A23hO7GYEaVac9QUOT2BIMiuzm0L99ooq7k0/w==", "license": "MIT", "dependencies": { - "@next/env": "15.3.8", - "@swc/counter": "0.1.3", + "@next/env": "16.1.1", "@swc/helpers": "0.5.15", - "busboy": "1.6.0", + "baseline-browser-mapping": "^2.8.3", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" @@ -5165,22 +5157,22 @@ "next": "dist/bin/next" }, "engines": { - "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" + "node": ">=20.9.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "15.3.5", - "@next/swc-darwin-x64": "15.3.5", - "@next/swc-linux-arm64-gnu": "15.3.5", - "@next/swc-linux-arm64-musl": "15.3.5", - "@next/swc-linux-x64-gnu": "15.3.5", - "@next/swc-linux-x64-musl": "15.3.5", - "@next/swc-win32-arm64-msvc": "15.3.5", - "@next/swc-win32-x64-msvc": "15.3.5", - "sharp": "^0.34.1" + "@next/swc-darwin-arm64": "16.1.1", + "@next/swc-darwin-x64": "16.1.1", + "@next/swc-linux-arm64-gnu": "16.1.1", + "@next/swc-linux-arm64-musl": "16.1.1", + "@next/swc-linux-x64-gnu": "16.1.1", + "@next/swc-linux-x64-musl": "16.1.1", + "@next/swc-win32-arm64-msvc": "16.1.1", + "@next/swc-win32-x64-msvc": "16.1.1", + "sharp": "^0.34.4" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", - "@playwright/test": "^1.41.2", + "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", @@ -6292,14 +6284,6 @@ "dev": true, "license": "MIT" }, - "node_modules/streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", diff --git a/examples/nextjs-with-typescript/package.json b/examples/nextjs-with-typescript/package.json index 8ae7bc0a9..6546d4e9f 100644 --- a/examples/nextjs-with-typescript/package.json +++ b/examples/nextjs-with-typescript/package.json @@ -15,7 +15,7 @@ "@mui/material": "^7.0.2", "@mux/mux-video": "^0.17.5", "media-chrome": "file:../../", - "next": "15.3.8", + "next": "~16.1.1", "react": "19.2.2", "react-dom": "19.2.2" }, diff --git a/examples/nextjs-with-typescript/tsconfig.json b/examples/nextjs-with-typescript/tsconfig.json index f48e7ee6f..877b650fc 100644 --- a/examples/nextjs-with-typescript/tsconfig.json +++ b/examples/nextjs-with-typescript/tsconfig.json @@ -14,7 +14,7 @@ "moduleResolution": "bundler", "resolveJsonModule": true, "isolatedModules": true, - "jsx": "preserve", + "jsx": "react-jsx", "incremental": true, "plugins": [ { @@ -32,7 +32,8 @@ "next-env.d.ts", "**/*.ts", "**/*.tsx", - ".next/types/**/*.ts" + ".next/types/**/*.ts", + ".next/dev/types/**/*.ts" ], "exclude": [ "node_modules" diff --git a/src/js/media-store/util.ts b/src/js/media-store/util.ts index a7ab59f5b..39c001b8d 100644 --- a/src/js/media-store/util.ts +++ b/src/js/media-store/util.ts @@ -1,6 +1,7 @@ import { TextTrackKinds, TextTrackModes } from '../constants.js'; import { getTextTracksList, updateTracksModeTo } from '../utils/captions.js'; import { TextTrackLike } from '../utils/TextTrackLike.js'; +import { globalThis } from '../utils/server-safe-globals.js'; export const getSubtitleTracks = (stateOwners): TextTrackLike[] => { return getTextTracksList(stateOwners.media, (textTrack) => { From f26b29737194a0ce6083498b606c72ba84a13ca9 Mon Sep 17 00:00:00 2001 From: Santiago Puppo Date: Wed, 14 Jan 2026 11:57:50 -0300 Subject: [PATCH 03/12] Disable hotkeys on disconnect --- examples/vanilla/memory-leak-tester.html | 1 - src/js/media-controller.ts | 10 +++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/examples/vanilla/memory-leak-tester.html b/examples/vanilla/memory-leak-tester.html index 82b63a2b0..8f2c610de 100644 --- a/examples/vanilla/memory-leak-tester.html +++ b/examples/vanilla/memory-leak-tester.html @@ -4,7 +4,6 @@ <mux-video> example -