mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-24 23:51:20 -08:00
refactor(core): CORE-08 type plugin registration and guard closed instances
This commit is contained in:
1 parent
f9707bad71
commit
874dac9f22
36 files changed
+2865
-142
No files matched your search
@@ -4,6 +4,56 @@ ArtPlayer keeps its existing constructor, player mixins, plugins and DOM/CSS hoo
|
||||
The production entry is still `src/index.js`; this document marks actual migrated
|
||||
boundaries rather than describing the entire core as TypeScript.
|
||||
|
||||
## Plugin registration and ownership
|
||||
|
||||
`src/plugins/index.ts` orchestrates registration; types.ts defines generic factories,
|
||||
minimal option hosts and internal sync/Promise return types. builtins.ts installs the
|
||||
five existing builtins in their original order and reads each condition at its turn.
|
||||
It keeps the mobile/live exclusions, including no fastForward for live media. The
|
||||
constructor captures option once before builtin installation, then traverses the
|
||||
same live user-plugin array. Builtin implementations remain JS until CORE-18.
|
||||
|
||||
registration.ts owns result naming and non-enumerable/non-writable/non-configurable
|
||||
registry properties. Names still prefer result.name, then factory.name, then the
|
||||
current completion-time id. Duplicate detection uses own properties; failed factory
|
||||
calls still consume an id. No new name restrictions or thenable assimilation are
|
||||
introduced. Native object-key coercion remains in its three historical positions;
|
||||
the final coercion is resolved before defining so a reentrant destroy cannot publish
|
||||
a property on a closing registry. Dynamic name/key assertions are local to this
|
||||
legacy boundary and do not claim that arbitrary plugin returns are validated.
|
||||
|
||||
Lifecycle.isClosing covers both the reset phase and a disposed scope. Public add
|
||||
after closure throws before incrementing id or executing the factory. Pending add
|
||||
fulfillments still settle with the original registry, but discard late results;
|
||||
factory rejection identity remains unchanged. A synchronous close during construction
|
||||
stops subsequent factories. Constructor-owned Promise rejections are observed and
|
||||
reported once with console.warn because no caller receives those promises. Public
|
||||
add retains its rejecting Promise rather than hiding failures.
|
||||
|
||||
The manager does not call a result's destroy method: existing result methods are not
|
||||
an agreed disposal protocol. Plugins own their subscriptions and external SDK/media
|
||||
resources; arbitrary work created by a factory after an await still needs that
|
||||
plugin's lifecycle guards. Preventing late registry writes does not certify every
|
||||
plugin's cleanup. Names that shadow prototype methods and completion-time fallback
|
||||
naming keep their historical semantics.
|
||||
|
||||
Public PluginFactory and Plugins are type-only contracts. Augment `artplayer/types`
|
||||
for a common plugin-result/event interface across old TS, NodeNext CJS/ESM and Bundler;
|
||||
augmenting the CJS root alias directly is not equivalent. The new subpath has only
|
||||
a types condition and typesVersions fallback: runtime require/import must reject it.
|
||||
Public add's legacy return signature remains tracked by BASE-TYPE-04/CORE-21; internal
|
||||
registration types preserve known synchronous/Promise results and use a union for
|
||||
unknown results. The Promise distinction retains instanceof semantics: foreign
|
||||
Promises and ordinary thenables are stored synchronously, not assimilated.
|
||||
|
||||
Tests: plugins.test.js covers naming/coercion, sync/async/error identity, closed scopes,
|
||||
reentry and constructor-owned rejection. plugins-source.ts checks internal returns;
|
||||
plugins-public.ts checks the common augmentation path in every package consumer mode.
|
||||
Browser plugins.spec.js compares old/new late registration, constructor close/reporting,
|
||||
and builtin order/live exclusions under a mobile user agent. That UA test is not a
|
||||
physical-device or builtin-feature acceptance test. Run the full installed-artifact
|
||||
browser suite after modifying the manager or its lifecycle boundaries.
|
||||
|
||||
## Input and resolved configuration
|
||||
|
||||
`src/option/defaults.ts` creates fresh defaults on every Artplayer.option access,
|
||||
|
||||
Vendored
+1
-1
@@ -4,4 +4,4 @@
|
||||
* (c) 2017-2026 Harvey Zhao
|
||||
* Released under the MIT License.
|
||||
*/
|
||||
!function(t,e){"object"===typeof exports&&"undefined"!==typeof module?module.exports=e():"function"==typeof define&&define.amd?(t.Artplayer=e(),define(function(){return t.Artplayer})):(t="undefined"!==typeof globalThis?globalThis:t||self).Artplayer=e()}(this,function(){"use strict";function t(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var e,r={exports:{}};var o=(e||(e=1,r.exports=function(){function t(e){return(t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(e)}var e=Object.prototype.toString,r=function(r){if(void 0===r)return"undefined";if(null===r)return"null";var a=t(r);if("boolean"===a)return"boolean";if("string"===a)return"string";if("number"===a)return"number";if("symbol"===a)return"symbol";if("function"===a)return"GeneratorFunction"===o(r)?"generatorfunction":"function";if(function(t){return Array.isArray?Array.isArray(t):t instanceof Array}(r))return"array";if(function(t){return!(!t.constructor||"function"!=typeof t.constructor.isBuffer)&&t.constructor.isBuffer(t)}(r))return"buffer";if(function(t){try{if("number"==typeof t.length&&"function"==typeof t.callee)return!0}catch(e){if(-1!==e.message.indexOf("callee"))return!0}return!1}(r))return"arguments";if(function(t){return t instanceof Date||"function"==typeof t.toDateString&&"function"==typeof t.getDate&&"function"==typeof t.setDate}(r))return"date";if(function(t){return t instanceof Error||"string"==typeof t.message&&t.constructor&&"number"==typeof t.constructor.stackTraceLimit}(r))return"error";if(function(t){return t instanceof RegExp||"string"==typeof t.flags&&"boolean"==typeof t.ignoreCase&&"boolean"==typeof t.multiline&&"boolean"==typeof t.global}(r))return"regexp";switch(o(r)){case"Symbol":return"symbol";case"Promise":return"promise";case"WeakMap":return"weakmap";case"WeakSet":return"weakset";case"Map":return"map";case"Set":return"set";case"Int8Array":return"int8array";case"Uint8Array":return"uint8array";case"Uint8ClampedArray":return"uint8clampedarray";case"Int16Array":return"int16array";case"Uint16Array":return"uint16array";case"Int32Array":return"int32array";case"Uint32Array":return"uint32array";case"Float32Array":return"float32array";case"Float64Array":return"float64array"}if(function(t){return"function"==typeof t.throw&&"function"==typeof t.return&&"function"==typeof t.next}(r))return"generator";switch(a=e.call(r)){case"[object Object]":return"object";case"[object Map Iterator]":return"mapiterator";case"[object Set Iterator]":return"setiterator";case"[object String Iterator]":return"stringiterator";case"[object Array Iterator]":return"arrayiterator"}return a.slice(8,-1).toLowerCase().replace(/\s/g,"")};function o(t){return t.constructor?t.constructor.name:null}function a(t,e){var o=2<arguments.length&&void 0!==arguments[2]?arguments[2]:["option"];return n(t,e,o),i(t,e,o),function(t,e,o){var s=r(e),l=r(t);if("object"===s){if("object"!==l)throw new Error("[Type Error]: '".concat(o.join("."),"' require 'object' type, but got '").concat(l,"'"));Object.keys(e).forEach(function(r){var s=t[r],l=e[r],c=o.slice();c.push(r),n(s,l,c),i(s,l,c),a(s,l,c)})}if("array"===s){if("array"!==l)throw new Error("[Type Error]: '".concat(o.join("."),"' require 'array' type, but got '").concat(l,"'"));t.forEach(function(r,s){var l=t[s],c=e[s]||e[0],d=o.slice();d.push(s),n(l,c,d),i(l,c,d),a(l,c,d)})}}(t,e,o),t}function n(t,e,o){if("string"===r(e)){var a=r(t);if("?"===e[0]&&(e=e.slice(1)+"|undefined"),!(-1<e.indexOf("|")?e.split("|").map(function(t){return t.toLowerCase().trim()}).filter(Boolean).some(function(t){return a===t}):e.toLowerCase().trim()===a))throw new Error("[Type Error]: '".concat(o.join("."),"' require '").concat(e,"' type, but got '").concat(a,"'"))}}function i(t,e,o){if("function"===r(e)){var a=e(t,r(t),o);if(!0!==a){var n=r(a);throw"string"===n?new Error(a):"error"===n?a:new Error("[Validator Error]: The scheme for '".concat(o.join("."),"' validator require return true, but got '").concat(a,"'"))}}}return a.kindOf=r,a}()),r.exports);const a=t(o),n="5.4.1",i={properties:["audioTracks","autoplay","buffered","controller","controls","crossOrigin","currentSrc","currentTime","defaultMuted","defaultPlaybackRate","duration","ended","error","loop","mediaGroup","muted","networkState","paused","playbackRate","played","preload","readyState","seekable","seeking","src","startDate","textTracks","videoTracks","volume"],methods:["addTextTrack","canPlayType","load","play","pause"],events:["abort","canplay","canplaythrough","durationchange","emptied","ended","error","loadeddata","loadedmetadata","loadstart","pause","play","playing","progress","ratechange","seeked","seeking","stalled","suspend","timeupdate","volumechange","waiting"],prototypes:["width","height","videoWidth","videoHeight","poster","webkitDecodedFrameCount","webkitDroppedFrameCount","playsInline","webLine truncated
|
||||
!function(t,e){"object"===typeof exports&&"undefined"!==typeof module?module.exports=e():"function"==typeof define&&define.amd?(t.Artplayer=e(),define(function(){return t.Artplayer})):(t="undefined"!==typeof globalThis?globalThis:t||self).Artplayer=e()}(this,function(){"use strict";function t(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var e,r={exports:{}};var o=(e||(e=1,r.exports=function(){function t(e){return(t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(e)}var e=Object.prototype.toString,r=function(r){if(void 0===r)return"undefined";if(null===r)return"null";var a=t(r);if("boolean"===a)return"boolean";if("string"===a)return"string";if("number"===a)return"number";if("symbol"===a)return"symbol";if("function"===a)return"GeneratorFunction"===o(r)?"generatorfunction":"function";if(function(t){return Array.isArray?Array.isArray(t):t instanceof Array}(r))return"array";if(function(t){return!(!t.constructor||"function"!=typeof t.constructor.isBuffer)&&t.constructor.isBuffer(t)}(r))return"buffer";if(function(t){try{if("number"==typeof t.length&&"function"==typeof t.callee)return!0}catch(e){if(-1!==e.message.indexOf("callee"))return!0}return!1}(r))return"arguments";if(function(t){return t instanceof Date||"function"==typeof t.toDateString&&"function"==typeof t.getDate&&"function"==typeof t.setDate}(r))return"date";if(function(t){return t instanceof Error||"string"==typeof t.message&&t.constructor&&"number"==typeof t.constructor.stackTraceLimit}(r))return"error";if(function(t){return t instanceof RegExp||"string"==typeof t.flags&&"boolean"==typeof t.ignoreCase&&"boolean"==typeof t.multiline&&"boolean"==typeof t.global}(r))return"regexp";switch(o(r)){case"Symbol":return"symbol";case"Promise":return"promise";case"WeakMap":return"weakmap";case"WeakSet":return"weakset";case"Map":return"map";case"Set":return"set";case"Int8Array":return"int8array";case"Uint8Array":return"uint8array";case"Uint8ClampedArray":return"uint8clampedarray";case"Int16Array":return"int16array";case"Uint16Array":return"uint16array";case"Int32Array":return"int32array";case"Uint32Array":return"uint32array";case"Float32Array":return"float32array";case"Float64Array":return"float64array"}if(function(t){return"function"==typeof t.throw&&"function"==typeof t.return&&"function"==typeof t.next}(r))return"generator";switch(a=e.call(r)){case"[object Object]":return"object";case"[object Map Iterator]":return"mapiterator";case"[object Set Iterator]":return"setiterator";case"[object String Iterator]":return"stringiterator";case"[object Array Iterator]":return"arrayiterator"}return a.slice(8,-1).toLowerCase().replace(/\s/g,"")};function o(t){return t.constructor?t.constructor.name:null}function a(t,e){var o=2<arguments.length&&void 0!==arguments[2]?arguments[2]:["option"];return n(t,e,o),i(t,e,o),function(t,e,o){var s=r(e),l=r(t);if("object"===s){if("object"!==l)throw new Error("[Type Error]: '".concat(o.join("."),"' require 'object' type, but got '").concat(l,"'"));Object.keys(e).forEach(function(r){var s=t[r],l=e[r],c=o.slice();c.push(r),n(s,l,c),i(s,l,c),a(s,l,c)})}if("array"===s){if("array"!==l)throw new Error("[Type Error]: '".concat(o.join("."),"' require 'array' type, but got '").concat(l,"'"));t.forEach(function(r,s){var l=t[s],c=e[s]||e[0],d=o.slice();d.push(s),n(l,c,d),i(l,c,d),a(l,c,d)})}}(t,e,o),t}function n(t,e,o){if("string"===r(e)){var a=r(t);if("?"===e[0]&&(e=e.slice(1)+"|undefined"),!(-1<e.indexOf("|")?e.split("|").map(function(t){return t.toLowerCase().trim()}).filter(Boolean).some(function(t){return a===t}):e.toLowerCase().trim()===a))throw new Error("[Type Error]: '".concat(o.join("."),"' require '").concat(e,"' type, but got '").concat(a,"'"))}}function i(t,e,o){if("function"===r(e)){var a=e(t,r(t),o);if(!0!==a){var n=r(a);throw"string"===n?new Error(a):"error"===n?a:new Error("[Validator Error]: The scheme for '".concat(o.join("."),"' validator require return true, but got '").concat(a,"'"))}}}return a.kindOf=r,a}()),r.exports);const a=t(o),n="5.4.1",i={properties:["audioTracks","autoplay","buffered","controller","controls","crossOrigin","currentSrc","currentTime","defaultMuted","defaultPlaybackRate","duration","ended","error","loop","mediaGroup","muted","networkState","paused","playbackRate","played","preload","readyState","seekable","seeking","src","startDate","textTracks","videoTracks","volume"],methods:["addTextTrack","canPlayType","load","play","pause"],events:["abort","canplay","canplaythrough","durationchange","emptied","ended","error","loadeddata","loadedmetadata","loadstart","pause","play","playing","progress","ratechange","seeked","seeking","stalled","suspend","timeupdate","volumechange","waiting"],prototypes:["width","height","videoWidth","videoHeight","poster","webkitDecodedFrameCount","webkitDroppedFrameCount","playsInline","webLine truncated
|
||||
+1
-1
@@ -4,4 +4,4 @@
|
||||
* (c) 2017-2026 Harvey Zhao
|
||||
* Released under the MIT License.
|
||||
*/
|
||||
!function(t,e){"object"===typeof exports&&"undefined"!==typeof module?module.exports=e():"function"==typeof define&&define.amd?(t.Artplayer=e(),define(function(){return t.Artplayer})):(t="undefined"!==typeof globalThis?globalThis:t||self).Artplayer=e()}(this,function(){"use strict";var t,e=Object.defineProperty,r=Object.defineProperties,o=Object.getOwnPropertyDescriptors,a=Object.getOwnPropertySymbols,n=Object.prototype.hasOwnProperty,i=Object.prototype.propertyIsEnumerable,s=(t,r,o)=>r in t?e(t,r,{enumerable:!0,configurable:!0,writable:!0,value:o}):t[r]=o,l=(t,e)=>{for(var r in e||(e={}))n.call(e,r)&&s(t,r,e[r]);if(a)for(var r of a(e))i.call(e,r)&&s(t,r,e[r]);return t},c=(t,e)=>r(t,o(e)),d=(t,e,r)=>new Promise((o,a)=>{var n=t=>{try{s(r.next(t))}catch(e){a(e)}},i=t=>{try{s(r.throw(t))}catch(e){a(e)}},s=t=>t.done?o(t.value):Promise.resolve(t.value).then(n,i);s((r=r.apply(t,e)).next())});function p(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var h,u={exports:{}};var m=(h||(h=1,u.exports=function(){function t(e){return(t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(e)}var e=Object.prototype.toString,r=function(r){if(void 0===r)return"undefined";if(null===r)return"null";var a=t(r);if("boolean"===a)return"boolean";if("string"===a)return"string";if("number"===a)return"number";if("symbol"===a)return"symbol";if("function"===a)return"GeneratorFunction"===o(r)?"generatorfunction":"function";if(function(t){return Array.isArray?Array.isArray(t):t instanceof Array}(r))return"array";if(function(t){return!(!t.constructor||"function"!=typeof t.constructor.isBuffer)&&t.constructor.isBuffer(t)}(r))return"buffer";if(function(t){try{if("number"==typeof t.length&&"function"==typeof t.callee)return!0}catch(e){if(-1!==e.message.indexOf("callee"))return!0}return!1}(r))return"arguments";if(function(t){return t instanceof Date||"function"==typeof t.toDateString&&"function"==typeof t.getDate&&"function"==typeof t.setDate}(r))return"date";if(function(t){return t instanceof Error||"string"==typeof t.message&&t.constructor&&"number"==typeof t.constructor.stackTraceLimit}(r))return"error";if(function(t){return t instanceof RegExp||"string"==typeof t.flags&&"boolean"==typeof t.ignoreCase&&"boolean"==typeof t.multiline&&"boolean"==typeof t.global}(r))return"regexp";switch(o(r)){case"Symbol":return"symbol";case"Promise":return"promise";case"WeakMap":return"weakmap";case"WeakSet":return"weakset";case"Map":return"map";case"Set":return"set";case"Int8Array":return"int8array";case"Uint8Array":return"uint8array";case"Uint8ClampedArray":return"uint8clampedarray";case"Int16Array":return"int16array";case"Uint16Array":return"uint16array";case"Int32Array":return"int32array";case"Uint32Array":return"uint32array";case"Float32Array":return"float32array";case"Float64Array":return"float64array"}if(function(t){return"function"==typeof t.throw&&"function"==typeof t.return&&"function"==typeof t.next}(r))return"generator";switch(a=e.call(r)){case"[object Object]":return"object";case"[object Map Iterator]":return"mapiterator";case"[object Set Iterator]":return"setiterator";case"[object String Iterator]":return"stringiterator";case"[object Array Iterator]":return"arrayiterator"}return a.slice(8,-1).toLowerCase().replace(/\s/g,"")};function o(t){return t.constructor?t.constructor.name:null}function a(t,e){var o=2<arguments.length&&void 0!==arguments[2]?arguments[2]:["option"];return n(t,e,o),i(t,e,o),function(t,e,o){var s=r(e),l=r(t);if("object"===s){if("object"!==l)throw new Error("[Type Error]: '".concat(o.join("."),"' require 'object' type, but got '").concat(l,"'"));Object.keys(e).forEach(function(r){var s=t[r],l=e[r],c=o.slice();c.push(r),n(s,l,c),i(s,l,c),a(s,l,c)})}if("array"===s){if("array"!==l)throw new Error("[Type Error]: '".concat(o.join("."),"' require 'array' type, but got '").concat(l,"'"));t.forEach(function(r,s){var l=t[s],c=e[s]||e[0],d=o.slice();d.push(s),n(l,c,d),i(l,c,d),a(l,c,d)})}}(t,e,o),t}function n(t,e,o){if("string"===r(e)){var a=r(t);if("?"===e[0]&&(e=e.slice(1)+"|undefined"),!(-1<e.indexOf("|")?e.split("|").map(function(t){return t.toLowerCase().trim()}).filter(Boolean).some(function(t){return a===t}):e.toLowerCase().trim()===a))throw new Error("[Type Error]: '".concat(o.join("."),"' require '").concat(e,"' type, but got '").concat(a,"'"))}}function i(t,e,o){if("function"===r(e)){var a=e(t,r(t),o);if(!0!==a){var n=r(a);throw"string"===n?new Error(a):"error"===n?a:new Error("[Validator Error]: The scheme for '".concat(o.join("."),"' validator require return true, but got '").concat(a,"'"))}}}return a.kindOf=r,a}()),u.exports);const f=p(m),g="5.4.1",v={properties:["audioTracks","autoplay","buffered","controller","controls","crossOrigin","currentSrc","currentTime","defaultMuted","defaultPlaybackRate","duration","ended","error","loop","meLine truncated
|
||||
!function(t,e){"object"===typeof exports&&"undefined"!==typeof module?module.exports=e():"function"==typeof define&&define.amd?(t.Artplayer=e(),define(function(){return t.Artplayer})):(t="undefined"!==typeof globalThis?globalThis:t||self).Artplayer=e()}(this,function(){"use strict";var t,e=Object.defineProperty,r=Object.defineProperties,o=Object.getOwnPropertyDescriptors,a=Object.getOwnPropertySymbols,n=Object.prototype.hasOwnProperty,i=Object.prototype.propertyIsEnumerable,s=(t,r,o)=>r in t?e(t,r,{enumerable:!0,configurable:!0,writable:!0,value:o}):t[r]=o,l=(t,e)=>{for(var r in e||(e={}))n.call(e,r)&&s(t,r,e[r]);if(a)for(var r of a(e))i.call(e,r)&&s(t,r,e[r]);return t},c=(t,e)=>r(t,o(e)),d=(t,e,r)=>new Promise((o,a)=>{var n=t=>{try{s(r.next(t))}catch(e){a(e)}},i=t=>{try{s(r.throw(t))}catch(e){a(e)}},s=t=>t.done?o(t.value):Promise.resolve(t.value).then(n,i);s((r=r.apply(t,e)).next())});function p(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var h,u={exports:{}};var m=(h||(h=1,u.exports=function(){function t(e){return(t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(e)}var e=Object.prototype.toString,r=function(r){if(void 0===r)return"undefined";if(null===r)return"null";var a=t(r);if("boolean"===a)return"boolean";if("string"===a)return"string";if("number"===a)return"number";if("symbol"===a)return"symbol";if("function"===a)return"GeneratorFunction"===o(r)?"generatorfunction":"function";if(function(t){return Array.isArray?Array.isArray(t):t instanceof Array}(r))return"array";if(function(t){return!(!t.constructor||"function"!=typeof t.constructor.isBuffer)&&t.constructor.isBuffer(t)}(r))return"buffer";if(function(t){try{if("number"==typeof t.length&&"function"==typeof t.callee)return!0}catch(e){if(-1!==e.message.indexOf("callee"))return!0}return!1}(r))return"arguments";if(function(t){return t instanceof Date||"function"==typeof t.toDateString&&"function"==typeof t.getDate&&"function"==typeof t.setDate}(r))return"date";if(function(t){return t instanceof Error||"string"==typeof t.message&&t.constructor&&"number"==typeof t.constructor.stackTraceLimit}(r))return"error";if(function(t){return t instanceof RegExp||"string"==typeof t.flags&&"boolean"==typeof t.ignoreCase&&"boolean"==typeof t.multiline&&"boolean"==typeof t.global}(r))return"regexp";switch(o(r)){case"Symbol":return"symbol";case"Promise":return"promise";case"WeakMap":return"weakmap";case"WeakSet":return"weakset";case"Map":return"map";case"Set":return"set";case"Int8Array":return"int8array";case"Uint8Array":return"uint8array";case"Uint8ClampedArray":return"uint8clampedarray";case"Int16Array":return"int16array";case"Uint16Array":return"uint16array";case"Int32Array":return"int32array";case"Uint32Array":return"uint32array";case"Float32Array":return"float32array";case"Float64Array":return"float64array"}if(function(t){return"function"==typeof t.throw&&"function"==typeof t.return&&"function"==typeof t.next}(r))return"generator";switch(a=e.call(r)){case"[object Object]":return"object";case"[object Map Iterator]":return"mapiterator";case"[object Set Iterator]":return"setiterator";case"[object String Iterator]":return"stringiterator";case"[object Array Iterator]":return"arrayiterator"}return a.slice(8,-1).toLowerCase().replace(/\s/g,"")};function o(t){return t.constructor?t.constructor.name:null}function a(t,e){var o=2<arguments.length&&void 0!==arguments[2]?arguments[2]:["option"];return n(t,e,o),i(t,e,o),function(t,e,o){var s=r(e),l=r(t);if("object"===s){if("object"!==l)throw new Error("[Type Error]: '".concat(o.join("."),"' require 'object' type, but got '").concat(l,"'"));Object.keys(e).forEach(function(r){var s=t[r],l=e[r],c=o.slice();c.push(r),n(s,l,c),i(s,l,c),a(s,l,c)})}if("array"===s){if("array"!==l)throw new Error("[Type Error]: '".concat(o.join("."),"' require 'array' type, but got '").concat(l,"'"));t.forEach(function(r,s){var l=t[s],c=e[s]||e[0],d=o.slice();d.push(s),n(l,c,d),i(l,c,d),a(l,c,d)})}}(t,e,o),t}function n(t,e,o){if("string"===r(e)){var a=r(t);if("?"===e[0]&&(e=e.slice(1)+"|undefined"),!(-1<e.indexOf("|")?e.split("|").map(function(t){return t.toLowerCase().trim()}).filter(Boolean).some(function(t){return a===t}):e.toLowerCase().trim()===a))throw new Error("[Type Error]: '".concat(o.join("."),"' require '").concat(e,"' type, but got '").concat(a,"'"))}}function i(t,e,o){if("function"===r(e)){var a=e(t,r(t),o);if(!0!==a){var n=r(a);throw"string"===n?new Error(a):"error"===n?a:new Error("[Validator Error]: The scheme for '".concat(o.join("."),"' validator require return true, but got '").concat(a,"'"))}}}return a.kindOf=r,a}()),u.exports);const f=p(m),g="5.4.1",v={properties:["audioTracks","autoplay","buffered","controller","controls","crossOrigin","currentSrc","currentTime","defaultMuted","defaultPlaybackRate","duration","ended","error","loop","meLine truncated
|
||||
+47
-26
@@ -1162,6 +1162,10 @@ function stateOf(owner) {
|
||||
function getScope(owner) {
|
||||
return stateOf(owner).scope;
|
||||
}
|
||||
function isClosing(owner) {
|
||||
const state2 = stateOf(owner);
|
||||
return state2.destroying || state2.scope.closed;
|
||||
}
|
||||
function ownContainer(owner, container, rollback) {
|
||||
const current = containers.get(container);
|
||||
if (current && current !== owner)
|
||||
@@ -4133,46 +4137,63 @@ function miniProgressBar(art) {
|
||||
});
|
||||
return { name: "mini-progress-bar" };
|
||||
}
|
||||
function installBuiltins(registry, option) {
|
||||
if (!isClosing(registry.art) && option.miniProgressBar && !option.isLive)
|
||||
registry.add(miniProgressBar);
|
||||
if (!isClosing(registry.art) && option.lock && isMobile)
|
||||
registry.add(lock);
|
||||
if (!isClosing(registry.art) && option.autoPlayback && !option.isLive)
|
||||
registry.add(autoPlayback);
|
||||
if (!isClosing(registry.art) && option.autoOrientation && isMobile)
|
||||
registry.add(autoOrientation);
|
||||
if (!isClosing(registry.art) && option.fastForward && isMobile && !option.isLive)
|
||||
registry.add(fastForward);
|
||||
}
|
||||
function registerPlugin(registry, plugin, result) {
|
||||
if (isClosing(registry.art))
|
||||
return registry;
|
||||
const name = result && result.name || plugin.name || `plugin${registry.id}`;
|
||||
if (isClosing(registry.art))
|
||||
return registry;
|
||||
let key = name;
|
||||
const duplicate = has(registry, key);
|
||||
if (isClosing(registry.art))
|
||||
return registry;
|
||||
const message = `Cannot add a plugin that already has the same name: ${name}`;
|
||||
if (isClosing(registry.art))
|
||||
return registry;
|
||||
errorHandle(!duplicate, message);
|
||||
if (typeof name === "object" && name !== null || typeof name === "function")
|
||||
key = Reflect.ownKeys({ [key]: void 0 })[0];
|
||||
if (!isClosing(registry.art))
|
||||
def(registry, key, { value: result });
|
||||
return registry;
|
||||
}
|
||||
class Plugins {
|
||||
constructor(art) {
|
||||
this.art = art;
|
||||
this.id = 0;
|
||||
const { option } = art;
|
||||
if (option.miniProgressBar && !option.isLive) {
|
||||
this.add(miniProgressBar);
|
||||
}
|
||||
if (option.lock && isMobile) {
|
||||
this.add(lock);
|
||||
}
|
||||
if (option.autoPlayback && !option.isLive) {
|
||||
this.add(autoPlayback);
|
||||
}
|
||||
if (option.autoOrientation && isMobile) {
|
||||
this.add(autoOrientation);
|
||||
}
|
||||
if (option.fastForward && isMobile && !option.isLive) {
|
||||
this.add(fastForward);
|
||||
}
|
||||
installBuiltins(this, option);
|
||||
for (let index = 0; index < option.plugins.length; index++) {
|
||||
this.add(option.plugins[index]);
|
||||
if (isClosing(art))
|
||||
return;
|
||||
const registration = this.add(option.plugins[index]);
|
||||
if (registration instanceof Promise) {
|
||||
registration.catch((error2) => console.warn("Failed to initialize ArtPlayer plugin:", error2));
|
||||
}
|
||||
}
|
||||
}
|
||||
add(plugin) {
|
||||
errorHandle(!isClosing(this.art), "Cannot add a plugin after ArtPlayer is destroyed");
|
||||
this.id += 1;
|
||||
const result = plugin.call(this.art, this.art);
|
||||
if (result instanceof Promise) {
|
||||
if (result instanceof Promise)
|
||||
return result.then((res) => this.next(plugin, res));
|
||||
} else {
|
||||
return this.next(plugin, result);
|
||||
}
|
||||
return this.next(plugin, result);
|
||||
}
|
||||
next(plugin, result) {
|
||||
const pluginName = result && result.name || plugin.name || `plugin${this.id}`;
|
||||
errorHandle(!has(this, pluginName), `Cannot add a plugin that already has the same name: ${pluginName}`);
|
||||
def(this, pluginName, {
|
||||
value: result
|
||||
});
|
||||
return this;
|
||||
return registerPlugin(this, plugin, result);
|
||||
}
|
||||
}
|
||||
function aspectRatio(art) {
|
||||
|
||||
@@ -28,6 +28,9 @@
|
||||
"default": "./dist/artplayer.js"
|
||||
}
|
||||
},
|
||||
"./types": {
|
||||
"types": "./types/artplayer.d.ts"
|
||||
},
|
||||
"./legacy": {
|
||||
"import": {
|
||||
"types": "./types/artplayer.d.cts",
|
||||
@@ -54,6 +57,9 @@
|
||||
"types": "./types/artplayer.d.ts",
|
||||
"typesVersions": {
|
||||
"*": {
|
||||
"types": [
|
||||
"types/artplayer.d.ts"
|
||||
],
|
||||
"i18n/*": [
|
||||
"types/legacy/language.d.ts"
|
||||
],
|
||||
|
||||
@@ -32,6 +32,11 @@ export function getScope(owner: object): ResourceScope {
|
||||
return stateOf(owner).scope
|
||||
}
|
||||
|
||||
export function isClosing(owner: object): boolean {
|
||||
const state = stateOf(owner)
|
||||
return state.destroying || state.scope.closed
|
||||
}
|
||||
|
||||
export function ownContainer(owner: object, container: Element, rollback: () => void): void {
|
||||
const current = containers.get(container)
|
||||
if (current && current !== owner)
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import type { BuiltinRegistry, PluginHost } from './types'
|
||||
import { isClosing } from '../lifecycle/instance'
|
||||
import { isMobile } from '../utils/compatibility'
|
||||
import autoOrientation from './autoOrientation'
|
||||
import autoPlayback from './autoPlayback'
|
||||
import fastForward from './fastForward'
|
||||
import lock from './lock'
|
||||
import miniProgressBar from './miniProgressBar'
|
||||
|
||||
export default function installBuiltins<Host extends PluginHost<Host>>(registry: BuiltinRegistry<Host>, option: PluginHost<Host>['option']): void {
|
||||
// Read each condition at its original turn; earlier plugins may change options.
|
||||
if (!isClosing(registry.art) && option.miniProgressBar && !option.isLive)
|
||||
registry.add(miniProgressBar)
|
||||
if (!isClosing(registry.art) && option.lock && isMobile)
|
||||
registry.add(lock)
|
||||
if (!isClosing(registry.art) && option.autoPlayback && !option.isLive)
|
||||
registry.add(autoPlayback)
|
||||
if (!isClosing(registry.art) && option.autoOrientation && isMobile)
|
||||
registry.add(autoOrientation)
|
||||
if (!isClosing(registry.art) && option.fastForward && isMobile && !option.isLive)
|
||||
registry.add(fastForward)
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
import { def, errorHandle, has, isMobile } from '../utils'
|
||||
import autoOrientation from './autoOrientation'
|
||||
import autoPlayback from './autoPlayback'
|
||||
import fastForward from './fastForward'
|
||||
import lock from './lock'
|
||||
import miniProgressBar from './miniProgressBar'
|
||||
|
||||
export default class Plugins {
|
||||
constructor(art) {
|
||||
this.art = art
|
||||
this.id = 0
|
||||
|
||||
const { option } = art
|
||||
|
||||
if (option.miniProgressBar && !option.isLive) {
|
||||
this.add(miniProgressBar)
|
||||
}
|
||||
|
||||
if (option.lock && isMobile) {
|
||||
this.add(lock)
|
||||
}
|
||||
|
||||
if (option.autoPlayback && !option.isLive) {
|
||||
this.add(autoPlayback)
|
||||
}
|
||||
|
||||
if (option.autoOrientation && isMobile) {
|
||||
this.add(autoOrientation)
|
||||
}
|
||||
|
||||
if (option.fastForward && isMobile && !option.isLive) {
|
||||
this.add(fastForward)
|
||||
}
|
||||
|
||||
for (let index = 0; index < option.plugins.length; index++) {
|
||||
this.add(option.plugins[index])
|
||||
}
|
||||
}
|
||||
|
||||
add(plugin) {
|
||||
this.id += 1
|
||||
const result = plugin.call(this.art, this.art)
|
||||
if (result instanceof Promise) {
|
||||
return result.then(res => this.next(plugin, res))
|
||||
}
|
||||
else {
|
||||
return this.next(plugin, result)
|
||||
}
|
||||
}
|
||||
|
||||
next(plugin, result) {
|
||||
const pluginName = (result && result.name) || plugin.name || `plugin${this.id}`
|
||||
errorHandle(!has(this, pluginName), `Cannot add a plugin that already has the same name: ${pluginName}`)
|
||||
def(this, pluginName, {
|
||||
value: result,
|
||||
})
|
||||
return this
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import type { PluginFactory, PluginHost, PluginRegistration } from './types'
|
||||
import { isClosing } from '../lifecycle/instance'
|
||||
import { errorHandle } from '../utils/error'
|
||||
import installBuiltins from './builtins'
|
||||
import registerPlugin from './registration'
|
||||
|
||||
export default class Plugins<Host extends PluginHost<Host>> {
|
||||
declare art: Host
|
||||
declare id: number
|
||||
|
||||
constructor(art: Host) {
|
||||
this.art = art
|
||||
this.id = 0
|
||||
const { option } = art
|
||||
installBuiltins(this, option)
|
||||
for (let index = 0; index < option.plugins.length; index++) {
|
||||
if (isClosing(art))
|
||||
return
|
||||
const registration = this.add(option.plugins[index]!)
|
||||
if (registration instanceof Promise) {
|
||||
// Constructor registrations have no caller-owned Promise to observe.
|
||||
registration.catch(error => console.warn('Failed to initialize ArtPlayer plugin:', error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
add<Result>(plugin: PluginFactory<Host, Result>): PluginRegistration<Result, this>
|
||||
add(plugin: PluginFactory<Host>): this | Promise<this> {
|
||||
errorHandle(!isClosing(this.art), 'Cannot add a plugin after ArtPlayer is destroyed')
|
||||
this.id += 1
|
||||
const result = plugin.call(this.art, this.art)
|
||||
if (result instanceof Promise)
|
||||
return result.then(res => this.next(plugin, res))
|
||||
return this.next(plugin, result)
|
||||
}
|
||||
|
||||
next(plugin: PluginFactory<Host>, result: unknown): this {
|
||||
return registerPlugin(this, plugin, result)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import { isClosing } from '../lifecycle/instance'
|
||||
import { errorHandle } from '../utils/error'
|
||||
import { def, has } from '../utils/property'
|
||||
|
||||
export default function registerPlugin<Registry extends { art: object, id: number }>(registry: Registry, plugin: { name: string }, result: unknown): Registry {
|
||||
if (isClosing(registry.art))
|
||||
return registry
|
||||
// Keep the historical duck-typed name lookup and native property-key coercion.
|
||||
const name = (result && (result as { name?: unknown }).name) || plugin.name || `plugin${registry.id}`
|
||||
if (isClosing(registry.art))
|
||||
return registry
|
||||
let key = name as PropertyKey
|
||||
const duplicate = has(registry, key)
|
||||
if (isClosing(registry.art))
|
||||
return registry
|
||||
const message = `Cannot add a plugin that already has the same name: ${name}`
|
||||
if (isClosing(registry.art))
|
||||
return registry
|
||||
errorHandle(!duplicate, message)
|
||||
// Object keys can execute user code during native coercion. Keep that third
|
||||
// coercion in its historical position, then check closure before defining.
|
||||
if ((typeof name === 'object' && name !== null) || typeof name === 'function')
|
||||
key = Reflect.ownKeys({ [key]: undefined })[0]!
|
||||
if (!isClosing(registry.art))
|
||||
def(registry, key, { value: result })
|
||||
return registry
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import type { PluginFactory } from '../../types/plugin'
|
||||
import type { ResolvedOption } from '../option/types'
|
||||
|
||||
export type { PluginFactory } from '../../types/plugin'
|
||||
|
||||
export type PluginRegistration<Result, Registry>
|
||||
= unknown extends Result ? Registry | Promise<Registry>
|
||||
: Result extends Promise<unknown> ? Promise<Registry> : Registry
|
||||
|
||||
export interface PluginHost<Host> {
|
||||
option: Pick<ResolvedOption, 'miniProgressBar' | 'isLive' | 'lock' | 'autoPlayback' | 'autoOrientation' | 'fastForward'> & {
|
||||
plugins: PluginFactory<Host>[]
|
||||
}
|
||||
}
|
||||
|
||||
export interface BuiltinRegistry<Host extends PluginHost<Host>> {
|
||||
art: Host
|
||||
add: (plugin: PluginFactory<Host>) => unknown
|
||||
}
|
||||
@@ -55,3 +55,30 @@ declaration. Optional capability checks belong to their consumers. Full construc
|
||||
type integration is tracked by CORE-20; proxy package migration validates each real
|
||||
adapter separately. Source type fixtures and real canvas integration live in
|
||||
test/types/media-hosts.ts and test/browser/media-hosts.spec.js.
|
||||
|
||||
## Plugin and event augmentation
|
||||
|
||||
Use the type-only `artplayer/types` entry to augment the shared Plugins and Events
|
||||
interfaces. This reaches the same definition through Node10, NodeNext CJS/ESM and
|
||||
Bundler. Directly augmenting the root CJS namespace type alias is not equivalent.
|
||||
|
||||
```ts
|
||||
import Artplayer from 'artplayer'
|
||||
|
||||
declare module 'artplayer/types' {
|
||||
interface Plugins {
|
||||
customPlugin?: { update: (value: number) => void }
|
||||
}
|
||||
}
|
||||
|
||||
const art = new Artplayer({ container: '#player' })
|
||||
art.plugins.customPlugin?.update(1)
|
||||
```
|
||||
|
||||
Types do not register a plugin or prove that it is installed; retain a presence
|
||||
guard unless the application owns and verifies installation. PluginFactory describes
|
||||
the existing single art argument and this receiver. Public add keeps its historical
|
||||
return signature; internal manager types model actual returns separately. The new
|
||||
subpath has no runtime export; use it only for types/augmentation. plugins-public.ts
|
||||
tests the same declarations in all installed consumer modes, and package runtime
|
||||
checks reject both require and import of artplayer/types.
|
||||
@@ -14,6 +14,8 @@ declare namespace Artplayer {
|
||||
type Option = Definition.Option
|
||||
type OptionInput = Definition.OptionInput
|
||||
type Player = Definition.Player
|
||||
type PluginFactory<Host = Artplayer, Result = unknown> = Definition.PluginFactory<Host, Result>
|
||||
type Plugins = Definition.Plugins
|
||||
type Setting = Definition.Setting
|
||||
type SettingOption = Definition.SettingOption
|
||||
type Subtitle = Definition.Subtitle
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
export { default } from './artplayer.cjs'
|
||||
export type { Config, Emitter, Events, I18n, Icons, Option, OptionInput, Player, Setting, SettingOption, Subtitle, SubtitleUpdateEvents, Template, Utils } from './artplayer.js'
|
||||
export type { Config, Emitter, Events, I18n, Icons, Option, OptionInput, Player, PluginFactory, Plugins, Setting, SettingOption, Subtitle, SubtitleUpdateEvents, Template, Utils } from './artplayer.js'
|
||||
+4
-6
@@ -6,6 +6,7 @@ import type { I18n } from './i18n'
|
||||
import type { Icons } from './icons'
|
||||
import type { Option, OptionInput } from './option'
|
||||
import type { Player } from './player'
|
||||
import type { PluginFactory, Plugins } from './plugin'
|
||||
import type { Setting, SettingOption } from './setting'
|
||||
import type { Subtitle } from './subtitle'
|
||||
import type { Template } from './template'
|
||||
@@ -20,6 +21,8 @@ export type {
|
||||
Option,
|
||||
OptionInput,
|
||||
Player,
|
||||
PluginFactory,
|
||||
Plugins,
|
||||
Setting,
|
||||
SettingOption,
|
||||
Subtitle,
|
||||
@@ -205,10 +208,5 @@ export default class Artplayer extends Player {
|
||||
remove: (name: string) => Artplayer['setting']
|
||||
} & Component
|
||||
|
||||
readonly plugins: {
|
||||
/** Legacy signature: synchronous factories return this registry directly; Promise factories return a Promise of it. */
|
||||
add: (
|
||||
plugin: (this: Artplayer, art: Artplayer) => unknown | Promise<unknown>,
|
||||
) => Promise<Artplayer['plugins']>
|
||||
} & Record<string, unknown>
|
||||
readonly plugins: Plugins
|
||||
}
|
||||
Vendored
+2
-1
@@ -3,6 +3,7 @@ import type { ComponentInput, ComponentOption } from './component'
|
||||
import type { CssVar } from './cssVar'
|
||||
import type { I18n } from './i18n'
|
||||
import type { Icons } from './icons'
|
||||
import type { PluginFactory } from './plugin'
|
||||
import type { Quality } from './quality'
|
||||
import type { Setting } from './setting'
|
||||
import type { Subtitle } from './subtitle'
|
||||
@@ -240,7 +241,7 @@ export interface Option {
|
||||
/**
|
||||
* Custom plugin list
|
||||
*/
|
||||
plugins?: ((this: Artplayer, art: Artplayer) => unknown | Promise<unknown>)[]
|
||||
plugins?: PluginFactory[]
|
||||
|
||||
/**
|
||||
* Custom layer list
|
||||
|
||||
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
import type Artplayer from './artplayer'
|
||||
|
||||
export type PluginFactory<Host = Artplayer, Result = unknown> = (this: Host, art: Host) => Result
|
||||
|
||||
/** Augment this interface with installed plugin results; augmentation does not register a plugin. */
|
||||
export interface Plugins {
|
||||
/** Legacy signature: synchronous factories return this registry; Promise factories return a Promise of it. */
|
||||
add: (plugin: PluginFactory) => Promise<Plugins>
|
||||
[name: string]: unknown
|
||||
}
|
||||
Reference in new issue
Block a user