Skip to content

refactor(core): rework media config as a plain getter/setter#1697

Merged
luwes merged 5 commits into
mainfrom
refactor/media-config-reset
Jun 18, 2026
Merged

refactor(core): rework media config as a plain getter/setter#1697
luwes merged 5 commits into
mainfrom
refactor/media-config-reset

Conversation

@luwes

@luwes luwes commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

Summary

Make media.config a plain getter/setter and route media method calls through component overrides.

Changes

  • Config is plain values. The config getter returns exactly what was assigned — plain values and POJOs, never component instances. JSON.stringify(media.config) is valid input back into the setter.
  • Replace on assign. Setting media.config = {...} replaces the object wholesale, so stale host/engine keys are dropped. This matches declarative usage where frameworks pass the full config each render.
  • Setter routes to components. On assign, each component namespace (muxData, googleCast, …) is applied onto the registered component. Components keep their applied state when a later config omits their namespace.
  • Method delegation. play, pause, load, canPlayType, and addTextTrack resolve their owner via getOwner directly, replacing the callProp helper.
Behavior note

config no longer reflects live component instances or component-internal defaults (e.g. MuxData.playerSoftwareName). Read those from the component directly. Callers relying on incremental config merges must pass the full object or spread { ...media.config, ... }. HTML/React elements set config as a whole property, so they're unaffected.

Testing

Covered by existing + updated unit tests: @videojs/core src/dom/media (288), plus @videojs/html and @videojs/react media suites green.

Note

Medium Risk
Core media host config semantics change (replace vs merge) can break code that relied on partial media.config assignments; playback delegation changes are localized but touch critical APIs.

Overview
media.config now replaces the whole config object instead of merging into the previous bag. Assigning { hlsJs: … } alone drops other host/engine keys (e.g. preferPlayback, contentType); callers that need incremental updates must pass { ...media.config, … }.

Component config is decoupled from the config bag. host.config.muxData (and other configKey namespaces) are plain POJOs—not live component instances—and only the setter applies namespace values onto registered components. In-place mutation of host.config.fake = { … } no longer updates components; omitted namespaces on a later assignment no longer clear already-applied component state (partial updates merge onto the instance).

Component registration adopts staged namespace values from the current config when a component is added, without installing per-key proxies; destroy no longer strips component keys from config.

Media host delegation routes play, pause, load, canPlayType, and addTextTrack through getOwner directly; getProp no longer auto-binds methods. Tests cover HLS, Mux, MuxVideo, and host config edge cases.

Reviewed by Cursor Bugbot for commit c02f39f. Bugbot is set up for automated code reviews on this repo. Configure here.

@vercel

vercel Bot commented Jun 17, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
v10-sandbox Ready Ready Preview, Comment Jun 18, 2026 12:31am

Request Review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want higher recall? High effort reviews run extra passes and find more bugs. A team admin can switch effort levels in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit f029512. Configure here.

Comment thread packages/core/src/dom/media/utils/config.ts Outdated
@luwes luwes changed the base branch from refactor/media-call-prop to main June 17, 2026 23:26
luwes added 4 commits June 17, 2026 16:28
Split media utils into components/config modules and rework how
component config is exposed on the host.

- Component config is no longer bridged via Object.defineProperty on the
  config object. The getter enumerates registered components live under
  their configKey; the setter routes matching keys onto the component.
- Assigning a new config object now resets the free-form host/engine bag
  (start-fresh intent) instead of merging. Component state is preserved
  and only overwritten per-key by the incoming config.
- Reading config returns a fresh object, so mutating the result no longer
  writes through to components; use the setter instead.

Stacked on #1695.
writeConfig clears the entire free-form bag on assignment, but component
namespace values staged before addComponent lived in that bag. A later
host.config = {…} that omitted the namespace silently dropped the staged
settings, so they were never adopted when the component registered.

Keep staged config in a separate per-host store that survives free-form
resets; components adopt their namespace from it on registration.
@luwes luwes force-pushed the refactor/media-config-reset branch from 9a542da to 800c3b8 Compare June 17, 2026 23:41
@netlify

netlify Bot commented Jun 17, 2026

Copy link
Copy Markdown

Deploy Preview for vjs10-site ready!

Name Link
🔨 Latest commit c02f39f
🔍 Latest deploy log https://app.netlify.com/projects/vjs10-site/deploys/6a333c3e295b1900084197cb
😎 Deploy Preview https://deploy-preview-1697--vjs10-site.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@github-actions

github-actions Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

📦 Bundle Size Report

