refactor(core): CORE-02 type emitter maps and fix nested once dispatch

This commit is contained in:
Harvey Zhao committed 2026-09-11 00:03:53 +08:00
1 parent d3c695024a
commit 362c616998
21 files changed
+943 -72

No files matched your search

+1 -1
View File
@@ -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 a=(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 o=t(r);if("boolean"===o)return"boolean";if("string"===o)return"string";if("number"===o)return"number";if("symbol"===o)return"symbol";if("function"===o)return"GeneratorFunction"===a(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(a(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(o=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 o.slice(8,-1).toLowerCase().replace(/\s/g,"")};function a(t){return t.constructor?t.constructor.name:null}function o(t,e){var a=2<arguments.length&&void 0!==arguments[2]?arguments[2]:["option"];return n(t,e,a),i(t,e,a),function(t,e,a){var s=r(e),l=r(t);if("object"===s){if("object"!==l)throw new Error("[Type Error]: '".concat(a.join("."),"' require 'object' type, but got '").concat(l,"'"));Object.keys(e).forEach(function(r){var s=t[r],l=e[r],c=a.slice();c.push(r),n(s,l,c),i(s,l,c),o(s,l,c)})}if("array"===s){if("array"!==l)throw new Error("[Type Error]: '".concat(a.join("."),"' require 'array' type, but got '").concat(l,"'"));t.forEach(function(r,s){var l=t[s],c=e[s]||e[0],d=a.slice();d.push(s),n(l,c,d),i(l,c,d),o(l,c,d)})}}(t,e,a),t}function n(t,e,a){if("string"===r(e)){var o=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 o===t}):e.toLowerCase().trim()===o))throw new Error("[Type Error]: '".concat(a.join("."),"' require '").concat(e,"' type, but got '").concat(o,"'"))}}function i(t,e,a){if("function"===r(e)){var o=e(t,r(t),a);if(!0!==o){var n=r(o);throw"string"===n?new Error(o):"error"===n?o:new Error("[Validator Error]: The scheme for '".concat(a.join("."),"' validator require return true, but got '").concat(o,"'"))}}}return o.kindOf=r,o}()),r.exports);const o=t(a),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 a=(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 o=t(r);if("boolean"===o)return"boolean";if("string"===o)return"string";if("number"===o)return"number";if("symbol"===o)return"symbol";if("function"===o)return"GeneratorFunction"===a(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(a(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(o=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 o.slice(8,-1).toLowerCase().replace(/\s/g,"")};function a(t){return t.constructor?t.constructor.name:null}function o(t,e){var a=2<arguments.length&&void 0!==arguments[2]?arguments[2]:["option"];return n(t,e,a),i(t,e,a),function(t,e,a){var s=r(e),l=r(t);if("object"===s){if("object"!==l)throw new Error("[Type Error]: '".concat(a.join("."),"' require 'object' type, but got '").concat(l,"'"));Object.keys(e).forEach(function(r){var s=t[r],l=e[r],c=a.slice();c.push(r),n(s,l,c),i(s,l,c),o(s,l,c)})}if("array"===s){if("array"!==l)throw new Error("[Type Error]: '".concat(a.join("."),"' require 'array' type, but got '").concat(l,"'"));t.forEach(function(r,s){var l=t[s],c=e[s]||e[0],d=a.slice();d.push(s),n(l,c,d),i(l,c,d),o(l,c,d)})}}(t,e,a),t}function n(t,e,a){if("string"===r(e)){var o=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 o===t}):e.toLowerCase().trim()===o))throw new Error("[Type Error]: '".concat(a.join("."),"' require '").concat(e,"' type, but got '").concat(o,"'"))}}function i(t,e,a){if("function"===r(e)){var o=e(t,r(t),a);if(!0!==o){var n=r(o);throw"string"===n?new Error(o):"error"===n?o:new Error("[Validator Error]: The scheme for '".concat(a.join("."),"' validator require return true, but got '").concat(o,"'"))}}}return o.kindOf=r,o}()),r.exports);const o=t(a),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
View File
@@ -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
+21 -8
View File
@@ -4780,36 +4780,49 @@ class Template {
}
}
}
const owns = (object, key) => Object.prototype.hasOwnProperty.call(object, key);
class Emitter {
on(name, fn, ctx) {
const e = this.e || (this.e = {});
(e[name] || (e[name] = [])).push({ fn, ctx });
let listeners = owns(e, name) ? e[name] : void 0;
if (!listeners) {
listeners = [];
Object.defineProperty(e, name, { value: listeners, enumerable: true, configurable: true, writable: true });
}
listeners.push({ fn, ctx });
return this;
}
once(name, fn, ctx) {
const self = this;
const callback = fn;
let fired = false;
function listener(...args) {
if (fired)
return;
fired = true;
self.off(name, listener);
fn.apply(ctx, args);
callback.apply(ctx, args);
}
listener._ = fn;
return this.on(name, listener, ctx);
}
emit(name, ...data) {
const evtArr = ((this.e || (this.e = {}))[name] || []).slice();
for (let i = 0; i < evtArr.length; i += 1) {
evtArr[i].fn.apply(evtArr[i].ctx, data);
const e = this.e || (this.e = {});
const snapshot = (owns(e, name) ? e[name] || [] : []).slice();
for (const event of snapshot) {
event.fn.apply(event.ctx, data);
}
return this;
}
off(name, callback) {
const e = this.e || (this.e = {});
const evts = e[name];
const evts = owns(e, name) ? e[name] : void 0;
const liveEvents = [];
if (evts && callback) {
for (let i = 0, len = evts.length; i < len; i += 1) {
if (evts[i].fn !== callback && evts[i].fn._ !== callback)
liveEvents.push(evts[i]);
const event = evts[i];
if (event.fn !== callback && event.fn._ !== callback)
liveEvents.push(event);
}
}
if (liveEvents.length) {
+31 -2
View File
@@ -18,9 +18,38 @@ boundaries rather than describing the entire core as TypeScript.
These modules do not import the player, UI components or each other except for the
barrel. Existing DOM and browser capability utilities remain JS and are re-exported
unchanged. Emitter and Component are separate migration tasks. Imports from the
unchanged. Emitter is now typed as described below; Component remains a later task. Imports from the
barrel must not silently add runtime fields to `Artplayer.utils`.
## Typed Emitter
`src/utils/emitter.ts` keeps the original on/once/emit/off class and a lazy ordinary
object registry. `declare e` emits no instance field; a fresh emitter still has no
own keys. There are no additional prototype methods or mandatory constructor options.
The generic event map associates event names with payload tuples, including readonly
tuples, symbols and optional arguments. An open Record default preserves arbitrary
JS event channels; internal typed consumers can use a closed map or intersect their
known events with an open map. Receiver inference is checked on registration and
erased inside each stored registration, where the original callback and ctx remain paired.
Current JS player consumers remain incremental; public declaration expansion is CORE-07.
Dispatch takes a shallow registration-array snapshot. Normal listeners removed during
dispatch still run if already captured, additions wait for a later dispatch, and a
throw stops that dispatch and propagates unchanged. Off accepts either a once wrapper
or its original callback; duplicate registrations of a callback are removed together.
The once wrapper unsubscribes before invoking user code and now records consumption,
so a nested dispatch cannot execute a captured copy twice. This fixes a demonstrated
old defect without changing ordinary snapshot behavior. Event names such as __proto__
and toString use own properties rather than inherited Object.prototype values.
Shared contracts in test/contracts/emitter.js run against published, workspace and
installed versions. Candidate corrections have separate published-defect observations
in test/public-behavior.test.js and test/browser/emitter.spec.js. The source type fixture
checks event name/payload correlation, receiver types, custom channels and chain typing.
Emitter owns registrations only; instance teardown must remove the relevant callbacks,
not clear unrelated subscribers before destroy dispatch. Resource scopes follow in CORE-03.
## Observable utility behavior
- `def` is the native Object.defineProperty function. Property keys include symbols;
@@ -77,5 +106,5 @@ core files in docs/compiled when committing a shippable core change.
For new utility behavior, extend the same old/new contract tests. Clearly separate
intentional defect corrections from preserved behavior. For timers or Blob URLs,
also identify the owner and verify cleanup in the consuming module. Remaining
constructor, playback, UI, Emitter, Component and capability migrations are recorded
constructor, playback, UI, Component and capability migrations are recorded
in refactor/tasks.json and should extend this map as they land.
+1 -1
View File
@@ -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 a=(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 o=t(r);if("boolean"===o)return"boolean";if("string"===o)return"string";if("number"===o)return"number";if("symbol"===o)return"symbol";if("function"===o)return"GeneratorFunction"===a(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(a(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(o=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 o.slice(8,-1).toLowerCase().replace(/\s/g,"")};function a(t){return t.constructor?t.constructor.name:null}function o(t,e){var a=2<arguments.length&&void 0!==arguments[2]?arguments[2]:["option"];return n(t,e,a),i(t,e,a),function(t,e,a){var s=r(e),l=r(t);if("object"===s){if("object"!==l)throw new Error("[Type Error]: '".concat(a.join("."),"' require 'object' type, but got '").concat(l,"'"));Object.keys(e).forEach(function(r){var s=t[r],l=e[r],c=a.slice();c.push(r),n(s,l,c),i(s,l,c),o(s,l,c)})}if("array"===s){if("array"!==l)throw new Error("[Type Error]: '".concat(a.join("."),"' require 'array' type, but got '").concat(l,"'"));t.forEach(function(r,s){var l=t[s],c=e[s]||e[0],d=a.slice();d.push(s),n(l,c,d),i(l,c,d),o(l,c,d)})}}(t,e,a),t}function n(t,e,a){if("string"===r(e)){var o=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 o===t}):e.toLowerCase().trim()===o))throw new Error("[Type Error]: '".concat(a.join("."),"' require '").concat(e,"' type, but got '").concat(o,"'"))}}function i(t,e,a){if("function"===r(e)){var o=e(t,r(t),a);if(!0!==o){var n=r(o);throw"string"===n?new Error(o):"error"===n?o:new Error("[Validator Error]: The scheme for '".concat(a.join("."),"' validator require return true, but got '").concat(o,"'"))}}}return o.kindOf=r,o}()),r.exports);const o=t(a),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 a=(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 o=t(r);if("boolean"===o)return"boolean";if("string"===o)return"string";if("number"===o)return"number";if("symbol"===o)return"symbol";if("function"===o)return"GeneratorFunction"===a(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(a(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(o=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 o.slice(8,-1).toLowerCase().replace(/\s/g,"")};function a(t){return t.constructor?t.constructor.name:null}function o(t,e){var a=2<arguments.length&&void 0!==arguments[2]?arguments[2]:["option"];return n(t,e,a),i(t,e,a),function(t,e,a){var s=r(e),l=r(t);if("object"===s){if("object"!==l)throw new Error("[Type Error]: '".concat(a.join("."),"' require 'object' type, but got '").concat(l,"'"));Object.keys(e).forEach(function(r){var s=t[r],l=e[r],c=a.slice();c.push(r),n(s,l,c),i(s,l,c),o(s,l,c)})}if("array"===s){if("array"!==l)throw new Error("[Type Error]: '".concat(a.join("."),"' require 'array' type, but got '").concat(l,"'"));t.forEach(function(r,s){var l=t[s],c=e[s]||e[0],d=a.slice();d.push(s),n(l,c,d),i(l,c,d),o(l,c,d)})}}(t,e,a),t}function n(t,e,a){if("string"===r(e)){var o=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 o===t}):e.toLowerCase().trim()===o))throw new Error("[Type Error]: '".concat(a.join("."),"' require '").concat(e,"' type, but got '").concat(o,"'"))}}function i(t,e,a){if("function"===r(e)){var o=e(t,r(t),a);if(!0!==o){var n=r(o);throw"string"===n?new Error(o):"error"===n?o:new Error("[Validator Error]: The scheme for '".concat(a.join("."),"' validator require return true, but got '").concat(o,"'"))}}}return o.kindOf=r,o}()),r.exports);const o=t(a),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
View File
@@ -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
+21 -8
View File
@@ -4780,36 +4780,49 @@ class Template {
}
}
}
const owns = (object, key) => Object.prototype.hasOwnProperty.call(object, key);
class Emitter {
on(name, fn, ctx) {
const e = this.e || (this.e = {});
(e[name] || (e[name] = [])).push({ fn, ctx });
let listeners = owns(e, name) ? e[name] : void 0;
if (!listeners) {
listeners = [];
Object.defineProperty(e, name, { value: listeners, enumerable: true, configurable: true, writable: true });
}
listeners.push({ fn, ctx });
return this;
}
once(name, fn, ctx) {
const self = this;
const callback = fn;
let fired = false;
function listener(...args) {
if (fired)
return;
fired = true;
self.off(name, listener);
fn.apply(ctx, args);
callback.apply(ctx, args);
}
listener._ = fn;
return this.on(name, listener, ctx);
}
emit(name, ...data) {
const evtArr = ((this.e || (this.e = {}))[name] || []).slice();
for (let i = 0; i < evtArr.length; i += 1) {
evtArr[i].fn.apply(evtArr[i].ctx, data);
const e = this.e || (this.e = {});
const snapshot = (owns(e, name) ? e[name] || [] : []).slice();
for (const event of snapshot) {
event.fn.apply(event.ctx, data);
}
return this;
}
off(name, callback) {
const e = this.e || (this.e = {});
const evts = e[name];
const evts = owns(e, name) ? e[name] : void 0;
const liveEvents = [];
if (evts && callback) {
for (let i = 0, len = evts.length; i < len; i += 1) {
if (evts[i].fn !== callback && evts[i].fn._ !== callback)
liveEvents.push(evts[i]);
const event = evts[i];
if (event.fn !== callback && event.fn._ !== callback)
liveEvents.push(event);
}
}
if (liveEvents.length) {
-44
View File
@@ -1,44 +0,0 @@
export default class Emitter {
on(name, fn, ctx) {
const e = this.e || (this.e = {});
(e[name] || (e[name] = [])).push({ fn, ctx })
return this
}
once(name, fn, ctx) {
const self = this
function listener(...args) {
self.off(name, listener)
fn.apply(ctx, args)
}
listener._ = fn
return this.on(name, listener, ctx)
}
emit(name, ...data) {
const evtArr = ((this.e || (this.e = {}))[name] || []).slice()
for (let i = 0; i < evtArr.length; i += 1) {
evtArr[i].fn.apply(evtArr[i].ctx, data)
}
return this
}
off(name, callback) {
const e = this.e || (this.e = {})
const evts = e[name]
const liveEvents = []
if (evts && callback) {
for (let i = 0, len = evts.length; i < len; i += 1) {
if (evts[i].fn !== callback && evts[i].fn._ !== callback)
liveEvents.push(evts[i])
}
}
if (liveEvents.length) {
e[name] = liveEvents
}
else {
delete e[name]
}
return this
}
}
+69
View File
@@ -0,0 +1,69 @@
type EventMap<Events> = { [Name in keyof Events]: readonly unknown[] }
type Listener<Args extends unknown[]> = ((...args: Args) => unknown) & { _?: (...args: Args) => unknown }
interface Registration<Args extends unknown[]> {
fn: Listener<Args>
ctx: unknown
}
type Registry<Events extends EventMap<Events>> = { [Name in keyof Events]?: Registration<[...Events[Name]]>[] }
const owns = (object: object, key: PropertyKey) => Object.prototype.hasOwnProperty.call(object, key)
export default class Emitter<Events extends EventMap<Events> = Record<PropertyKey, unknown[]>> {
declare e?: Registry<Events>
on<Name extends keyof Events, Context>(name: Name, fn: (this: Context, ...args: [...Events[Name]]) => unknown, ctx?: Context): this {
const e: Registry<Events> = this.e || (this.e = {})
let listeners = owns(e, name) ? e[name] : undefined
if (!listeners) {
listeners = []
Object.defineProperty(e, name, { value: listeners, enumerable: true, configurable: true, writable: true })
}
listeners.push({ fn, ctx })
return this
}
once<Name extends keyof Events, Context>(name: Name, fn: (this: Context, ...args: [...Events[Name]]) => unknown, ctx?: Context): this {
// eslint-disable-next-line ts/no-this-alias -- The once wrapper unsubscribes its owner, independently of callback ctx.
const self = this
const callback: Listener<[...Events[Name]]> = fn
let fired = false
function listener(...args: [...Events[Name]]) {
if (fired)
return
fired = true
self.off(name, listener)
callback.apply(ctx, args)
}
listener._ = fn
return this.on(name, listener, ctx)
}
emit<Name extends keyof Events>(name: Name, ...data: [...Events[Name]]): this {
const e: Registry<Events> = this.e || (this.e = {})
const snapshot = (owns(e, name) ? e[name] || [] : []).slice()
for (const event of snapshot) {
event.fn.apply(event.ctx, data)
}
return this
}
off<Name extends keyof Events>(name: Name, callback?: Listener<[...Events[Name]]>): this {
const e: Registry<Events> = this.e || (this.e = {})
const evts = owns(e, name) ? e[name] : undefined
const liveEvents: Registration<[...Events[Name]]>[] = []
if (evts && callback) {
for (let i = 0, len = evts.length; i < len; i += 1) {
// Registrations are inserted densely; retain the captured-length traversal.
const event = evts[i]!
if (event.fn !== callback && event.fn._ !== callback)
liveEvents.push(event)
}
}
if (liveEvents.length) {
e[name] = liveEvents
}
else {
delete e[name]
}
return this
}
}
+548
View File
@@ -0,0 +1,548 @@
{
"task": "CORE-02",
"capturedAt": "2026-09-10T16:02:48.874Z",
"source": "26a93d3ff35b53e71a5f3bb22c252a854559d8151ede50a66a28d9eefae6c008",
"packages": [
{
"name": "artplayer",
"version": "5.4.1",
"archive": "artplayer.tgz",
"sha256": "1850bab2601b6b5c0fac6a4c3010edf4a5e700f00a6c26a29e8d35730f56dba3",
"files": {
"package/ARCHITECTURE.md": "bd26a46f62bac3aac033a9ea8b881d65aec162e8b697ddb37b3837748c4355b4",
"package/README.md": "1e185e65f67fc2081b4182bbc6c4558ea05b6e3fa3acc5dd0c3ac7df1d542b09",
"package/dist/artplayer.js": "fb9c8dca1d789631dd87cb0cf43f2e66c8419a751cdd3a188c2ee1a6481e04c1",
"package/dist/artplayer.legacy.js": "a0c0adb9c48d7a96ddba43eab7a7f6d91e920fde41ee8010e294ebe6efcc0062",
"package/dist/artplayer.mjs": "d1e206489b72001dfb570c9c8b358085eb18317c10e2fc8cc8c83148319ff7ff",
"package/dist/i18n/ar.js": "61c43469ee95a00dc624583f418653e3dcbf48b24ae6a4c203ad986234852365",
"package/dist/i18n/ar.mjs": "68922fdc9f80d3321ea0654c8ff8f5875b6715103d2b14ffcf17f93738b39cf9",
"package/dist/i18n/cs.js": "ad7bbf8853204a6955ef84bfbd932cab3f141a7e73a8145f28ba7a5b2b83b7c0",
"package/dist/i18n/cs.mjs": "29a489be767fda9d46b59c9adbaad323f17a5e67daf7f7aa78b7ce8fb5b4d63c",
"package/dist/i18n/es.js": "aaa95cc9645b734c58fba06fdbcdda962c4cb3a0e7eb6206f06d6168208cd86b",
"package/dist/i18n/es.mjs": "331d2ef74da2eec8f3304fec0b5340c795d9c1eec24e08167c9a7b66bf30973b",
"package/dist/i18n/fa.js": "c998467261cbdfd2c3fb16c0ae4b2c48c409f42f41aea35ed94766f1e12819d5",
"package/dist/i18n/fa.mjs": "b4c98894b46975cebf5ea9088bcf0b5bdfd408bc3c82f4e2e9128133c7de2d4d",
"package/dist/i18n/fr.js": "6b06e16b1fb01c8695fb5c10b32a00421399180de5dc5d845ce17010f2fd3e66",
"package/dist/i18n/fr.mjs": "abe8e3548fa7304f302e2c74818a6176edee8c3b65e33cb6f62e96d130749ee5",
"package/dist/i18n/id.js": "a5832c4bfc03c7f16418bf4b324d9773895541dc823ece9114741794737aad74",
"package/dist/i18n/id.mjs": "a40a433be6ca1ac1ee1810fe805ee60784d349e59b9ad82ea80201d660db4e68",
"package/dist/i18n/pl.js": "2491487062bdfc91d60f17c6e9a83ee196c991216d15f525fe3536b98873da2c",
"package/dist/i18n/pl.mjs": "ad8ea2c03785edbfe1f35761bec21b8a04213f9fa88a794d850bb3973564930f",
"package/dist/i18n/ru.js": "2d3a9ee6533cb6fa961f0a24a25ce63cc76992fca17e1769b6fa75104f8a1529",
"package/dist/i18n/ru.mjs": "a89b8c36cfd7c181c2b31aa823deda3d7c37b56b2b81746338c52ea1c1d93352",
"package/dist/i18n/tr.js": "438b06a4c3f479a2901b0085eaa7bdba8eaef87bdb07ff3faa559c85403fe433",
"package/dist/i18n/tr.mjs": "cc96f9cbb9c1587d5cd8f25b0b9800678ad76e93de089ae42c38dee16e6fe8fa",
"package/dist/i18n/vi.js": "1ffbd62843a902ea2967eab46432d3fc548f5633e53eed104314b523cacc46a8",
"package/dist/i18n/vi.mjs": "7872ded84622bcda20e8c1d70c597c2ba071b50701900efa47cc4683ee17f1a2",
"package/dist/i18n/zh-tw.js": "2d43577f98456488196921e1ec721695a95e1b8c827077286b02ce3fb987e8ff",
"package/dist/i18n/zh-tw.mjs": "7ec638b4babe59d3ab1d3e64abdd74a96fefb260a50e2cd7240f8d50a1340925",
"package/package.json": "b343df9955df9ac0ea71ea775bd0743c6b26c06d3bb7699128f7eac484fa769f",
"package/types/README.md": "d38bb63f9e96f995273f9da6833a8b936a74718ef7b710dbd316530d41ccae07",
"package/types/artplayer.d.cts": "be67cbb6c352944741bca88f969ad1bafa9898049595930e2dc6693d5e7262f5",
"package/types/artplayer.d.mts": "87d1f0e2a7bf7b7bdf700875cb2c77dea8be34ba3ac943e5fd35e8daa99bf241",
"package/types/artplayer.d.ts": "98d3e7b65f9f81fba155da08fd47e4fb25f4c69279e3afd993c4a55070f8a850",
"package/types/component.d.ts": "facfa29d9092fe2c63a7d8357ce7d0faa5e32811d2fedeef6dc8b28ad5d04891",
"package/types/config.d.ts": "c4fd8681bf32b10c743e3e561c532520c8f32e43fd765524850b15e55cb91c72",
"package/types/cssVar.d.ts": "e027d82fb4f01c9ce7559cf679b2d5ee1962d3f7e5b4dd64ca21f472b933efb6",
"package/types/events.d.ts": "98c74aebb82455accc0b3523af5a1145bc9119da58c884200adc36e70a164b02",
"package/types/i18n.d.ts": "3e14759caf71f97f01650839248c8737c42d2c2979dabc43ad92b724da648708",
"package/types/icons.d.ts": "0d8e8e52e52130dd4a29bab551dd7a2a954797e42e92a6e068c85d583e23e6a4",
"package/types/language.d.cts": "1c9e0c47fae3c2d68c3e144d95a55071318a03bb31554dd049109efd3d0f95a4",
"package/types/language.d.mts": "c391e863012c77769e661afbf8fa949e9373aa88d17f58cbba7f5696edb8077f",
"package/types/legacy/language.d.ts": "c452ffd764ff9b29b819b3475c42395d2ea7a33560d8c186ef5df3844b9524c3",
"package/types/option.d.ts": "d4de53930c2fa9d59c77c4324d63f24b057bce6c4d0273c34a0ab06094dcea2c",
"package/types/player.d.ts": "986382bb6b4e82746fd2405092e69d0ef413988887a557a0fd4db85d64b78d54",
"package/types/quality.d.ts": "7ed6ed78cea52991b2f6ddd2bd3b7bd8c5146fdfff7486fe8b814c3e632f1567",
"package/types/setting.d.ts": "d12a75b656fff70cbb30be4bffec46d9c4273636e8722bce971a4d2b188712a1",
"package/types/subtitle.d.ts": "d25b470e47d6a9bd696d9c1ad8adb58e56a208f05695186d513bc8c43c2e8acf",
"package/types/template.d.ts": "68aed9e97d006d6be4fabb8504ca84dafab770b0925f4d6e7319e67c82f21b0d",
"package/types/utils.d.ts": "d3fb67b9187e1c81c6b3850694cf2627e927225ace160ae58c11631e9f673a98"
}
},
{
"name": "artplayer-plugin-chapter",
"version": "1.1.0",
"archive": "artplayer-plugin-chapter.tgz",
"sha256": "df90b76c987209cecaed5a3b5a480a85e0c300e463d7dc5cc508c9aad002bb4c",
"files": {
"package/ARCHITECTURE.md": "20743bad87a174b0450e0d876b6aa6b2a9f47df296d479511ce7cc9298fdb57c",
"package/README.md": "b95400ff3d525621a15268bb56a2d353aacaaadefde7e735d7abd91a34edd96f",
"package/dist/artplayer-plugin-chapter.js": "6ac3dfe28f46084ac7caedd571b1a97dcee3cf9d708112f1b8bbd6566e1dc5c5",
"package/dist/artplayer-plugin-chapter.legacy.js": "6d9bff885412169e701670961aa00c2e46c4b42c9b9647ff4e6d198777d2a359",
"package/dist/artplayer-plugin-chapter.mjs": "26415cecab2c0198c566cef0232e20123413782d5bad7534a32939b3298617af",
"package/package.json": "24eec6907b3218439189adab6af3f932c1497c47c2d41209311c01042b07fd4f",
"package/types/artplayer-plugin-chapter.d.cts": "4f07514b37453cd6cea8e5aa28fa018ff31738e0d423c11a3b5eccd50ed30bcc",
"package/types/artplayer-plugin-chapter.d.mts": "610179754db36276e161a07bccf4eaba8b4480f053e716a2bcc5a1574871a171",
"package/types/artplayer-plugin-chapter.d.ts": "581aa2862e709601c87a23585f54a969ebd350be56a7469a31ff53f1311b578d"
}
}
],
"runtimeChecks": 27,
"knownTypeBlockers": 0,
"ciChecks": 85,
"artifactEmitterChecks": {
"umd": 29,
"legacy": 29,
"esm": 29
},
"browser": {
"startTime": "2026-09-10T15:59:51.244Z",
"duration": 31373.444,
"expected": 75,
"skipped": 0,
"unexpected": 0,
"flaky": 0
},
"tests": [
{
"title": "published-only observations: blank title, NaN and once-only metadata are historical defects",
"project": "chromium",
"status": "passed",
"browser": "153.0.8010.12"
},
{
"title": "candidate clears titles on blank chapters, zero hover and replacement",
"project": "chromium",
"status": "passed",
"browser": "153.0.8010.12"
},
{
"title": "candidate rejects NaN and can recover after an invalid update",
"project": "chromium",
"status": "passed",
"browser": "153.0.8010.12"
},
{
"title": "candidate releases only its listeners and DOM across multiple instances and early destruction",
"project": "chromium",
"status": "passed",
"browser": "153.0.8010.12"
},
{
"title": "candidate ignores pending metadata initialization after immediate destroy",
"project": "chromium",
"status": "passed",
"browser": "153.0.8010.12"
},
{
"title": "candidate deduplicates stylesheet injection while the document is loading",
"project": "chromium",
"status": "passed",
"browser": "153.0.8010.12"
},
{
"title": "published-only observations: blank title, NaN and once-only metadata are historical defects",
"project": "firefox",
"status": "passed",
"browser": "155.0"
},
{
"title": "candidate clears titles on blank chapters, zero hover and replacement",
"project": "firefox",
"status": "passed",
"browser": "155.0"
},
{
"title": "candidate rejects NaN and can recover after an invalid update",
"project": "firefox",
"status": "passed",
"browser": "155.0"
},
{
"title": "candidate releases only its listeners and DOM across multiple instances and early destruction",
"project": "firefox",
"status": "passed",
"browser": "155.0"
},
{
"title": "candidate ignores pending metadata initialization after immediate destroy",
"project": "firefox",
"status": "passed",
"browser": "155.0"
},
{
"title": "candidate deduplicates stylesheet injection while the document is loading",
"project": "firefox",
"status": "passed",
"browser": "155.0"
},
{
"title": "published-only observations: blank title, NaN and once-only metadata are historical defects",
"project": "webkit",
"status": "passed",
"browser": "26.6"
},
{
"title": "candidate clears titles on blank chapters, zero hover and replacement",
"project": "webkit",
"status": "passed",
"browser": "26.6"
},
{
"title": "candidate rejects NaN and can recover after an invalid update",
"project": "webkit",
"status": "passed",
"browser": "26.6"
},
{
"title": "candidate releases only its listeners and DOM across multiple instances and early destruction",
"project": "webkit",
"status": "passed",
"browser": "26.6"
},
{
"title": "candidate ignores pending metadata initialization after immediate destroy",
"project": "webkit",
"status": "passed",
"browser": "26.6"
},
{
"title": "candidate deduplicates stylesheet injection while the document is loading",
"project": "webkit",
"status": "passed",
"browser": "26.6"
},
{
"title": "factory, registration, input normalization and safe title text",
"project": "chromium",
"status": "passed",
"browser": "153.0.8010.12"
},
{
"title": "progress bars, real hover, title edges and boundary seek",
"project": "chromium",
"status": "passed",
"browser": "153.0.8010.12"
},
{
"title": "sync update, Infinity, object identity, empty lists and invalid data",
"project": "chromium",
"status": "passed",
"browser": "153.0.8010.12"
},
{
"title": "explicit source update and core-owned destruction",
"project": "chromium",
"status": "passed",
"browser": "153.0.8010.12"
},
{
"title": "factory, registration, input normalization and safe title text",
"project": "firefox",
"status": "passed",
"browser": "155.0"
},
{
"title": "progress bars, real hover, title edges and boundary seek",
"project": "firefox",
"status": "passed",
"browser": "155.0"
},
{
"title": "sync update, Infinity, object identity, empty lists and invalid data",
"project": "firefox",
"status": "passed",
"browser": "155.0"
},
{
"title": "explicit source update and core-owned destruction",
"project": "firefox",
"status": "passed",
"browser": "155.0"
},
{
"title": "factory, registration, input normalization and safe title text",
"project": "webkit",
"status": "passed",
"browser": "26.6"
},
{
"title": "progress bars, real hover, title edges and boundary seek",
"project": "webkit",
"status": "passed",
"browser": "26.6"
},
{
"title": "sync update, Infinity, object identity, empty lists and invalid data",
"project": "webkit",
"status": "passed",
"browser": "26.6"
},
{
"title": "explicit source update and core-owned destruction",
"project": "webkit",
"status": "passed",
"browser": "26.6"
},
{
"title": "factory, registration, input normalization and safe title text",
"project": "chromium",
"status": "passed",
"browser": "153.0.8010.12"
},
{
"title": "progress bars, real hover, title edges and boundary seek",
"project": "chromium",
"status": "passed",
"browser": "153.0.8010.12"
},
{
"title": "sync update, Infinity, object identity, empty lists and invalid data",
"project": "chromium",
"status": "passed",
"browser": "153.0.8010.12"
},
{
"title": "explicit source update and core-owned destruction",
"project": "chromium",
"status": "passed",
"browser": "153.0.8010.12"
},
{
"title": "factory, registration, input normalization and safe title text",
"project": "firefox",
"status": "passed",
"browser": "155.0"
},
{
"title": "progress bars, real hover, title edges and boundary seek",
"project": "firefox",
"status": "passed",
"browser": "155.0"
},
{
"title": "sync update, Infinity, object identity, empty lists and invalid data",
"project": "firefox",
"status": "passed",
"browser": "155.0"
},
{
"title": "explicit source update and core-owned destruction",
"project": "firefox",
"status": "passed",
"browser": "155.0"
},
{
"title": "factory, registration, input normalization and safe title text",
"project": "webkit",
"status": "passed",
"browser": "26.6"
},
{
"title": "progress bars, real hover, title edges and boundary seek",
"project": "webkit",
"status": "passed",
"browser": "26.6"
},
{
"title": "sync update, Infinity, object identity, empty lists and invalid data",
"project": "webkit",
"status": "passed",
"browser": "26.6"
},
{
"title": "explicit source update and core-owned destruction",
"project": "webkit",
"status": "passed",
"browser": "26.6"
},
{
"title": "published: emitter event names and once across nested dispatch",
"project": "chromium",
"status": "passed",
"browser": "153.0.8010.12"
},
{
"title": "candidate: emitter event names and once across nested dispatch",
"project": "chromium",
"status": "passed",
"browser": "153.0.8010.12"
},
{
"title": "published: emitter event names and once across nested dispatch",
"project": "firefox",
"status": "passed",
"browser": "155.0"
},
{
"title": "candidate: emitter event names and once across nested dispatch",
"project": "firefox",
"status": "passed",
"browser": "155.0"
},
{
"title": "published: emitter event names and once across nested dispatch",
"project": "webkit",
"status": "passed",
"browser": "26.6"
},
{
"title": "candidate: emitter event names and once across nested dispatch",
"project": "webkit",
"status": "passed",
"browser": "26.6"
},
{
"title": "published: real playback, pause, seek, switch and destroy",
"project": "chromium",
"status": "passed",
"browser": "153.0.8010.12"
},
{
"title": "candidate: real playback, pause, seek, switch and destroy",
"project": "chromium",
"status": "passed",
"browser": "153.0.8010.12"
},
{
"title": "controlled HTTP media failure emits a real video error",
"project": "chromium",
"status": "passed",
"browser": "153.0.8010.12"
},
{
"title": "Range, media identity and docs candidate routes",
"project": "chromium",
"status": "passed",
"browser": "153.0.8010.12"
},
{
"title": "published: real playback, pause, seek, switch and destroy",
"project": "firefox",
"status": "passed",
"browser": "155.0"
},
{
"title": "candidate: real playback, pause, seek, switch and destroy",
"project": "firefox",
"status": "passed",
"browser": "155.0"
},
{
"title": "controlled HTTP media failure emits a real video error",
"project": "firefox",
"status": "passed",
"browser": "155.0"
},
{
"title": "Range, media identity and docs candidate routes",
"project": "firefox",
"status": "passed",
"browser": "155.0"
},
{
"title": "published: real playback, pause, seek, switch and destroy",
"project": "webkit",
"status": "passed",
"browser": "26.6"
},
{
"title": "candidate: real playback, pause, seek, switch and destroy",
"project": "webkit",
"status": "passed",
"browser": "26.6"
},
{
"title": "controlled HTTP media failure emits a real video error",
"project": "webkit",
"status": "passed",
"browser": "26.6"
},
{
"title": "Range, media identity and docs candidate routes",
"project": "webkit",
"status": "passed",
"browser": "26.6"
},
{
"title": "published: subtitle object URL contains real VTT data",
"project": "chromium",
"status": "passed",
"browser": "153.0.8010.12"
},
{
"title": "published: download starts and removes its temporary anchor",
"project": "chromium",
"status": "passed",
"browser": "153.0.8010.12"
},
{
"title": "candidate: subtitle object URL contains real VTT data",
"project": "chromium",
"status": "passed",
"browser": "153.0.8010.12"
},
{
"title": "candidate: download starts and removes its temporary anchor",
"project": "chromium",
"status": "passed",
"browser": "153.0.8010.12"
},
{
"title": "candidate download releases the anchor even when click fails",
"project": "chromium",
"status": "passed",
"browser": "153.0.8010.12"
},
{
"title": "published: subtitle object URL contains real VTT data",
"project": "firefox",
"status": "passed",
"browser": "155.0"
},
{
"title": "published: download starts and removes its temporary anchor",
"project": "firefox",
"status": "passed",
"browser": "155.0"
},
{
"title": "candidate: subtitle object URL contains real VTT data",
"project": "firefox",
"status": "passed",
"browser": "155.0"
},
{
"title": "candidate: download starts and removes its temporary anchor",
"project": "firefox",
"status": "passed",
"browser": "155.0"
},
{
"title": "candidate download releases the anchor even when click fails",
"project": "firefox",
"status": "passed",
"browser": "155.0"
},
{
"title": "published: subtitle object URL contains real VTT data",
"project": "webkit",
"status": "passed",
"browser": "26.6"
},
{
"title": "published: download starts and removes its temporary anchor",
"project": "webkit",
"status": "passed",
"browser": "26.6"
},
{
"title": "candidate: subtitle object URL contains real VTT data",
"project": "webkit",
"status": "passed",
"browser": "26.6"
},
{
"title": "candidate: download starts and removes its temporary anchor",
"project": "webkit",
"status": "passed",
"browser": "26.6"
},
{
"title": "candidate download releases the anchor even when click fails",
"project": "webkit",
"status": "passed",
"browser": "26.6"
}
]
}
@@ -0,0 +1,36 @@
# CORE-02:带事件映射的 Emitter
## 实现与保留契约
Emitter 迁移为 src/utils/emitter.ts,支持事件名到参数 tuple 的映射、可选/readonly 参数、symbol、
ctx 推导和子类链式返回。默认开放通道;已知事件可与开放自定义事件组合,已知 payload 不被放宽。
当前 JS 播放器与现有公开声明继续渐进迁移,不在本任务改变 Artplayer 构造或新增公开方法。
保留懒创建的普通对象 e、原始 fn/ctx、once wrapper 的 `_` 引用、方法参数个数和描述符。
declare 字段不生成运行时初始化。派发浅拷贝数组,普通订阅移除/追加、原始 callback 移除 once、
异常传播和停止当前派发等语义由发布/工作区/产物共享的九组契约覆盖。一次受控的密集数组索引
断言保留 off 的原固定长度遍历;没有引入通用 any 或事件库依赖。
## 两处有意修复
- EVENT-NAME-01:旧版使用继承属性查询,toString/constructor/hasOwnProperty/__proto__ 不能
正常注册。现在只读 own entries 并定义 own data property,registry 原型不变。
- EVENT-ONCE-01:较早的普通 listener 嵌套 emit 时,旧版的 once 被内外两个已捕获快照重复执行。
wrapper 现在先记录 consumed 再取消订阅,跨快照只调用一次。普通 listener 的快照行为不变。
这两项是已复现缺陷,不作为必须保留的旧行为。Node 对照和三个真实浏览器都分别保留旧失败观察
与候选修复断言;不会通过更新冻结发布结果来制造兼容结论。
## 验证
- 严格源码类型检查包含七个必须拒绝的错误调用;名字/payload/receiver/自定义通道都有正例。
- `yarn ci:check` 共 85 项 Node/基线测试通过。
- 实际 UMD、legacy、ESM 各 29 项 Emitter 对照及修复测试通过。
- `yarn build artplayer` / `yarn build:i18n` 重建 dist 与 docs/compiled。
- 严格 tarball 安装消费:27 项运行时、五组类型零诊断;共享 Emitter 契约已随安装检查增加。
- 安装产物三浏览器 75 项通过,无重试/跳过,包括真实播放器和 chapter 的既有回归。
[执行指纹](../baselines/emitter-validation.json) 记录最终 runtime 与浏览器资源的一致性。
[核心架构](../../packages/artplayer/ARCHITECTURE.md) 已更新数据和事件所有权。新修复在统一风险台账关闭,
公共 Emitter 声明扩展仍属于 CORE-07。下一项 CORE-03 建立内部资源作用域,再接初始化/销毁修复。
独立提交包含生成产物;未升级版本、推送或发布。回退该提交即可恢复本次行为及源码。
+3 -2
View File
@@ -4,7 +4,7 @@
基线:`40fcda6a37d0049d42e49c1e64e70d4fd9ba5f7f`。总任务 214 项,范围 22 个包及工作区/示例。
状态:todo 177 / doing 0 / blocked 0 / done 37 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。
状态:todo 176 / doing 0 / blocked 0 / done 38 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。
前置依赖是启动条件;验收是完成条件。任务可以继续拆分,但不能复用或悄悄删除旧 ID。
@@ -105,7 +105,7 @@
| ID | 范围 / 步骤 | 前置依赖 | 交付物 | 验收条件 | 风险 | 状态 |
| --- | --- | --- | --- | --- | --- | --- |
| CORE-01 | artplayer<br>迁移纯工具并冻结导出 | ENG-03, ENG-04, ENG-06, PILOT-01 | utils/time/property/format/file/error/subtitle 的分批 TS 迁移 | Artplayer.utils 导出/参数/绑定保持,纯逻辑与类型测试通过 | M | done |
| CORE-02 | artplayer<br>迁移内部 Emitter | CORE-01, BASE-03 | 带类型事件映射的原 Emitter 实现 | ctx、once/off、重入/异常和链式返回保持 | H | todo |
| CORE-02 | artplayer<br>迁移内部 Emitter | CORE-01, BASE-03 | 带类型事件映射的原 Emitter 实现 | ctx、once/off、重入/异常和链式返回保持 | H | done |
| CORE-03 | artplayer<br>建立内部资源作用域 | CORE-02 | 监听/订阅/定时器/RAF/请求/URL 的资源登记 | 实例与操作作用域分离,单项清理失败不阻断其他资源 | H | todo |
| CORE-04 | artplayer<br>修复初始化与销毁生命周期 | CORE-03, ENG-05, BASE-07 | 构造失败回收、重复/重入 destroy、instances 修复 | 事件顺序、removeHtml、多实例和销毁中异步有真实回归;处理 baselines/lifecycle-coverage.md 的 BASE-LIFE-04/05 并增加候选正向回归;协调 BASE-PERF-01 销毁后定时器与回调归属 | H | todo |
| CORE-05 | artplayer<br>区分输入配置和内部配置 | CORE-01, ENG-04 | Option/ResolvedOption、默认值与校验整理 | 配置合并/错误时机不变,JS 输入仍运行时校验 | M | todo |
@@ -436,6 +436,7 @@
- ENG-10: [记录](changes/2026-09-10-ENG-10-test-reliability.md) [记录](test-reliability.md)
- PILOT-01: [记录](changes/2026-09-10-PILOT-01-chapter.md) [记录](baselines/pilot-validation.json)
- CORE-01: [记录](changes/2026-09-10-CORE-01-typed-utils.md) [记录](baselines/core-utils-validation.json)
- CORE-02: [记录](changes/2026-09-11-CORE-02-typed-emitter.md) [记录](baselines/emitter-validation.json)
- PKG-CHAPTER-01: [记录](changes/2026-09-10-PKG-CHAPTER-01-contract.md) [记录](baselines/chapter-contract.md)
- PKG-CHAPTER-02: [记录](changes/2026-09-10-PKG-CHAPTER-02-tests.md) [记录](baselines/chapter-validation.json)
- PKG-CHAPTER-03: [记录](changes/2026-09-10-PKG-CHAPTER-03-typescript-modules.md) [记录](baselines/chapter-migration-validation.json)
+4
View File
@@ -1,5 +1,9 @@
# 进度与证据
## 当前实施:CORE-02 Emitter TS 迁移完成
事件映射、payload/ctx 和链式类型已加入;九组普通契约保持,另修复原型事件名与嵌套快照重复 once。85 项 Node/基线、75 项三浏览器、三格式各 29 项 Emitter 检查通过;严格打包 27 项运行时/五组类型零诊断。见 [交付](changes/2026-09-11-CORE-02-typed-emitter.md)。当前 214 项,38 完成、176 待办。核心八个 TS 文件、chapter 五个 TS 文件;下一项 CORE-03 内部资源作用域。
## 当前实施:CORE-01 核心工具 TS 迁移完成
七个核心 utils 文件已迁移为 TS,保留导出、属性与定时器契约,修复合并结果原型和下载失败清理;核心产物与 docs/compiled 已由脚本更新。75 项 Node/基线检查、69 项安装产物三浏览器测试、三格式各 18 项工具契约通过;严格打包零诊断。见 [交付](changes/2026-09-10-CORE-01-typed-utils.md)。当前 214 项,37 完成、177 待办。生产迁移:chapter 五个 TS 文件、核心 utils 七个 TS 文件;核心其他模块仍待迁移。下一项 CORE-02 内部 Emitter。公开 Utils 声明差异单独登记 BASE-TYPE-05,交 CORE-07 协调,不计为已修复。
+2
View File
@@ -47,3 +47,5 @@
| UTIL-MERGE-01 | resolved / 已复现 | mergeDeep lets a JSON __proto__ key replace the result prototype | CORE-01 |
| UTIL-DOWNLOAD-01 | resolved / 源码/产物事实 | Temporary download anchor remains if click throws | CORE-01 |
| BASE-TYPE-05 | open / 源码/产物事实 | Public Utils declarations omit exports and misstate timer/descriptor signatures | CORE-07 |
| EVENT-NAME-01 | resolved / 已复现 | Emitter event names collide with Object.prototype | CORE-02 |
| EVENT-ONCE-01 | resolved / 已复现 | Nested dispatch snapshots invoke the same once registration twice | CORE-02 |
+47 -1
View File
@@ -2,7 +2,7 @@
"schemaVersion": 1,
"task": "BASE-07",
"sourceCommit": "e01f39ff",
"updatedAt": "2026-09-10T15:48:43.324Z",
"updatedAt": "2026-09-10T16:03:52.413Z",
"note": "Open means closure evidence is outstanding; source-observed and unverified are not reproduced runtime bugs. A source issue already mitigated in the workspace still requires candidate regression evidence. No accepted-with-scope item is implied by baseline task completion.",
"items": [
{
@@ -715,6 +715,52 @@
],
"compatibleResolution": "Coordinate compatible public overloads/exports separately; use accurate strict types in migrated source.",
"closureCriteria": "Cover missing unescape/ArtPlayerError, def identity/property keys, optional sleep, timer void returns and ignored debounce context; retain legal old consumers in new/old compilers."
},
{
"id": "EVENT-NAME-01",
"title": "Emitter event names collide with Object.prototype",
"confirmation": "reproduced",
"status": "resolved",
"owners": [
"CORE-02"
],
"evidence": [
"refactor/changes/2026-09-11-CORE-02-typed-emitter.md",
"test/public-behavior.test.js",
"test/browser/emitter.spec.js"
],
"compatibleResolution": "Own property lookup and data descriptors accept reserved event names while preserving registry prototype.",
"closureCriteria": "Published observation and candidate regression pass in Node, all three artifact formats and three browsers.",
"resolutionEvidence": [
"refactor/changes/2026-09-11-CORE-02-typed-emitter.md",
"refactor/baselines/emitter-validation.json",
"test/public-behavior.test.js",
"test/browser/emitter.spec.js"
],
"resolutionRationale": "Own property lookup and data descriptors accept reserved event names while preserving registry prototype."
},
{
"id": "EVENT-ONCE-01",
"title": "Nested dispatch snapshots invoke the same once registration twice",
"confirmation": "reproduced",
"status": "resolved",
"owners": [
"CORE-02"
],
"evidence": [
"refactor/changes/2026-09-11-CORE-02-typed-emitter.md",
"test/public-behavior.test.js",
"test/browser/emitter.spec.js"
],
"compatibleResolution": "The wrapper records consumption before unsubscribe/invocation; ordinary dispatch snapshot semantics are retained.",
"closureCriteria": "Published observation and candidate regression pass in Node, all three artifact formats and three browsers.",
"resolutionEvidence": [
"refactor/changes/2026-09-11-CORE-02-typed-emitter.md",
"refactor/baselines/emitter-validation.json",
"test/public-behavior.test.js",
"test/browser/emitter.spec.js"
],
"resolutionRationale": "The wrapper records consumption before unsubscribe/invocation; ordinary dispatch snapshot semantics are retained."
}
]
}
+5 -2
View File
@@ -770,11 +770,14 @@
"CORE-01",
"BASE-03"
],
"status": "todo",
"status": "done",
"risk": "H",
"deliverable": "带类型事件映射的原 Emitter 实现",
"acceptance": "ctx、once/off、重入/异常和链式返回保持",
"evidence": []
"evidence": [
"changes/2026-09-11-CORE-02-typed-emitter.md",
"baselines/emitter-validation.json"
]
},
{
"id": "CORE-03",
+28
View File
@@ -0,0 +1,28 @@
import { expect, test } from './fixtures.js'
for (const core of ['published', 'candidate']) {
test(`${core}: emitter event names and once across nested dispatch`, async ({ page }) => {
await page.goto(`/test/player.html?core=${core}&chapter=published`)
const result = await page.evaluate(() => {
const emitter = new window.Artplayer.Emitter()
const freshKeys = Object.keys(emitter)
let reservedCalls = 0
let errorName
try {
emitter.on('__proto__', () => reservedCalls++).emit('__proto__').off('__proto__')
}
catch (error) { errorName = error.name }
let nested = false
let onceCalls = 0
emitter.on('value', () => {
if (!nested) {
nested = true
emitter.emit('value')
}
}).once('value', () => onceCalls++)
emitter.emit('value')
return { freshKeys, reservedCalls, errorName, onceCalls }
})
expect(result).toEqual({ freshKeys: [], reservedCalls: core === 'published' ? 0 : 1, errorName: core === 'published' ? 'TypeError' : undefined, onceCalls: core === 'published' ? 2 : 1 })
})
}
+45
View File
@@ -1,6 +1,51 @@
import assert from 'node:assert/strict'
export const emitterContracts = {
'EVENT.lazy-registry': function (Emitter) {
const emitter = new Emitter()
assert.deepEqual(Object.keys(emitter), [])
emitter.emit('empty').off('empty')
assert.equal(Object.getOwnPropertyDescriptor(emitter, 'e').enumerable, true)
assert.deepEqual(Object.keys(emitter.e), [])
assert.equal(typeof emitter.e.hasOwnProperty, 'function')
},
'EVENT.symbol-number-channels': function (Emitter) {
const emitter = new Emitter()
const symbol = Symbol('channel')
const seen = []
emitter.on(symbol, value => seen.push(value)).on(1, value => seen.push(value))
emitter.emit(symbol, 'symbol').emit('1', 'numeric')
emitter.off(symbol).off(1).emit(symbol).emit('1')
assert.deepEqual(seen, ['symbol', 'numeric'])
},
'EVENT.context-removal': function (Emitter) {
const emitter = new Emitter()
const seen = []
function fn() {
seen.push(this)
}
const a = {}
const b = {}
emitter.on('value', fn, a).once('value', fn, b)
const wrapper = emitter.e.value[1].fn
assert.equal(wrapper._, fn)
emitter.off('value', wrapper).emit('value')
assert.deepEqual(seen, [a])
emitter.on('value', fn, b).off('value', fn).emit('value')
assert.deepEqual(seen, [a])
},
'EVENT.once-throw-consumed': function (Emitter) {
const emitter = new Emitter()
const marker = new Error('once failed')
let calls = 0
emitter.once('value', () => {
calls++
throw marker
})
assert.throws(() => emitter.emit('value'), error => error === marker)
emitter.emit('value')
assert.equal(calls, 1)
},
'EVENT.chain-context-arguments': function (Emitter) {
const emitter = new Emitter()
const context = {}
+2 -1
View File
@@ -5,6 +5,7 @@ import path from 'node:path'
import { test } from 'node:test'
import { checkFiles, publishedConsumer } from '../scripts/package-check.mjs'
import { removeConsumer, runtimeConsumer } from '../scripts/package-consumer.mjs'
import { emitterContracts } from './contracts/emitter.js'
test('Package checks reject missing files, missing wildcard exports and internal configuration', () => {
const manifest = { name: 'fixture', main: './dist/main.js', module: './dist/main.mjs', types: './types/main.d.ts', legacy: './dist/legacy.js', exports: { '.': './dist/main.js', './lang/*': './dist/lang/*.js' } }
@@ -19,7 +20,7 @@ test('Package checks reject missing files, missing wildcard exports and internal
test('Actual isolated runtime rejects removed default exports and required files', async () => {
const { dir } = await publishedConsumer()
try {
assert.equal(runtimeConsumer(dir).checks.length, 23)
assert.equal(runtimeConsumer(dir).checks.length, 18 + Object.keys(emitterContracts).length)
const esm = path.join(dir, 'node_modules/artplayer-plugin-chapter/dist/artplayer-plugin-chapter.mjs')
const original = fs.readFileSync(esm)
fs.writeFileSync(esm, 'export const removedDefault = true\n')
+35
View File
@@ -1,3 +1,4 @@
import assert from 'node:assert/strict'
import process from 'node:process'
// eslint-disable-next-line test/no-import-node-test -- Run the same public contract against each actual implementation.
import { test } from 'node:test'
@@ -12,3 +13,37 @@ for (const { name, Artplayer } of targets) {
for (const [id, verify] of Object.entries(emitterContracts))
test(`${id}: ${name}`, () => verify(Artplayer.Emitter))
}
test('EVENT.prototype-event-names: candidate supports names that collide with Object.prototype', () => {
for (const name of ['__proto__', 'constructor', 'toString', 'hasOwnProperty']) {
assert.throws(() => new targets[0].Artplayer.Emitter().on(name, () => {}), error => error.name === 'TypeError')
for (const { Artplayer } of targets.slice(1)) {
const emitter = new Artplayer.Emitter()
let calls = 0
const fn = () => calls++
emitter.emit(name).off(name)
const prototype = Object.getPrototypeOf(emitter.e)
emitter.on(name, fn).once(name, fn)
emitter.emit(name).emit(name).off(name, fn).emit(name)
assert.equal(calls, 3)
assert.equal(Object.prototype.hasOwnProperty.call(emitter.e, name), false)
assert.equal(Object.getPrototypeOf(emitter.e), prototype)
}
}
})
test('EVENT.once-nested-snapshot: candidate consumes a once registration across nested dispatch snapshots', () => {
for (const [index, { Artplayer }] of targets.entries()) {
const emitter = new Artplayer.Emitter()
let nested = false
let calls = 0
emitter.on('value', () => {
if (!nested) {
nested = true
emitter.emit('value')
}
}).once('value', () => calls++)
emitter.emit('value')
assert.equal(calls, index === 0 ? 2 : 1)
}
})
+42
View File
@@ -0,0 +1,42 @@
import type { Events } from 'artplayer'
import Emitter from '../../packages/artplayer/src/utils/emitter'
const symbol = Symbol('message')
interface Messages {
ready: []
value: [count: number, label?: string]
readonly: readonly [value: number]
[symbol]: [message: string]
}
class TypedEmitter extends Emitter<Messages> {
count = 0
}
const events = new TypedEmitter()
const context = { total: 0 }
const chain: TypedEmitter = events.on('value', function (count, label) {
this.total += count
label?.toUpperCase()
}, context).once('ready', () => {}).emit('value', 1).off('ready')
events.emit(symbol, 'message')
events.emit('readonly', 1)
const playerEvents = new Emitter<Events & Record<string, unknown[]>>()
playerEvents.emit('setBar', 'loaded', 0.5)
playerEvents.emit('custom:event', { extra: true })
// @ts-expect-error Known events retain their payload types with open custom names.
playerEvents.emit('setBar', 'invalid', 0.5)
// @ts-expect-error A declared map rejects unknown names.
events.emit('missing')
// @ts-expect-error Payload types are correlated with the event name.
events.emit('value', 'one')
// @ts-expect-error Required payloads cannot be omitted.
events.emit('value')
// @ts-expect-error Empty events reject extra values.
events.emit('ready', 1)
// @ts-expect-error Listener arguments must match the event.
events.on('value', (count: string) => count)
// @ts-expect-error Explicit receiver types must agree with the provided context.
events.on('ready', contextListener, { total: 'zero' })
function contextListener(this: { total: number }) {
return this.total
}
void chain