diff --git a/packages/core/src/core/media/delegate.ts b/packages/core/src/core/media/delegate.ts
index 1c561879..8476097e 100644
--- a/packages/core/src/core/media/delegate.ts
+++ b/packages/core/src/core/media/delegate.ts
@@ -1,5 +1,7 @@
import type { Constructor } from '@videojs/utils/types';
+import { defineClassPropHooks } from '../utils/define-class-prop-hooks';
+
export interface MediaDelegate {
attach?(target: EventTarget): void;
detach?(): void;
@@ -52,6 +54,10 @@ export function MediaDelegateMixin, Delegate exten
}
}
+ for (let proto = DelegateClass.prototype; proto && proto !== Object.prototype; proto = Object.getPrototypeOf(proto)) {
+ defineClassPropHooks(DelegateMedia, proto);
+ }
+
return DelegateMedia as unknown as Constructor<
InstanceType &
InstanceType & {
diff --git a/packages/core/src/core/media/proxy.ts b/packages/core/src/core/media/proxy.ts
index 90b5a58d..ffe60464 100644
--- a/packages/core/src/core/media/proxy.ts
+++ b/packages/core/src/core/media/proxy.ts
@@ -1,13 +1,8 @@
import type { AnyConstructor, Constructor } from '@videojs/utils/types';
+import { defineClassPropHooks } from '../utils/define-class-prop-hooks';
export interface MediaApiProxyTarget extends EventTarget {}
-type API_TYPE = 0 | 1 | 2;
-
-const API_METHOD: API_TYPE = 0;
-const API_GET: API_TYPE = 1;
-const API_GET_SET: API_TYPE = 2;
-
/**
* This mixin creates an API from the passed classes and proxies the methods and properties to the attached target.
*
@@ -24,32 +19,6 @@ export const MediaProxyMixin = (
...AdditionalClasses: AnyConstructor[]
) => {
class MediaApiProxy {
- static extends(...MediaApiTargetClasses: AnyConstructor[]) {
- const props = getClassProps(...MediaApiTargetClasses);
-
- for (const [prop, type] of props.entries()) {
- if (prop in MediaApiProxy.prototype) continue;
-
- const config: PropertyDescriptor = {};
- if (type === API_METHOD) {
- config.value = function (this: MediaApiProxy, ...args: any[]) {
- return this.call(prop as keyof MediaApiProxyTarget, ...args);
- };
- } else if (type === API_GET || type === API_GET_SET) {
- config.get = function (this: MediaApiProxy) {
- return this.get(prop as keyof MediaApiProxyTarget);
- };
- if (type === API_GET_SET) {
- config.set = function (this: MediaApiProxy, val: any) {
- this.set(prop as keyof MediaApiProxyTarget, val);
- };
- }
- }
-
- Object.defineProperty(MediaApiProxy.prototype, prop, config);
- }
- }
-
#target: MediaApiProxyTarget | null = null;
get target() {
@@ -82,30 +51,9 @@ export const MediaProxyMixin = (
}
}
- MediaApiProxy.extends(PrimaryClass, ...AdditionalClasses);
+ for (const Class of [PrimaryClass, ...AdditionalClasses]) {
+ defineClassPropHooks(MediaApiProxy, Class.prototype);
+ }
return MediaApiProxy as unknown as Constructor;
};
-
-/**
- * Helper function to get the methods, getters, and setters from a class prototype.
- */
-export function getClassProps(...Classes: AnyConstructor[]) {
- const props = new Map();
- for (const Class of Classes) {
- const names = Object.getOwnPropertyNames(Class.prototype) as (keyof T)[];
- for (const name of names) {
- const descriptor = Object.getOwnPropertyDescriptor(Class.prototype, name);
- if (typeof descriptor?.value === 'function') {
- props.set(name, API_METHOD);
- } else if (typeof descriptor?.get === 'function') {
- if (typeof descriptor?.set === 'function') {
- props.set(name, API_GET_SET);
- } else {
- props.set(name, API_GET);
- }
- }
- }
- }
- return props;
-}
diff --git a/packages/core/src/core/utils/define-class-prop-hooks.ts b/packages/core/src/core/utils/define-class-prop-hooks.ts
new file mode 100644
index 00000000..a4bf81ab
--- /dev/null
+++ b/packages/core/src/core/utils/define-class-prop-hooks.ts
@@ -0,0 +1,29 @@
+import type { Constructor } from '@videojs/utils/types';
+
+export function defineClassPropHooks>(Class: T, BaseClassProto: PropertyDescriptorMap) {
+ for (const prop of Object.getOwnPropertyNames(BaseClassProto)) {
+ if (prop in Class.prototype) continue;
+
+ const descriptor = Object.getOwnPropertyDescriptor(BaseClassProto, prop);
+ if (!descriptor) continue;
+
+ const config: PropertyDescriptor = {};
+ if (typeof descriptor.value === 'function') {
+ config.value = function (this: InstanceType, ...args: any[]) {
+ return this.call?.(prop, ...args);
+ };
+ } else if (descriptor.get) {
+ config.get = function (this: InstanceType) {
+ return this.get?.(prop);
+ };
+
+ if (descriptor.set) {
+ config.set = function (this: InstanceType, val: any) {
+ this.set?.(prop, val);
+ };
+ }
+ }
+
+ Object.defineProperty(Class.prototype, prop, config);
+ }
+}
diff --git a/packages/html/src/media/hls-video/index.ts b/packages/html/src/media/hls-video/index.ts
index 0544c465..e4c06d77 100644
--- a/packages/html/src/media/hls-video/index.ts
+++ b/packages/html/src/media/hls-video/index.ts
@@ -27,7 +27,7 @@ export class HlsVideo extends HlsCustomMedia {
}
disconnectedCallback(): void {
- super.disconnectedCallback();
+ super.disconnectedCallback?.();
if (!this.hasAttribute('keep-alive')) {
this.destroy();