🎨 @videojs/html — no changes
Presets (7)
Entry Size
/video (default) 44.12 kB
/video (default + hls) 183.59 kB
/video (minimal) 43.89 kB
/video (minimal + hls) 183.30 kB
/audio (default) 37.71 kB
/audio (minimal) 36.54 kB
/background 4.22 kB
Media (10)
Entry Size
/media/background-video 1.07 kB
/media/container 1.72 kB
/media/dash-video 242.77 kB
/media/hls-video 141.25 kB
/media/mux-audio 163.70 kB
/media/mux-video 163.64 kB
/media/native-hls-video 9.01 kB
/media/simple-hls-audio-only 16.94 kB
/media/simple-hls-video 18.76 kB
/media/vimeo-video 12.32 kB
Players (5)
Entry Size
/video/player 8.06 kB
/audio/player 5.38 kB
/background/player 3.93 kB
/live-video/player 7.64 kB
/live-audio/player 5.39 kB
Skins (30)
Entry Type Size
/video/minimal-skin.css css 5.38 kB
/video/skin.css css 5.35 kB
/video/minimal-skin js 43.79 kB
/video/minimal-skin.tailwind js 44.45 kB
/video/skin js 44.17 kB
/video/skin.tailwind js 44.74 kB
/audio/minimal-skin.css css 3.60 kB
/audio/skin.css css 3.53 kB
/audio/minimal-skin js 36.56 kB
/audio/minimal-skin.tailwind js 36.91 kB
/audio/skin js 37.75 kB
/audio/skin.tailwind js 38.09 kB
/background/skin.css css 133 B
/background/skin js 1.16 kB
/live-video/minimal-skin.css css 5.38 kB
/live-video/skin.css css 5.35 kB
/live-video/minimal-skin js 42.98 kB
/live-video/minimal-skin.tailwind js 43.37 kB
/live-video/skin js 42.92 kB
/live-video/skin.tailwind js 43.40 kB
/live-audio/minimal-skin.css css 3.60 kB
/live-audio/skin.css css 3.53 kB
/live-audio/minimal-skin js 29.62 kB
/live-audio/minimal-skin.tailwind js 29.08 kB
/live-audio/skin js 30.94 kB
/live-audio/skin.tailwind js 30.52 kB
/global.css css 176 B
/shared.css css 88 B
/tailwind.css css 228 B
/skin-element js 1.37 kB
UI Components (38)
Entry Size
/ui/airplay-button 3.65 kB
/ui/alert-dialog 1.26 kB
/ui/alert-dialog-close 582 B
/ui/alert-dialog-description 418 B
/ui/alert-dialog-title 407 B
/ui/buffering-indicator 2.98 kB
/ui/captions-button 3.72 kB
/ui/captions-radio-group 3.43 kB
/ui/cast-button 3.62 kB
/ui/compounds 8.58 kB
/ui/controls 2.85 kB
/ui/error-dialog 3.45 kB
/ui/fullscreen-button 3.63 kB
/ui/hotkey 2.22 kB
/ui/menu 5.69 kB
/ui/mute-button 3.66 kB
/ui/pip-button 3.64 kB
/ui/play-button 3.58 kB
/ui/playback-rate-button 3.78 kB
/ui/playback-rate-radio-group 3.10 kB
/ui/popover 2.04 kB
/ui/poster 2.78 kB
/ui/quality-radio-group 2.49 kB
/ui/seek-button 3.63 kB
/ui/seek-indicator 3.92 kB
/ui/seek-indicator-value 232 B
/ui/slider 1.49 kB
/ui/status-announcer 3.58 kB
/ui/status-indicator 3.72 kB
/ui/status-indicator-value 265 B
/ui/thumbnail 3.33 kB
/ui/time 3.05 kB
/ui/time-slider 4.09 kB
/ui/tooltip 2.26 kB
/ui/volume-indicator 3.90 kB
/ui/volume-indicator-fill 209 B
/ui/volume-indicator-value 209 B
/ui/volume-slider 2.92 kB

Sizes are marginal over the root entry point.

⚛️ @videojs/react — no changes
Presets (7)
Entry Size
/video (default) 36.68 kB
/video (default + hls) 175.06 kB
/video (minimal) 36.74 kB
/video (minimal + hls) 175.26 kB
/audio (default) 29.97 kB
/audio (minimal) 30.04 kB
/background 754 B
Media (9)
Entry Size
/media/background-video 575 B
/media/dash-video 241.13 kB
/media/hls-video 139.75 kB
/media/mux-audio 162.35 kB
/media/mux-video 162.22 kB
/media/native-hls-video 7.39 kB
/media/simple-hls-audio-only 15.37 kB
/media/simple-hls-video 17.18 kB
/media/vimeo-video 10.58 kB
Skins (27)
Entry Type Size
/tailwind.css css 228 B
/video/minimal-skin.css css 5.30 kB
/video/skin.css css 5.26 kB
/video/minimal-skin js 36.63 kB
/video/minimal-skin.tailwind js 42.37 kB
/video/skin js 36.61 kB
/video/skin.tailwind js 42.28 kB
/audio/minimal-skin.css css 3.47 kB
/audio/skin.css css 3.39 kB
/audio/minimal-skin js 29.96 kB
/audio/minimal-skin.tailwind js 31.75 kB
/audio/skin js 29.93 kB
/audio/skin.tailwind js 33.77 kB
/background/skin.css css 90 B
/background/skin js 272 B
/live-video/minimal-skin.css css 5.30 kB
/live-video/skin.css css 5.26 kB
/live-video/minimal-skin js 32.43 kB
/live-video/minimal-skin.tailwind js 37.96 kB
/live-video/skin js 32.44 kB
/live-video/skin.tailwind js 37.98 kB
/live-audio/minimal-skin.css css 3.47 kB
/live-audio/skin.css css 3.39 kB
/live-audio/minimal-skin js 21.74 kB
/live-audio/minimal-skin.tailwind js 24.65 kB
/live-audio/skin js 21.79 kB
/live-audio/skin.tailwind js 24.76 kB
UI Components (32)
Entry Size
/ui/airplay-button 3.52 kB
/ui/alert-dialog 1.08 kB
/ui/buffering-indicator 2.05 kB
/ui/captions-button 3.55 kB
/ui/captions-radio-group 2.74 kB
/ui/cast-button 3.51 kB
/ui/controls 2.10 kB
/ui/error-dialog 2.65 kB
/ui/fullscreen-button 2.63 kB
/ui/gesture 2.17 kB
/ui/hotkey 2.05 kB
/ui/live-button 2.95 kB
/ui/menu 7.18 kB
/ui/mute-button 2.65 kB
/ui/pip-button 2.61 kB
/ui/play-button 2.65 kB
/ui/playback-rate 2.74 kB
/ui/playback-rate-button 2.61 kB
/ui/popover 2.29 kB
/ui/poster 2.33 kB
/ui/quality 2.95 kB
/ui/seek-button 2.68 kB
/ui/seek-indicator 2.08 kB
/ui/slider 3.65 kB
/ui/status-announcer 1.87 kB
/ui/status-indicator 2.06 kB
/ui/thumbnail 2.38 kB
/ui/time 2.94 kB
/ui/time-slider 4.14 kB
/ui/tooltip 2.64 kB
/ui/volume-indicator 2.06 kB
/ui/volume-slider 4.11 kB

Sizes are marginal over the root entry point.

🧩 @videojs/core — no changes
Entries (13)
Entry Size
. 8.65 kB
/dom 17.01 kB
/dom/media/custom-media-element 2.05 kB
/dom/media/dash 236.79 kB
/dom/media/google-cast 4.04 kB
/dom/media/hls 135.63 kB
/dom/media/media-host 1.25 kB
/dom/media/media-played-ranges 576 B
/dom/media/mux 151.26 kB
/dom/media/native-hls 3.05 kB
/dom/media/simple-hls 16.55 kB
/dom/media/simple-hls-audio-only 14.79 kB
/dom/media/vimeo 9.86 kB
🏷️ @videojs/element — no changes
Entries (2)
Entry Size
. 996 B
/context 943 B
📦 @videojs/store — no changes
Entries (3)
Entry Size
. 1.39 kB
/html 696 B
/react 360 B
🔧 @videojs/utils — no changes
Entries (10)
Entry Size
/array 104 B
/dom 2.22 kB
/events 319 B
/function 327 B
/object 275 B
/predicate 265 B
/string 232 B
/style 190 B
/time 478 B
/number 158 B
📦 @videojs/spf — no changes
Entries (4)
Entry Size
. 4.45 kB
/dom 6.33 kB
/hls 15.44 kB
/background-looping-video 12.95 kB

ℹ️ How to interpret

All sizes are standalone totals (minified + brotli).

Icon Meaning
No change
🔺 Increased ≤ 10%
🔴 Increased > 10%
🔽 Decreased
🆕 New (no baseline)

Run pnpm size locally to check current sizes.

@luwes luwes changed the title refactor(core): reset free-form media config on assignment refactor(core): rework media config as a plain getter/setter Jun 18, 2026
@luwes luwes merged commit b32b80e into main Jun 18, 2026
26 checks passed
@luwes luwes deleted the refactor/media-config-reset branch June 18, 2026 00:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants