YouTube JS Engine Tamer

To enhance YouTube performance by modifying YouTube JS Engine

当前为 2024-04-22 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name YouTube JS Engine Tamer
  3. // @namespace UserScripts
  4. // @match https://www.youtube.com/*
  5. // @version 0.13.0
  6. // @license MIT
  7. // @author CY Fung
  8. // @icon https://github.com/cyfung1031/userscript-supports/raw/main/icons/yt-engine.png
  9. // @description To enhance YouTube performance by modifying YouTube JS Engine
  10. // @grant none
  11. // @require https://cdn.jsdelivr.net/gh/cyfung1031/userscript-supports@7221a4efffd49d852de0074ec503d4febb99f28b/library/nextBrowserTick.min.js
  12. // @run-at document-start
  13. // @unwrap
  14. // @inject-into page
  15. // @allFrames true
  16. // ==/UserScript==
  17.  
  18. (() => {
  19.  
  20. const NATIVE_CANVAS_ANIMATION = false; // for #cinematics
  21. const FIX_schedulerInstanceInstance = 2 | 4;
  22. const FIX_yt_player = true; // DONT CHANGE
  23. const FIX_Animation_n_timeline = true;
  24. const NO_PRELOAD_GENERATE_204 = false;
  25. const ENABLE_COMPUTEDSTYLE_CACHE = true;
  26. const NO_SCHEDULING_DUE_TO_COMPUTEDSTYLE = true;
  27. const CHANGE_appendChild = true; // discussions#236759
  28.  
  29. const FIX_error_many_stack = true; // should be a bug caused by uBlock Origin
  30. // const FIX_error_many_stack_keepAliveDuration = 200; // ms
  31. // const FIX_error_many_stack_keepAliveDuration_check_if_n_larger_than = 8;
  32.  
  33. const FIX_Iframe_NULL_SRC = true;
  34.  
  35. const IGNORE_bindAnimationForCustomEffect = true; // prevent `v.bindAnimationForCustomEffect(this);` being executed
  36.  
  37. const FIX_ytdExpander_childrenChanged = true;
  38. const FIX_paper_ripple_animate = true;
  39. const FIX_avoid_incorrect_video_meta = true; // omit the incorrect yt-animated-rolling-number
  40. const FIX_avoid_incorrect_video_meta_emitterBehavior = true;
  41.  
  42. const FIX_doIdomRender = true;
  43.  
  44. const FIX_Shady = true;
  45.  
  46. const FIX_ytAction_ = true; // ytd-app
  47. const FIX_onVideoDataChange = false;
  48. // const FIX_onClick = true;
  49. const FIX_onStateChange = true;
  50. const FIX_onLoopRangeChange = true;
  51. // const FIX_maybeUpdateFlexibleMenu = true; // ytd-menu-renderer
  52. const FIX_VideoEVENTS_v2 = true; // true might cause bug in switching page
  53.  
  54. const ENABLE_discreteTasking = true;
  55. // << if ENABLE_discreteTasking >>
  56. const FIX_stampDomArray_stableList = true;
  57. const ENABLE_weakenStampReferences = true; // disabled in old browsers
  58. // << end >>
  59.  
  60. const FIX_perfNow = true; // history state issue; see https://bugzilla.mozilla.org/show_bug.cgi?id=1756970
  61. const ENABLE_ASYNC_DISPATCHEVENT = false; // problematic
  62.  
  63. const UNLOAD_DETACHED_POLYMER = false; // unstable
  64.  
  65. const WEAK_REF_BINDING = true; // false if your browser is slow
  66. // << if WEAK_REF_BINDING >>
  67. const WEAK_REF_PROXY_DOLLAR = true; // false if your browser is slow
  68. // << end >>
  69.  
  70. const TO_REMOVE_PRUNE_propNeedles = true; // brave scriptlet related
  71. const DEBUG_removePrune = false; // true for DEBUG
  72.  
  73. const FIX_XHR_REQUESTING = true;
  74. const FIX_VIDEO_BLOCKING = true; // usually it is a ads block issue
  75.  
  76. const LOG_FETCHMETA_UPDATE = false; // for DEBUG
  77.  
  78. const IGNORE_bufferhealth_CHECK = false; // experimental; true will make "Stats for nerds" no info.
  79.  
  80. const DENY_requestStorageAccess = true; // remove document.requestStorageAccess
  81. const DISABLE_IFRAME_requestStorageAccess = true; // no effect if DENY_requestStorageAccess is true
  82.  
  83. const DISABLE_COOLDOWN_SCROLLING = true; // YT cause scroll hang in MacOS
  84.  
  85. // ----------------------------- Shortkey Keyboard Control -----------------------------
  86. // dependency: FIX_yt_player
  87.  
  88. const FIX_SHORTCUTKEYS = 2; // 0 - no fix; 1 - basic fix; 2 - advanced fix
  89. // [0] no fix - not recommended
  90. // [1] basic fix - just fix the global focus detection variable
  91. // [2] advanced fix - call the shortcut actions directly, auto foucs change, direct control of spacebar behavior, etc
  92. // (note) 0 or 1 if you find conflict with other userscripts/plugin
  93.  
  94. const CHANGE_SPEEDMASTER_SPACEBAR_CONTROL = 0; // 0 - disable; 1 - force true; 2 - force false
  95. const USE_IMPROVED_PAUSERESUME_UNDER_NO_SPEEDMASTER = true; // only for SPEEDMASTER = false & FIX_SHORTCUTKEYS = 2
  96.  
  97.  
  98. // const CAN_TUNE_VOLUMN_AFTER_RESUME_OR_PAUSE = false; // NO USE; TO BE REVIEWED
  99.  
  100. // ----------------------------- Shortkey Keyboard Control -----------------------------
  101.  
  102. /*
  103. window.addEventListener('edm',()=>{
  104. let p = [...this.onerror.errorTokens][0].token; (()=>{ console.log(p); throw new Error(p);console.log(334,p) })()
  105. });
  106.  
  107. window.addEventListener('edn',()=>{
  108. let p = [...this.onerror.errorTokens][0].token+"X"; (()=>{ console.log(p); throw new Error(p);console.log(334,p) })()
  109. });
  110. window.addEventListener('edr',()=>{
  111. let p = '123'; (()=>{ console.log(p); throw new Error(p);console.log(334,p) })()
  112. });
  113. */
  114.  
  115. // only for macOS with Chrome/Firefox 100+
  116. const advanceLogging = typeof AbortSignal !== 'undefined' && typeof (AbortSignal || 0).timeout === 'function' && typeof navigator !== 'undefined' && /\b(Macintosh|Mac\s*OS)\b/i.test((navigator || 0).userAgent || '');
  117.  
  118. const win = this instanceof Window ? this : window;
  119.  
  120. // Create a unique key for the script and check if it is already running
  121. const hkey_script = 'jswylcojvzts';
  122. if (win[hkey_script]) throw new Error('Duplicated Userscript Calling'); // avoid duplicated scripting
  123. win[hkey_script] = true;
  124.  
  125.  
  126. // const setImmediate = ((self || 0).jmt || 0).setImmediate;
  127. /** @type {(f: ()=>{})=>{}} */
  128. const nextBrowserTick = (self || 0).nextBrowserTick || 0;
  129. const nextBrowserTick_ = nextBrowserTick || (f => f());
  130.  
  131. let p59 = 0;
  132.  
  133. const Promise = (async () => { })().constructor;
  134.  
  135. const PromiseExternal = ((resolve_, reject_) => {
  136. const h = (resolve, reject) => { resolve_ = resolve; reject_ = reject };
  137. return class PromiseExternal extends Promise {
  138. constructor(cb = h) {
  139. super(cb);
  140. if (cb === h) {
  141. /** @type {(value: any) => void} */
  142. this.resolve = resolve_;
  143. /** @type {(reason?: any) => void} */
  144. this.reject = reject_;
  145. }
  146. }
  147. };
  148. })();
  149.  
  150. /**
  151. @param {number} x
  152. @param {number} d */
  153. const toFixed2 = (x, d) => {
  154. let t = x.toFixed(d);
  155. let y = `${+t}`;
  156. return y.length > t.length ? t : y;
  157. }
  158.  
  159.  
  160. let pf31 = new PromiseExternal();
  161.  
  162. // native RAF
  163. let __requestAnimationFrame__ = typeof webkitRequestAnimationFrame === 'function' ? window.webkitRequestAnimationFrame.bind(window) : window.requestAnimationFrame.bind(window);
  164.  
  165. // 1st wrapped RAF
  166. const baseRAF = (callback) => {
  167. return p59 ? __requestAnimationFrame__(callback) : __requestAnimationFrame__((hRes) => {
  168. pf31.then(() => {
  169. callback(hRes);
  170. });
  171. });
  172. };
  173.  
  174. // 2nd wrapped RAF
  175. window.requestAnimationFrame = baseRAF;
  176.  
  177. const insp = o => o ? (o.polymerController || o.inst || o || 0) : (o || 0);
  178. const indr = o => insp(o).$ || o.$ || 0;
  179.  
  180. const prototypeInherit = (d, b) => {
  181. const m = Object.getOwnPropertyDescriptors(b);
  182. for (const p in m) {
  183. if (!Object.getOwnPropertyDescriptor(d, p)) {
  184. Object.defineProperty(d, p, m[p]);
  185. }
  186. }
  187. };
  188.  
  189. /** @type {(o: Object | null) => WeakRef | null} */
  190. const mWeakRef = typeof WeakRef === 'function' ? (o => o ? new WeakRef(o) : null) : (o => o || null);
  191.  
  192. /** @type {(wr: Object | null) => Object | null} */
  193. const kRef = (wr => (wr && wr.deref) ? wr.deref() : wr);
  194.  
  195. if (typeof Document.prototype.requestStorageAccessFor === 'function') {
  196. if (DENY_requestStorageAccess) {
  197. // https://developer.mozilla.org/en-US/docs/Web/API/Document/requestStorageAccessFor
  198. Document.prototype.requestStorageAccessFor = undefined;
  199. console.log('[yt-js-engine-tamer]', 'requestStorageAccessFor is removed.');
  200. } else if (DISABLE_IFRAME_requestStorageAccess && window !== top) {
  201. Document.prototype.requestStorageAccessFor = function () {
  202. return new Promise((resolve, reject) => {
  203. reject();
  204. });
  205. };
  206. }
  207. }
  208.  
  209. FIX_perfNow && performance.timeOrigin > 9 && (() => {
  210. if (performance.now23 || performance.now16 || typeof Performance.prototype.now !== 'function') return;
  211. const f = performance.now23 = Performance.prototype.now;
  212.  
  213. let k = 0; // 0 <= k < 9998m
  214. let u = 0;
  215. let s = ((performance.timeOrigin % 7) + 1) / 7 - 1e-2 / 7; // s > 0.14
  216.  
  217. // By definition, performance.now() is mono increasing.
  218. // Fixing in YouTube.com is required to ensure performance.now() is strictly increasing.
  219. performance.now = performance.now16 = function () {
  220. /**
  221. * Bug 1842437 - When attempting to go back on youtube.com, the content remains the same
  222. *
  223. * If consecutive session history entries had history.state.entryTime set to same value,
  224. * back button doesn't work as expected. The entryTime value is coming from performance.now()
  225. * and modifying its return value slightly to make sure two close consecutive calls don't
  226. * get the same result helped with resolving the issue.
  227. */
  228. // see https://bugzilla.mozilla.org/show_bug.cgi?id=1756970
  229. // see https://bugzilla.mozilla.org/show_bug.cgi?id=1842437
  230.  
  231. const v = typeof (this || 0).now23 === 'function' ? this.now23() + s : f.call(performance) + s; // v > 0.14
  232. if (u + 0.0015 < (u = v)) k = 0; // note: hRes should be accurate to 5 µs in isolated contexts
  233. else if (k < 0.001428) k += 1e-6 / 7; // M = 10000 * m; m * 9996 = 0.001428
  234. else { // more than 9998 consecutive calls
  235. /**
  236. *
  237. * max no. of consecutive calls
  238. *
  239. * Sample Size: 4800
  240. * Sample Avg = 1565.375
  241. * Sample Median = 1469.5
  242. * Sample Max = 5660 << 7500 << 9999
  243. *
  244. *
  245. * */
  246. k = 0;
  247. s += 1 / 7;
  248. }
  249. return v + k; // 0 < v - M < v - M + k < v
  250. }
  251.  
  252. let loggerMsg = '';
  253. if (`${performance.now()}` === `${performance.now()}`) {
  254. const msg1 = 'performance.now is modified but performance.now() is not strictly increasing.';
  255. const msg2 = 'performance.now cannot be modified and performance.now() is not strictly increasing.';
  256. loggerMsg = performance.now !== performance.now16 ? msg1 : msg2; // might not able to set in Firefox
  257. }
  258. loggerMsg && console.warn(loggerMsg);
  259. })();
  260.  
  261. if (ENABLE_ASYNC_DISPATCHEVENT && nextBrowserTick) {
  262. const filter = new Set([
  263. 'yt-action',
  264. // 'iframe-src-replaced',
  265. 'shown-items-changed',
  266. 'can-show-more-changed', 'collapsed-changed',
  267.  
  268. 'yt-navigate', 'yt-navigate-start', 'yt-navigate-cache',
  269. 'yt-player-updated', 'yt-page-data-fetched', 'yt-page-type-changed', 'yt-page-data-updated',
  270. 'yt-navigate-finish',
  271.  
  272. // 'data-changed','yt-watch-comments-ready'
  273. ])
  274. EventTarget.prototype.dispatchEvent938 = EventTarget.prototype.dispatchEvent;
  275. EventTarget.prototype.dispatchEvent = function (event) {
  276. const type = (event || 0).type;
  277. if (typeof type === 'string' && event.isTrusted === false && (event instanceof CustomEvent) && event.cancelable === false) {
  278. if (!filter.has(type) && !type.endsWith('-changed')) {
  279. if (this instanceof Node || this instanceof Window) {
  280. nextBrowserTick(() => this.dispatchEvent938(event));
  281. return true;
  282. }
  283. }
  284. }
  285. return this.dispatchEvent938(event);
  286. }
  287. }
  288.  
  289. // avoid REGEXP testPattern execution in Brave's scriptlet for performance boost
  290. const removePrune_propNeedles = () => {
  291. // const xhr = new XMLHttpRequest;
  292. const pdOri = Object.getOwnPropertyDescriptor(Map.prototype, 'size');
  293. if (!pdOri || pdOri.configurable !== true) return;
  294. let propNeedles = null;
  295. const pdNew = {
  296. configurable: true,
  297. enumerable: true,
  298. get: function () {
  299. propNeedles = this;
  300. if (DEBUG_removePrune) debugger; // to locate Brave scriptlets
  301. throw new Error();
  302. }
  303. }
  304. Object.defineProperty(Map.prototype, 'size', pdNew);
  305. try {
  306. XMLHttpRequest.prototype.open.call(0);
  307. // xhr.open.call(null)
  308. } catch (e) { }
  309. Object.defineProperty(Map.prototype, 'size', pdOri);
  310. if (!propNeedles) return;
  311. const entries = [...propNeedles.entries()];
  312. propNeedles.clear();
  313. console.log('[yt-js-engine-tamer] propNeedles is cleared from scriptlet', entries, propNeedles);
  314. }
  315.  
  316. if (TO_REMOVE_PRUNE_propNeedles) {
  317. removePrune_propNeedles();
  318. }
  319.  
  320. if (FIX_XHR_REQUESTING) {
  321.  
  322. const URL = window.URL || new Function('return URL')();
  323. const createObjectURL = URL.createObjectURL.bind(URL);
  324.  
  325. XMLHttpRequest = (() => {
  326. const XMLHttpRequest_ = XMLHttpRequest;
  327. if ('__xmMc8__' in XMLHttpRequest_.prototype) return XMLHttpRequest_;
  328. const url0 = createObjectURL(new Blob([], { type: 'text/plain' }));
  329. const c = class XMLHttpRequest extends XMLHttpRequest_ {
  330. constructor(...args) {
  331. super(...args);
  332. }
  333. open(method, url, ...args) {
  334. let skip = false;
  335. if (!url || typeof url !== 'string') skip = true;
  336. else if (typeof url === 'string') {
  337. let turl = url[0] === '/' ? `.youtube.com${url}` : `${url}`;
  338. if (turl.includes('googleads') || turl.includes('doubleclick.net')) {
  339. skip = true;
  340. } else if (turl.includes('.youtube.com/pagead/')) {
  341. skip = true;
  342. } else if (turl.includes('.youtube.com/ptracking')) {
  343. skip = true;
  344. } else if (turl.includes('.youtube.com/youtubei/v1/log_event?')) {
  345. skip = true;
  346. } else if (turl.includes('.youtube.com/api/stats/')) { // /api/stats/
  347. if (turl.includes('.youtube.com/api/stats/qoe?')) {
  348. skip = true;
  349. } else if (turl.includes('.youtube.com/api/stats/ads?')) {
  350. skip = true;
  351. } else {
  352. // skip = true; // for user activity logging e.g. watched videos
  353. }
  354. } else if (turl.includes('play.google.com/log')) {
  355. skip = true;
  356. } else if (turl.includes('.youtube.com//?')) { // //?cpn=
  357. skip = true;
  358. }
  359. }
  360. if (!skip) {
  361. this.__xmMc8__ = 1;
  362. return super.open(method, url, ...args);
  363. } else {
  364. this.__xmMc8__ = 2;
  365. return super.open('GET', url0);
  366. }
  367. }
  368. send(...args) {
  369. if (this.__xmMc8__ === 1) {
  370. return super.send(...args);
  371. } else if (this.__xmMc8__ === 2) {
  372. return super.send();
  373. } else {
  374. console.log('[yt-js-engine-tamer]', 'xhr warning');
  375. return super.send(...args);
  376. }
  377. }
  378. }
  379. c.prototype.__xmMc8__ = 0;
  380. prototypeInherit(c.prototype, XMLHttpRequest_.prototype);
  381. return c;
  382. })();
  383. }
  384.  
  385. // Alternative HACK -> Tabview Youtube
  386. if (DISABLE_COOLDOWN_SCROLLING && typeof EventTarget.prototype.addEventListener52178 !== 'function' && typeof EventTarget.prototype.addEventListener === 'function') {
  387.  
  388. // ---- << this.overscrollConfig HACK >> -----
  389.  
  390. // 2024.04.19 - Playlist in Single Column Mode cannot be scrolled correctly.
  391.  
  392. /*
  393.  
  394. ;function gZb(a, b) {
  395. b = void 0 === b ? !0 : b;
  396. a.addEventListener("wheel", hZb);
  397. a.overscrollConfig = {
  398. cooldown: b
  399. }
  400. }
  401. function iZb(a) {
  402. a.overscrollConfig = void 0;
  403. a.removeEventListener("wheel", hZb)
  404. }
  405. function hZb(a) {
  406. var b = a.deltaY
  407. , c = a.target
  408. , d = null;
  409. if (window.Polymer && window.Polymer.Element) {
  410. if (c = a.path || a.composedPath && a.composedPath()) {
  411. c = g(c);
  412. for (var e = c.next(); !e.done && (e = e.value,
  413. !jZb(e, b)); e = c.next())
  414. if (e.overscrollConfig) {
  415. d = e;
  416. break
  417. }
  418. }
  419. } else
  420. for (; c && !jZb(c, b); ) {
  421. if (c.overscrollConfig) {
  422. d = c;
  423. break
  424. }
  425. c = c.parentElement
  426. }
  427. d && (b = d.overscrollConfig,
  428. b.cooldown ? (d = a.deltaY,
  429. c = b.lastDeltaY || 0,
  430. b.lastDeltaY = d,
  431. e = b.lastStopped || 0,
  432. c && e && 0 < c == 0 < d ? Math.abs(c) >= Math.abs(d) ? (d = e + 1200,
  433. c = !1) : (d = e + 600,
  434. c = !0) : (d = Date.now() + 600,
  435. c = !0),
  436. d > Date.now() && (a.preventDefault(),
  437. c && (b.lastStopped = Date.now()))) : a.preventDefault())
  438. }
  439. */
  440.  
  441. let wheelHandler = function (a) {
  442. if (window.Polymer && window.Polymer.Element) {
  443. let c;
  444. if (c = a.path || a.composedPath && a.composedPath()) {
  445. for (const e of c) {
  446. const cnt = insp(e);
  447. if (e.overscrollConfig) e.overscrollConfig = void 0;
  448. if (cnt.overscrollConfig) cnt.overscrollConfig = void 0;
  449. }
  450. }
  451. } else {
  452. let e = a.target;
  453. for (; e instanceof Element; e = e.parentElement) {
  454. const cnt = insp(e);
  455. if (e.overscrollConfig) e.overscrollConfig = void 0;
  456. if (cnt.overscrollConfig) cnt.overscrollConfig = void 0;
  457. }
  458. }
  459. };
  460.  
  461. let checkWheelListenerObjs = null;
  462.  
  463. let getObjsFn = () => {
  464. let euyVal = 0;
  465. const eukElm = {};
  466. Object.setPrototypeOf(eukElm, HTMLElement.prototype);
  467. const euzObj = new Proxy(eukElm, {
  468. get(target, prop) {
  469. throw `ErrorF31.get(${prop})`
  470. },
  471. set(target, prop, value) {
  472. throw `ErrorF33.set(${prop}, ${value})`
  473. }
  474. });
  475. const euxElm = new Proxy(eukElm, {
  476. get(target, prop) {
  477. if (prop === 'scrollTop') {
  478. euyVal = euyVal | 8;
  479. return 0;
  480. }
  481. if (prop === 'overscrollConfig') {
  482. euyVal = euyVal | 16;
  483. return void 0;
  484. }
  485. if (prop === 'scrollHeight' || prop === 'clientHeight' || prop === 'offsetHeight') {
  486. return 640;
  487. }
  488. if (prop === 'scrollLeft') {
  489. euyVal = euyVal | 8;
  490. return 0;
  491. }
  492. if (prop === 'scrollWidth' || prop === 'clientWidth' || prop === 'offsetWidth') {
  493. return 800;
  494. }
  495. throw `ErrorF45.get(${prop})`
  496. },
  497. set(target, prop, value) {
  498. throw `ErrorF47.set(${prop}, ${value})`
  499. }
  500. });
  501. const eukEvt = {};
  502. Object.setPrototypeOf(eukEvt, WheelEvent.prototype);
  503. const euyEvt = new Proxy(eukEvt, {
  504. get(target, prop) {
  505. if (prop === 'deltaY' || prop === 'deltaX') {
  506. euyVal = euyVal | 1;
  507. return -999;
  508. }
  509. if (prop === 'target') {
  510. euyVal = euyVal | 2;
  511. return euxElm
  512. }
  513. if (prop === 'path' || prop === 'composedPath') {
  514. euyVal = euyVal | 2;
  515. return [euxElm]
  516. }
  517. throw `ErrorF51.get(${prop})`
  518. },
  519. set(target, prop, value) {
  520. throw `ErrorF53.set(${prop}, ${value})`
  521. }
  522. });
  523. const setVal = (v) => {
  524. euyVal = v;
  525. }
  526. const getVal = () => {
  527. return euyVal;
  528. }
  529. return { euzObj, euyEvt, setVal, getVal };
  530. }
  531.  
  532. let checkWheelListener = (callback) => {
  533.  
  534. let callbackIdentifier = '';
  535.  
  536. let res = null;
  537. try {
  538. const { euzObj, euyEvt, getVal, setVal } = checkWheelListenerObjs || (checkWheelListenerObjs = getObjsFn());
  539. setVal(0);
  540. if (callback.call(euzObj, euyEvt) !== void 0) throw 'ErrorF99';
  541. throw `RESULT${getVal()}`;
  542. } catch (e) {
  543. res = e;
  544. }
  545.  
  546. res = `${res}` || `${null}`;
  547. if (res.length > 20) res = `${res.substring(0, 20)}...`;
  548.  
  549. callbackIdentifier = res;
  550. if (callbackIdentifier === 'RESULT27') 0;
  551. else if (callbackIdentifier === 'RESULT0') {
  552. // a.isSearch && !a.disableWheelScroll && B("desktop_enable_dmpanel_wheel_scroll")
  553. } else if (callbackIdentifier.startsWith('RESULT')) {
  554. console.log('wheel eventListener - RESULT', callbackIdentifier, callback)
  555. }
  556. return callbackIdentifier;
  557.  
  558. };
  559.  
  560. let callbackFound = false;
  561. EventTarget.prototype.addEventListener52178 = EventTarget.prototype.addEventListener;
  562. EventTarget.prototype.addEventListener = function (type, callback, option = void 0) {
  563. // M-youtube-js-engine-tamer.52178
  564. if (type === 'wheel' && !option && typeof callback === 'function' && callback.length === 1) {
  565. // (( match with signature `a.addEventListener("wheel", hZb);` )) [subject to further review]
  566. const callbackIdentifier = callback.yaujmoms || (callbackFound ? 'IGNORE' : (callback.yaujmoms = checkWheelListener(callback)));
  567. // RESULTXX / ErrorFXX / Other...
  568. if (callbackIdentifier === 'RESULT27') {
  569. this.overscrollConfigDisable = true;
  570. if (!callbackFound) {
  571. callbackFound = true; // suppose only one function is assigned to overscrollConfig cooldown [no function binding]
  572. getObjsFn = checkWheelListener = null;
  573. checkWheelListenerObjs = null;
  574. wheelHandler = null;
  575. }
  576. return void 0;
  577. } else if (!callbackFound && !this.overscrollConfigDisable) {
  578. this.overscrollConfigDisable = true;
  579. this.addEventListener52178('wheel', wheelHandler, { passive: false });
  580. }
  581. }
  582. return this.addEventListener52178(type, callback, option);
  583. };
  584.  
  585. // ---- << this.overscrollConfig HACK >> -----
  586.  
  587. }
  588.  
  589. const { pageMediaWatcher, shortcutKeysFixer, keyboardController } = (() => {
  590.  
  591. let p_a_objWR = null;
  592. let isSpaceKeyImmediate = false; // for ADVANCED_FIX_SHORTCUTKEYS
  593. let ytPageReady = 0;
  594.  
  595. let isSpeedMastSpacebarControlEnabled = false; // youtube experimental feature // can be forced by CHANGE_SPEEDMASTER_SPACEBAR_CONTROL
  596. let mediaPlayerElementWR = null;
  597. let focusedElementAtSelection = null;
  598.  
  599. // let want_control_video = false;
  600.  
  601. let spaceBarControl_keyG = '';
  602.  
  603. let lastUserAction = 0;
  604.  
  605. const wmKeyControlPhase = new WeakMap();
  606.  
  607. let currentSelectionText = null;
  608.  
  609. const getCurrentSelectionText = () => {
  610. if (currentSelectionText !== null) return currentSelectionText
  611. return (currentSelectionText = getSelection() + "")
  612. }
  613.  
  614. const pageMediaWatcher = () => {
  615.  
  616. // CAN_TUNE_VOLUMN_AFTER_RESUME_OR_PAUSE && document.addEventListener('wheel', () => {
  617. // want_control_video = false;
  618. // }, { capture: true, passive: true });
  619.  
  620. document.addEventListener('yt-navigate', () => {
  621. ytPageReady = 0;
  622. });
  623. document.addEventListener('yt-navigate-start', () => {
  624. ytPageReady = 0;
  625. });
  626. document.addEventListener('yt-navigate-cache', () => {
  627. ytPageReady = 0;
  628. });
  629.  
  630. document.addEventListener('yt-navigate-finish', () => {
  631. ytPageReady = 1;
  632. });
  633.  
  634. document.addEventListener('durationchange', () => {
  635. for (const elm of document.querySelectorAll('#movie_player video[src], #movie_player audio[src]')) {
  636. if (elm.duration > 0.01) {
  637. if (elm.closest('[hidden]')) continue;
  638. mediaPlayerElementWR = mWeakRef(elm);
  639. return;
  640. }
  641. }
  642. }, { capture: true, passive: true });
  643.  
  644. document.addEventListener('selectionchange', (evt) => {
  645. if (!evt || !evt.isTrusted || !(evt instanceof Event)) return;
  646. currentSelectionText = null;
  647. if (!(evt.target instanceof Node)) return;
  648. focusedElementAtSelection = evt.target;
  649. }, { capture: true, passive: true })
  650.  
  651. document.addEventListener('pointerdown', (evt) => {
  652. if (evt.isTrusted && evt instanceof Event) lastUserAction = Date.now();
  653. }, { capture: true, passive: true });
  654.  
  655.  
  656. document.addEventListener('pointerup', (evt) => {
  657. if (evt.isTrusted && evt instanceof Event) lastUserAction = Date.now();
  658. }, { capture: true, passive: true });
  659.  
  660.  
  661. document.addEventListener('keydown', (evt) => {
  662. if (evt.isTrusted && evt instanceof Event) lastUserAction = Date.now();
  663. }, { capture: true, passive: true });
  664.  
  665. document.addEventListener('keyup', (evt) => {
  666. if (evt.isTrusted && evt instanceof Event) lastUserAction = Date.now();
  667. }, { capture: true, passive: true });
  668.  
  669. };
  670.  
  671.  
  672. const checkKeyB = (p_a_obj) => {
  673.  
  674. const boolList = new Set();
  675. const p_a_obj_api = p_a_obj.api;
  676.  
  677. const nilFunc0 = function () {
  678. return void 0
  679. };
  680. const mt = new Proxy({}, {
  681. get(target, prop) {
  682. if (prop === 'get') return nilFunc0;
  683. return mt;
  684. }
  685. });
  686. const nilFunc = function () {
  687. return mt
  688. };
  689. const mw = new Proxy({}, {
  690. get(target, prop) {
  691. if (prop in p_a_obj_api) {
  692. if (typeof p_a_obj_api.constructor.prototype[prop] === 'function') return nilFunc;
  693. let q = Object.getOwnPropertyDescriptor(p_a_obj_api, prop);
  694. if (q && q.value) {
  695. if (!q.writable) return q.value;
  696. if (typeof q.value === 'string') return '';
  697. if (typeof q.value === 'number') return 0;
  698. if (typeof q.value === 'boolean') return false;
  699. if (q.value && typeof q.value === 'object') return {};
  700. }
  701. }
  702. return undefined;
  703. },
  704. set(target, prop) {
  705. throw 'mwSet';
  706. }
  707. });
  708.  
  709. const mq = new Proxy({}, {
  710. get(target, prop) {
  711. if (prop === 'api') return mw;
  712. if (prop in p_a_obj) {
  713. if (typeof p_a_obj.constructor.prototype[prop] === 'function') return nilFunc;
  714. let q = Object.getOwnPropertyDescriptor(p_a_obj, prop);
  715. if (q && q.value) {
  716. if (!q.writable) return q.value;
  717. if (typeof q.value === 'string') return '';
  718. if (typeof q.value === 'number') return 0;
  719. if (typeof q.value === 'boolean') return false;
  720. if (q.value && typeof q.value === 'object') return {};
  721. }
  722. }
  723. return undefined;
  724. },
  725. set(target, prop, val) {
  726. if (typeof val === 'boolean') boolList.add(prop)
  727. throw `mqSet(${prop},${val})`;
  728. }
  729. });
  730.  
  731. let res = ''
  732. try {
  733. res = `RESULT::${p_a_obj.handleGlobalKeyUp.call(mq, 9, false, false, false, false, "Tab", "Tab")}`;
  734. } catch (e) {
  735. res = `ERROR::${e}`;
  736. }
  737.  
  738. if (boolList.size === 1) {
  739. const value = boolList.values().next().value;
  740. if (res === `ERROR::mqSet(${value},${true})`) {
  741. p_a_obj.__uZWaD__ = value;
  742. }
  743. }
  744.  
  745. console.log('[yt-js-engine-tamer] global shortcut control', { '__uZWaD__': p_a_obj.__uZWaD__ });
  746.  
  747. }
  748.  
  749.  
  750. let pm_p_a = null;
  751.  
  752. const p_a_init = function () {
  753. const r = this.init91();
  754. const keyBw = this.__cPzfo__ || '__NIL__';
  755. const p_a_obj = this[keyBw];
  756. if (!p_a_obj) return;
  757. try {
  758. checkKeyB(p_a_obj);
  759. } catch (e) { }
  760. p_a_objWR = mWeakRef(p_a_obj);
  761. if (FIX_SHORTCUTKEYS > 0) {
  762. if (p_a_obj && !p_a_obj.hVhtg) {
  763. p_a_obj.hVhtg = 1;
  764. p_a_obj.handleGlobalKeyUp91 = p_a_obj.handleGlobalKeyUp;
  765. p_a_obj.handleGlobalKeyUp = p_a_xt.handleGlobalKeyUp;
  766. p_a_obj.handleGlobalKeyDown91 = p_a_obj.handleGlobalKeyDown;
  767. p_a_obj.handleGlobalKeyDown = p_a_xt.handleGlobalKeyDown;
  768. p_a_obj.__handleGlobalKeyBefore__ = p_a_xt.__handleGlobalKeyBefore__;
  769. p_a_obj.__handleGlobalKeyAfter__ = p_a_xt.__handleGlobalKeyAfter__;
  770. }
  771. // if (CAN_TUNE_VOLUMN_AFTER_RESUME_OR_PAUSE && p_a_obj && p_a_obj.api && !p_a_obj.api.hVhtg) {
  772. // const api = p_a_obj.api
  773. // api.hVhtg = 1;
  774. // api.playVideo91 = api.playVideo;
  775. // api.playVideo = p_a_jt.playVideo;
  776. // api.pauseVideo91 = api.pauseVideo;
  777. // api.pauseVideo = p_a_jt.pauseVideo;
  778. // }
  779. }
  780. if (pm_p_a) {
  781. pm_p_a.resolve();
  782. pm_p_a = null;
  783. }
  784. return r;
  785. };
  786.  
  787. const p_a_xt = {
  788.  
  789. __handleGlobalKeyBefore__(a, b, c, d, e, f, h, activeElement) {
  790.  
  791. if (FIX_SHORTCUTKEYS === 2) {
  792.  
  793. if (activeElement) {
  794.  
  795. const controlPhaseCache = wmKeyControlPhase.get(activeElement);
  796.  
  797. if (controlPhaseCache === 6 && getCurrentSelectionText() !== "") void 0;
  798. else if (controlPhaseCache === 1 || controlPhaseCache === 2 || controlPhaseCache === 5) return false;
  799. else if ((controlPhaseCache !== 6 || focusedElementAtSelection === document.activeElement) && getCurrentSelectionText() !== "") return false;
  800.  
  801. }
  802.  
  803. const isSpaceBar = a === 32 && b === false && c === false && d === false && e === false && f === ' ' && h === 'Space';
  804. const isDelayedSpaceBar = FIX_SHORTCUTKEYS === 2 && isSpaceBar && !isSpaceKeyImmediate && isSpeedMastSpacebarControlEnabled;
  805. // console.log(582, isDelayedSpaceBar)
  806. if (isDelayedSpaceBar) return void 0; // accept delay spacebar under isSpeedMastSpacebarControlEnabled (no rejection)
  807.  
  808. if (activeElement && (h === 'Space' || h === 'Enter')) {
  809. const controlPhase = wmKeyControlPhase.get(activeElement);
  810. if (controlPhase === 4 || controlPhase === 5) return false;
  811. }
  812. if (focusedElementAtSelection === activeElement && getCurrentSelectionText() !== "") return false;
  813. // if (!isSpeedMastSpacebarControlEnabled && a === 32 && b === false && c === false && d === false && e === false && f === ' ' && h === 'Space') {
  814. // if (!isSpaceKeyImmediate) return false;
  815. // }
  816. }
  817.  
  818. },
  819.  
  820. __handleGlobalKeyAfter__(a, b, c, d, e, f, h, activeElement, ret) {
  821.  
  822.  
  823. if (FIX_SHORTCUTKEYS === 2 && ret && a >= 32 && ytPageReady === 1 && Date.now() - lastUserAction < 40 && activeElement === document.activeElement) {
  824.  
  825. const isSpaceBar = a === 32 && b === false && c === false && d === false && e === false && f === ' ' && h === 'Space';
  826. const isDelayedSpaceBar = FIX_SHORTCUTKEYS === 2 && isSpaceBar && !isSpaceKeyImmediate && isSpeedMastSpacebarControlEnabled;
  827. // console.log(583, isDelayedSpaceBar)
  828. if (isDelayedSpaceBar) return void 0; // accept delay spacebar under isSpeedMastSpacebarControlEnabled (no rejection)
  829.  
  830. const mediaPlayerElement = kRef(mediaPlayerElementWR);
  831.  
  832. let mediaWorking = false;
  833. if (mediaPlayerElement && (mediaPlayerElement.readyState === 4 || mediaPlayerElement.readyState === 1) && mediaPlayerElement.networkState === 2 && mediaPlayerElement.duration > 0.01) {
  834. mediaWorking = true;
  835. } else if (mediaPlayerElement && !mediaPlayerElement.paused && !mediaPlayerElement.muted && mediaPlayerElement.duration > 0.01) {
  836. mediaWorking = true;
  837. }
  838. // console.log(182, mediaWorking, mediaPlayerElement.readyState , mediaPlayerElement.networkState)
  839. mediaWorking && Promise.resolve().then(() => {
  840. if (activeElement === document.activeElement) {
  841. return activeElement.blur()
  842. } else {
  843. return false
  844. }
  845. }).then((r) => {
  846. r !== false && mediaPlayerElement.focus();
  847. });
  848. }
  849. },
  850.  
  851.  
  852. handleGlobalKeyUp(a, b, c, d, e, f, h) {
  853.  
  854. const activeElement = document.activeElement;
  855.  
  856. const allow = typeof this.__handleGlobalKeyBefore__ === 'function' ? this.__handleGlobalKeyBefore__(a, b, c, d, e, f, h, activeElement) : void 0;
  857. if (allow === false) return false;
  858.  
  859. const ret = this.handleGlobalKeyUp91(a, b, c, d, e, f, h);
  860. // console.log('handleGlobalKeyUp',ret, a, b, c, d, e, f, h);
  861.  
  862. typeof this.__handleGlobalKeyAfter__ === 'function' && this.__handleGlobalKeyAfter__(a, b, c, d, e, f, h, activeElement, ret);
  863.  
  864. return ret;
  865. },
  866. handleGlobalKeyDown(a, b, c, d, e, f, h, l) {
  867.  
  868. const activeElement = document.activeElement;
  869. if (!isSpeedMastSpacebarControlEnabled && a === 32 && b === false && c === false && d === false && e === false && f === ' ' && h === 'Space') {
  870. return false;
  871. }
  872. const allow = typeof this.__handleGlobalKeyBefore__ === 'function' ? this.__handleGlobalKeyBefore__(a, b, c, d, e, f, h, activeElement) : void 0;
  873. if (allow === false) return false;
  874.  
  875. const ret = this.handleGlobalKeyDown91(a, b, c, d, e, f, h, l);
  876. // console.log('handleGlobalKeyDown',ret, a, b, c, d, e, f, h,l)
  877.  
  878. typeof this.__handleGlobalKeyAfter__ === 'function' && this.__handleGlobalKeyAfter__(a, b, c, d, e, f, h, activeElement, ret);
  879.  
  880. return ret;
  881. }
  882.  
  883. };
  884.  
  885. // const p_a_jt = { // API
  886.  
  887. // playVideo(a) { // without spinner effect
  888.  
  889. // if (CAN_TUNE_VOLUMN_AFTER_RESUME_OR_PAUSE) {
  890.  
  891. // const mediaPlayerElement = kRef(mediaPlayerElementWR);
  892. // if (mediaPlayerElement && !mediaPlayerElement.paused && !mediaPlayerElement.muted && mediaPlayerElement.duration > 0.01) {
  893. // want_control_video = true;
  894. // // Promise.resolve().then(()=> mediaPlayerElement.focus() );
  895. // }
  896.  
  897. // }
  898. // return this.playVideo91(a);
  899.  
  900. // },
  901.  
  902. // pauseVideo(a) { // without spinner effect
  903.  
  904. // if (CAN_TUNE_VOLUMN_AFTER_RESUME_OR_PAUSE) {
  905.  
  906. // const mediaPlayerElement = kRef(mediaPlayerElementWR);
  907. // if (mediaPlayerElement && mediaPlayerElement.paused && !mediaPlayerElement.muted && mediaPlayerElement.duration > 0.01) {
  908. // want_control_video = true;
  909. // // Promise.resolve().then(()=> mediaPlayerElement.focus() );
  910. // }
  911.  
  912. // }
  913. // return this.pauseVideo91(a);
  914.  
  915. // }
  916. // };
  917.  
  918.  
  919. const keyboardController = async (_yt_player) => {
  920.  
  921. const keyQT = getQT(_yt_player);
  922. const keySV = getSV(_yt_player);
  923. const keyDX = getDX(_yt_player);
  924. console.log(`[QT,SV,DX]`, [keyQT, keySV, keyDX]);
  925.  
  926. if (!keyDX) return;
  927. if (keyDX === keyQT || keyDX === keySV) return;
  928.  
  929. if (typeof keyDX !== 'string') return;
  930.  
  931. let lastAccessKey = '';
  932. let lastAccessKeyConfirmed = '';
  933. const mb = new Proxy({}, {
  934. get(target, prop) {
  935. if (prop === 'handleGlobalKeyUp') lastAccessKeyConfirmed = lastAccessKey;
  936. throw 'mbGet'
  937. },
  938. set(target, prop, val) {
  939. throw 'mbSet'
  940. }
  941. });
  942. const ma = new Proxy({}, {
  943. get(target, prop) {
  944. lastAccessKey = prop;
  945. return mb
  946. },
  947. set(target, prop, val) {
  948. throw 'maSet'
  949. }
  950. });
  951.  
  952. let keyBw = '';
  953. try {
  954. _yt_player[keyDX].prototype.handleGlobalKeyUp.call(ma);
  955. } catch (e) {
  956. if (e === 'mbGet' && typeof lastAccessKeyConfirmed === 'string' && lastAccessKeyConfirmed.length > 0) {
  957. keyBw = lastAccessKeyConfirmed;
  958. }
  959. }
  960.  
  961. if (!keyBw) return;
  962.  
  963. if (typeof _yt_player[keyDX].prototype.init !== 'function' || _yt_player[keyDX].prototype.init.length !== 0) return;
  964.  
  965. pm_p_a = new PromiseExternal();
  966.  
  967. _yt_player[keyDX].prototype.__cPzfo__ = keyBw;
  968.  
  969. _yt_player[keyDX].prototype.init91 = _yt_player[keyDX].prototype.init;
  970.  
  971. _yt_player[keyDX].prototype.init = p_a_init;
  972.  
  973. await pm_p_a.then();
  974. const p_a_obj = kRef(p_a_objWR);
  975.  
  976. const config = (win.yt || 0).config_ || (win.ytcfg || 0).data_ || 0;
  977. if (config && config.EXPERIMENT_FLAGS && config.EXPERIMENT_FLAGS.web_speedmaster_spacebar_control) {
  978. isSpeedMastSpacebarControlEnabled = true;
  979. }
  980. if (config && config.EXPERIMENTS_FORCED_FLAGS && config.EXPERIMENTS_FORCED_FLAGS.web_speedmaster_spacebar_control) {
  981. isSpeedMastSpacebarControlEnabled = true;
  982. }
  983.  
  984. const isSpeedMastSpacebarControlEnabledA = isSpeedMastSpacebarControlEnabled;
  985.  
  986. if (CHANGE_SPEEDMASTER_SPACEBAR_CONTROL > 0) {
  987.  
  988. isSpeedMastSpacebarControlEnabled = CHANGE_SPEEDMASTER_SPACEBAR_CONTROL == 1;
  989.  
  990. if (!isSpeedMastSpacebarControlEnabled) {
  991.  
  992. if (config && config.EXPERIMENT_FLAGS) {
  993. config.EXPERIMENT_FLAGS.web_speedmaster_spacebar_control = false;
  994. }
  995. if (config && config.EXPERIMENTS_FORCED_FLAGS) {
  996. config.EXPERIMENTS_FORCED_FLAGS.web_speedmaster_spacebar_control = false;
  997. }
  998.  
  999. } else {
  1000.  
  1001. if (config && config.EXPERIMENT_FLAGS) {
  1002. config.EXPERIMENT_FLAGS.web_speedmaster_spacebar_control = true;
  1003. }
  1004. if (config && config.EXPERIMENTS_FORCED_FLAGS) {
  1005. config.EXPERIMENTS_FORCED_FLAGS.web_speedmaster_spacebar_control = true;
  1006. }
  1007.  
  1008. }
  1009.  
  1010. }
  1011.  
  1012. const isSpeedMastSpacebarControlEnabledB = isSpeedMastSpacebarControlEnabled;
  1013.  
  1014. console.log('[yt-js-engine-tamer] speedmaster by space (yt setting)', isSpeedMastSpacebarControlEnabledA, isSpeedMastSpacebarControlEnabledB);
  1015.  
  1016. // console.log(p_a_obj.handleGlobalKeyUp)
  1017. console.log('[yt-js-engine-tamer] p_a', p_a_obj)
  1018.  
  1019. // console.log(p_a_obj.api)
  1020.  
  1021.  
  1022. // QT -> DX(SV) -> p_a
  1023.  
  1024.  
  1025. /*
  1026. *
  1027. *
  1028. g.k.handleGlobalKeyUp = function(a, b, c, d, e, f, h) {
  1029. b = void 0 === b ? !1 : b;
  1030. c = void 0 === c ? !1 : c;
  1031. d = void 0 === d ? !1 : d;
  1032. e = void 0 === e ? !1 : e;
  1033. var l = g.PT(this);
  1034. l && l.handleGlobalKeyUp(a, b, c, d, e, f, h)
  1035. }
  1036.  
  1037. */
  1038.  
  1039. /*
  1040. *
  1041. *
  1042. *
  1043. g.k.handleGlobalKeyUp = function(a, b, c, d, e, f, h) {
  1044. return this.Bw ? this.Bw.handleGlobalKeyUp(a, b, c, d, e, f, h) : !1
  1045. }
  1046.  
  1047. */
  1048.  
  1049.  
  1050. // if(!keyDX) return;
  1051.  
  1052. // console.log(4999, keyDX)
  1053.  
  1054. };
  1055.  
  1056.  
  1057. const ytResumeFn = function () { // ADVANCED_FIX_SHORTCUTKEYS
  1058.  
  1059. const p_a_obj = kRef(p_a_objWR);
  1060. // const api = p_a_obj.api;
  1061.  
  1062.  
  1063. // console.log(540);
  1064.  
  1065. let boolList = null;
  1066. let ret;
  1067. isSpaceKeyImmediate = true;
  1068. try {
  1069.  
  1070. ret = 0;
  1071. ret = ret | (p_a_obj.handleGlobalKeyDown(32, false, false, false, false, ' ', 'Space', false) ? 1 : 0);
  1072. let p_a_objT;
  1073. if (!spaceBarControl_keyG) { // just in case
  1074. boolList = new Set();
  1075. p_a_objT = new Proxy(p_a_obj, {
  1076. get(target, prop, handler) {
  1077. const val = target[prop];
  1078. if (typeof val !== 'boolean') return val;
  1079. boolList.add(prop);
  1080. // console.log(555, prop, val);
  1081. if (typeof prop === 'string' && prop.length <= 3 && val === true && boolList.length === 1) {
  1082. spaceBarControl_keyG = prop;
  1083. p_a_obj.__uZWaD__ = spaceBarControl_keyG;
  1084. val = false;
  1085. }
  1086. return val;
  1087. }
  1088. });
  1089.  
  1090.  
  1091. } else if (p_a_obj[spaceBarControl_keyG] === true) {
  1092. p_a_obj[spaceBarControl_keyG] = false;
  1093. p_a_objT = p_a_obj;
  1094. // console.log(p_a_obj, spaceBarControl_keyG, p_a_obj[spaceBarControl_keyG] )
  1095. } else {
  1096.  
  1097. p_a_objT = p_a_obj;
  1098. }
  1099.  
  1100. ret = ret | (p_a_objT.handleGlobalKeyUp(32, false, false, false, false, ' ', 'Space') ? 2 : 0);
  1101.  
  1102.  
  1103. } catch (e) {
  1104. console.log(e)
  1105. }
  1106. isSpaceKeyImmediate = false;
  1107.  
  1108. if (boolList && boolList.size === 1) {
  1109. const value = boolList.values().next().value;
  1110. spaceBarControl_keyG = value;
  1111. p_a_obj.__uZWaD__ = spaceBarControl_keyG;
  1112.  
  1113. }
  1114.  
  1115. if (spaceBarControl_keyG && p_a_obj[spaceBarControl_keyG] === true) p_a_obj[spaceBarControl_keyG] = false;
  1116.  
  1117. return ret;
  1118. }
  1119.  
  1120. const shortcutKeysFixer = () => {
  1121.  
  1122. let pausePromiseControlJ = 0;
  1123.  
  1124.  
  1125. const obtainCurrentControlPhase = (evt, mediaPlayerElement) => {
  1126.  
  1127. let controlPhase = 0;
  1128. const aElm = document.activeElement;
  1129.  
  1130. if (aElm) {
  1131.  
  1132. const controlPhaseCache = wmKeyControlPhase.get(aElm);
  1133.  
  1134. if (typeof controlPhaseCache === 'number') {
  1135.  
  1136. controlPhase = controlPhaseCache;
  1137. } else {
  1138.  
  1139. if (aElm instanceof HTMLInputElement) controlPhase = 1;
  1140. else if (aElm instanceof HTMLTextAreaElement) controlPhase = 1;
  1141. else if (aElm instanceof HTMLButtonElement) controlPhase = 2;
  1142. else if (aElm instanceof HTMLIFrameElement) controlPhase = 2;
  1143. else if (aElm instanceof HTMLImageElement) controlPhase = 2;
  1144. else if (aElm instanceof HTMLEmbedElement) controlPhase = 2;
  1145. else {
  1146. if (aElm instanceof HTMLElement && aElm.closest('[role]')) controlPhase = 5;
  1147. if (aElm instanceof HTMLDivElement) controlPhase = 2;
  1148. else if (aElm instanceof HTMLAnchorElement) controlPhase = 2;
  1149. else if (!(aElm instanceof HTMLElement) && (aElm instanceof Element)) controlPhase = 2; // svg
  1150. }
  1151.  
  1152. if ((controlPhase === 2 || controlPhase === 5) && (aElm instanceof HTMLElement) && aElm.contains(mediaPlayerElement)) {
  1153. controlPhase = 0;
  1154. }
  1155.  
  1156. if ((controlPhase === 2 || controlPhase === 5) && evt && evt.target && evt.target === aElm) {
  1157. if (aElm.closest('[contenteditable], input, textarea')) {
  1158. controlPhase = 5;
  1159. } else if (aElm.closest('button')) {
  1160. controlPhase = 4;
  1161. }
  1162. }
  1163.  
  1164. if (aElm.closest('#movie_player')) controlPhase = 6;
  1165.  
  1166. wmKeyControlPhase.set(aElm, controlPhase);
  1167.  
  1168. }
  1169. }
  1170.  
  1171. return controlPhase;
  1172.  
  1173. }
  1174.  
  1175. const isStateControllable = (api) => {
  1176. let appState = null;
  1177. let playerState = null;
  1178. let adState = null;
  1179. try {
  1180. appState = api.getAppState();
  1181. playerState = api.getPlayerState();
  1182. adState = api.getAdState();
  1183. } catch (e) { }
  1184. // ignore playerState -1
  1185. return appState === 5 && adState === -1 && (playerState === 1 || playerState === 2 || playerState === 3);
  1186. };
  1187.  
  1188.  
  1189. const keyEventListener = (evt) => {
  1190.  
  1191. if (evt.isTrusted && evt instanceof Event) lastUserAction = Date.now();
  1192. if (isSpaceKeyImmediate || !evt.isTrusted || !(evt instanceof KeyboardEvent)) return;
  1193. if (!ytPageReady) return;
  1194.  
  1195. if (evt.defaultPrevented === true) return;
  1196.  
  1197. const p_a_obj = kRef(p_a_objWR);
  1198.  
  1199. if (!p_a_obj) return;
  1200.  
  1201. const mediaPlayerElement = kRef(mediaPlayerElementWR);
  1202. if (!mediaPlayerElement) return;
  1203.  
  1204. // let focusBodyIfSuccess = false;
  1205.  
  1206. const controlPhase = obtainCurrentControlPhase(evt, mediaPlayerElement);
  1207.  
  1208. if (controlPhase === 6 && getCurrentSelectionText() !== "") void 0;
  1209. else if (controlPhase === 1 || controlPhase === 2 || controlPhase === 5) return;
  1210. else if ((controlPhase !== 6 || focusedElementAtSelection === document.activeElement) && getCurrentSelectionText() !== "") return;
  1211.  
  1212.  
  1213. // console.log(`${evt.type}::controlPhase`,controlPhase)
  1214.  
  1215. // if (controlPhase == 4) {
  1216. // focusBodyIfSuccess = true;
  1217. // }
  1218.  
  1219. spaceBarControl_keyG = spaceBarControl_keyG || p_a_obj.__uZWaD__ || ''
  1220. if (spaceBarControl_keyG && p_a_obj[spaceBarControl_keyG] === true) p_a_obj[spaceBarControl_keyG] = false;
  1221.  
  1222. if (FIX_SHORTCUTKEYS < 2) return;
  1223. if (!(!evt.shiftKey && !evt.ctrlKey && !evt.altKey && !evt.metaKey)) return; // ignore if modifier key is pressed -> let other event listener to handle first
  1224.  
  1225. let rr;
  1226. const isSpaceBar = evt.code === 'Space' && !evt.shiftKey && !evt.ctrlKey && !evt.altKey && !evt.metaKey;
  1227.  
  1228.  
  1229.  
  1230. let useImprovedPauseResume = false;
  1231.  
  1232. if (USE_IMPROVED_PAUSERESUME_UNDER_NO_SPEEDMASTER && isSpaceBar && !isSpeedMastSpacebarControlEnabled) {
  1233.  
  1234. const api = p_a_obj.api;
  1235. const stateControllable = isStateControllable(api);
  1236. // console.log(2122, appState, playerState, adState)
  1237.  
  1238. if (stateControllable && location.pathname === '/watch' && mediaPlayerElement.duration > 0.01 && (mediaPlayerElement.readyState === 4 || mediaPlayerElement.readyState === 1) && mediaPlayerElement.networkState === 2) {
  1239.  
  1240. useImprovedPauseResume = true;
  1241.  
  1242. }
  1243.  
  1244.  
  1245. }
  1246.  
  1247.  
  1248. // force flag: CHANGE_SPEEDMASTER_SPACEBAR_CONTROL
  1249. if (evt.type === 'keydown') {
  1250.  
  1251. if (useImprovedPauseResume) {
  1252.  
  1253. const isPaused = mediaPlayerElement.paused;
  1254.  
  1255. const cj = ++pausePromiseControlJ;
  1256. Promise.resolve().then(() => {
  1257.  
  1258. if (cj !== pausePromiseControlJ) return;
  1259.  
  1260. if (mediaPlayerElement.paused !== isPaused) return;
  1261.  
  1262. const ret = ytResumeFn();
  1263. if (!ret) { // fallback
  1264. isPaused ? api.playVideo() : api.pauseVideo();
  1265. }
  1266.  
  1267. /*
  1268. let a = void 0;
  1269. console.log('Rb', api.Rb())
  1270. a = !window._yt_player.nL(api.Rb());
  1271. p_a_obj.Wd.kG(a)
  1272. a ? api.playVideo() : api.pauseVideo();
  1273. */
  1274.  
  1275.  
  1276. });
  1277. rr = true;
  1278. } else {
  1279.  
  1280. isSpaceKeyImmediate = true;
  1281. rr = p_a_obj.handleGlobalKeyDown(evt.keyCode, evt.shiftKey, evt.ctrlKey, evt.altKey, evt.metaKey, evt.key, evt.code, evt.repeat);
  1282. isSpaceKeyImmediate = false;
  1283. if (spaceBarControl_keyG && p_a_obj[spaceBarControl_keyG] === true) p_a_obj[spaceBarControl_keyG] = false;
  1284.  
  1285. }
  1286.  
  1287.  
  1288. } else if (evt.type === 'keyup') {
  1289.  
  1290. if (isSpaceBar && useImprovedPauseResume && !isSpeedMastSpacebarControlEnabled) {
  1291.  
  1292. rr = true;
  1293. } else {
  1294.  
  1295. isSpaceKeyImmediate = true;
  1296. rr = p_a_obj.handleGlobalKeyUp(evt.keyCode, evt.shiftKey, evt.ctrlKey, evt.altKey, evt.metaKey, evt.key, evt.code);
  1297. isSpaceKeyImmediate = false;
  1298. if (spaceBarControl_keyG && p_a_obj[spaceBarControl_keyG] === true) p_a_obj[spaceBarControl_keyG] = false;
  1299.  
  1300. }
  1301.  
  1302.  
  1303. /*
  1304. if (d)
  1305. switch (c) {
  1306. case 32:
  1307. case 13:
  1308. if ("BUTTON" === d.tagName || "A" === d.tagName || "INPUT" === d.tagName)
  1309. b = !0,
  1310. e = !1;
  1311. else if (e) {
  1312. var m = d.getAttribute("role");
  1313. !m || "option" !== m && "button" !== m && 0 !== m.indexOf("menuitem") || (b = !0,
  1314. d.click(),
  1315. f = !0)
  1316. }
  1317. break;
  1318. case 37:
  1319. case 39:
  1320. case 36:
  1321. case 35:
  1322. b = "slider" === d.getAttribute("role");
  1323. break;
  1324. case 38:
  1325. case 40:
  1326. m = d.getAttribute("role"),
  1327. d = 38 === c ? d.previousSibling : d.nextSibling,
  1328. "slider" === m ? b = !0 : e && ("option" === m ? (d && "option" === d.getAttribute("role") && d.focus(),
  1329. f = b = !0) : m && 0 === m.indexOf("menuitem") && (d && d.hasAttribute("role") && 0 === d.getAttribute("role").indexOf("menuitem") && d.focus(),
  1330. f = b = !0))
  1331. }
  1332. if (e && !f)
  1333. switch (c) {
  1334. case 38:
  1335. f = Math.min(this.api.getVolume() + 5, 100);
  1336. XV(this.Wd, f, !1);
  1337. this.api.setVolume(f);
  1338. h = f = !0;
  1339. break;
  1340. case 40:
  1341. f = Math.max(this.api.getVolume() - 5, 0);
  1342. XV(this.Wd, f, !0);
  1343. this.api.setVolume(f);
  1344. h = f = !0;
  1345. break;
  1346. case 36:
  1347. this.api.Yh() && (this.api.startSeekCsiAction(),
  1348. this.api.seekTo(0, void 0, void 0, void 0, 79),
  1349. h = f = !0);
  1350. break;
  1351. case 35:
  1352. this.api.Yh() && (this.api.startSeekCsiAction(),
  1353. this.api.seekTo(Infinity, void 0, void 0, void 0, 80),
  1354. h = f = !0)
  1355. }
  1356. */
  1357.  
  1358. }
  1359.  
  1360.  
  1361. if (rr) {
  1362.  
  1363. // focusBodyIfSuccess && Promise.resolve().then(() => {
  1364. // activeElement === document.activeElement && activeElement.blur();
  1365. // });
  1366.  
  1367. evt.preventDefault();
  1368. evt.stopImmediatePropagation();
  1369. evt.stopPropagation();
  1370.  
  1371. }
  1372.  
  1373. };
  1374.  
  1375. document.addEventListener('keydown', keyEventListener, { capture: true });
  1376.  
  1377.  
  1378. document.addEventListener('keyup', keyEventListener, { capture: true });
  1379.  
  1380. }
  1381.  
  1382. return { pageMediaWatcher, shortcutKeysFixer, keyboardController };
  1383.  
  1384. })();
  1385.  
  1386.  
  1387. pageMediaWatcher();
  1388. FIX_SHORTCUTKEYS > 0 && shortcutKeysFixer();
  1389.  
  1390.  
  1391. const check_for_set_key_order = (() => {
  1392.  
  1393. let mySet = new Set();
  1394.  
  1395. mySet.add("value1");
  1396. mySet.add("value2");
  1397. mySet.add("value3");
  1398.  
  1399. // Function to convert Set values to an array
  1400. function getSetValues(set) {
  1401. return Array.from(set.values());
  1402. }
  1403.  
  1404. // Function to test if the Set maintains insertion order
  1405. function testSetOrder(set, expectedOrder) {
  1406. let values = getSetValues(set);
  1407. return expectedOrder.join(',') === values.join(',');
  1408. }
  1409.  
  1410. // Test 1: Initial order
  1411. if (mySet.values().next().value !== "value1") return false;
  1412. if (!testSetOrder(mySet, ["value1", "value2", "value3"])) return false;
  1413.  
  1414. // Test 2: After deleting an element
  1415. mySet.delete("value2");
  1416. if (mySet.values().next().value !== "value1") return false;
  1417. if (!testSetOrder(mySet, ["value1", "value3"])) return false;
  1418.  
  1419. // Test 3: After re-adding a deleted element
  1420. mySet.add("value2");
  1421. if (mySet.values().next().value !== "value1") return false;
  1422. if (!testSetOrder(mySet, ["value1", "value3", "value2"])) return false;
  1423.  
  1424. // Test 4: After adding a new element
  1425. mySet.add("value4");
  1426. if (mySet.values().next().value !== "value1") return false;
  1427. if (!testSetOrder(mySet, ["value1", "value3", "value2", "value4"])) return false;
  1428.  
  1429. // Test 5: Delete+Add
  1430. mySet.delete("value1");
  1431. mySet.delete("value3");
  1432. mySet.add("value3");
  1433. mySet.add("value1");
  1434. if (mySet.values().next().value !== "value2") return false;
  1435. if (!testSetOrder(mySet, ["value2", "value4", "value3", "value1"])) return false;
  1436.  
  1437. return true;
  1438. })();
  1439.  
  1440.  
  1441. // const qm47 = Symbol();
  1442. const qm57 = Symbol();
  1443. const qm53 = Symbol();
  1444. const qn53 = Symbol();
  1445.  
  1446.  
  1447. const ump3 = new WeakMap();
  1448.  
  1449. const stp = document.createElement('noscript');
  1450. stp.id = 'weakref-placeholder'
  1451.  
  1452.  
  1453. const setupD = typeof WeakRef !== 'undefined' ? (elm, s, usePlaceholder) => {
  1454.  
  1455. const z = `${s}72`;
  1456.  
  1457. if (s in elm) {
  1458.  
  1459. const p = elm[s];
  1460.  
  1461. delete elm[s];
  1462.  
  1463. Object.defineProperty(elm, s, {
  1464. get() {
  1465. const elm = this;
  1466. const wr = elm[z];
  1467. if (!wr) return null;
  1468. const m = kRef(wr);
  1469. if (!m && usePlaceholder) {
  1470. if (typeof usePlaceholder === 'function') usePlaceholder(elm);
  1471. return stp;
  1472. }
  1473. return m;
  1474. },
  1475. set(nv) {
  1476. const elm = this;
  1477. elm[z] = nv ? mWeakRef(nv) : null;
  1478. return true;
  1479. },
  1480. configurable: true,
  1481. enumerable: true
  1482.  
  1483. });
  1484.  
  1485. elm[s] = p;
  1486. elm = null;
  1487.  
  1488.  
  1489. }
  1490. } : null;
  1491.  
  1492. const mxMap = new WeakMap();
  1493.  
  1494. const myMap = new WeakSet();
  1495.  
  1496. const setup$ = typeof WeakRef !== 'undefined' ? function (dh) {
  1497.  
  1498. const $ = dh.$;
  1499.  
  1500. if (WEAK_REF_PROXY_DOLLAR && $ && typeof $ === 'object' && !dh.$ky37) {
  1501.  
  1502. dh.$ky37 = 1;
  1503.  
  1504. if (!myMap.has($)) {
  1505.  
  1506. for (const [k, v] of Object.entries($)) {
  1507. if (v instanceof Node) {
  1508. $[k] = mWeakRef(v);
  1509. }
  1510. }
  1511.  
  1512. dh.$ = mxMap.get($) || new Proxy($, {
  1513. get(obj, prop) {
  1514. const val = obj[prop];
  1515. if (typeof (val || 0).deref === 'function') {
  1516. return val.deref();
  1517. }
  1518. return val;
  1519. },
  1520. set(obj, prop, val) {
  1521. if (val instanceof Node) {
  1522. obj[prop] = mWeakRef(val);
  1523. } else {
  1524. obj[prop] = val;
  1525. }
  1526. return true;
  1527. }
  1528. });
  1529.  
  1530. mxMap.set($, dh.$);
  1531. myMap.add(dh.$);
  1532.  
  1533. }
  1534.  
  1535. }
  1536.  
  1537. } : null;
  1538.  
  1539.  
  1540. const configureVisibilityObserverT_ = function () {
  1541. const hostElement = this.hostElement;
  1542. if (!(hostElement instanceof Node) || hostElement.nodeName === 'NOSCRIPT') {
  1543. this.unobserve_();
  1544. } else {
  1545. return this.configureVisibilityObserver27_();
  1546. }
  1547. };
  1548. const getParentRendererT = function () {
  1549. const hostElement = this.hostElement;
  1550. if (!(hostElement instanceof Node) || hostElement.nodeName === 'NOSCRIPT') {
  1551. return null;
  1552. } else {
  1553. return this.getParentRenderer27();
  1554. }
  1555. }
  1556.  
  1557. const attachedT = function () {
  1558. const hostElement = this.hostElement;
  1559. if (!(hostElement instanceof Node) || hostElement.nodeName === 'NOSCRIPT') {
  1560. if (this.isAttached === true) this.isAttached = false;
  1561. return void 0;
  1562. } else {
  1563. return this.attached27();
  1564. }
  1565. }
  1566.  
  1567. const hostElementCleanUp = (dh) => {
  1568. if (typeof dh.dispose === 'function') {
  1569. try {
  1570. if (dh.visibilityMonitor || dh.visibilityObserver) {
  1571. dh.dispose();
  1572. dh.visibilityMonitor = null;
  1573. dh.visibilityObserver = null;
  1574. }
  1575. } catch (e) { }
  1576. }
  1577. if (typeof dh.detached === 'function') {
  1578. try {
  1579. if (dh.visibilityObserverForChild_ || dh.localVisibilityObserver_) {
  1580. dh.detached();
  1581. dh.visibilityObserverForChild_ = null;
  1582. dh.localVisibilityObserver_ = null;
  1583. }
  1584. } catch (e) { }
  1585. }
  1586. };
  1587. const setupDataHost = setupD && setup$ ? function (dh, opt) {
  1588.  
  1589. if (dh && typeof dh === 'object') {
  1590.  
  1591. if (typeof dh.configureVisibilityObserver_ === 'function' && !dh.configureVisibilityObserver27_) {
  1592. dh.configureVisibilityObserver27_ = dh.configureVisibilityObserver_;
  1593. dh.configureVisibilityObserver_ = configureVisibilityObserverT_;
  1594. }
  1595.  
  1596. if (typeof dh.getParentRenderer === 'function' && !dh.getParentRenderer27) {
  1597. dh.getParentRenderer27 = dh.getParentRenderer;
  1598. dh.getParentRenderer = getParentRendererT;
  1599. }
  1600.  
  1601. if (typeof dh.attached === 'function' && !dh.attached27) {
  1602. dh.attached27 = dh.attached;
  1603. dh.attached = attachedT;
  1604. }
  1605.  
  1606. setupD(dh, 'hostElement', hostElementCleanUp);
  1607. setupD(dh, 'parentComponent');
  1608. setupD(dh, 'localVisibilityObserver_');
  1609. setupD(dh, 'cachedProviderNode_');
  1610.  
  1611.  
  1612. setupD(dh, '__template');
  1613. setupD(dh, '__templatizeOwner');
  1614. setupD(dh, '__templateInfo');
  1615.  
  1616. // setupD(dh, 'root', 1);
  1617.  
  1618. const elements_ = dh.elements_;
  1619. if (elements_ && typeof elements_ === 'object' && Object.keys(elements_).length > 0) setupD(dh, 'elements_');
  1620.  
  1621. setup$(dh);
  1622. }
  1623.  
  1624.  
  1625.  
  1626.  
  1627. } : null;
  1628.  
  1629.  
  1630. let delay300 = null;
  1631.  
  1632. if (UNLOAD_DETACHED_POLYMER || WEAK_REF_BINDING) {
  1633. delay300 = new PromiseExternal();
  1634. setInterval(() => {
  1635. delay300.resolve();
  1636. delay300 = new PromiseExternal();
  1637. }, 300);
  1638. }
  1639.  
  1640. const aDelay = async function () {
  1641. await delay300.then();
  1642. await delay300.then();
  1643. }
  1644.  
  1645. const convertionFuncMap = new WeakMap();
  1646. let val_kevlar_should_maintain_stable_list = null;
  1647.  
  1648. const createStampDomArrayFn_ = (fn) => {
  1649. if (val_kevlar_should_maintain_stable_list === null) {
  1650. const config_ = ((window.yt || 0).config_ || 0);
  1651. val_kevlar_should_maintain_stable_list = ((config_ || 0).EXPERIMENT_FLAGS || 0).kevlar_should_maintain_stable_list === true
  1652. }
  1653. const gn = function (a, b, c, d, e, h) {
  1654. const isNonEmptyArray = (a || 0).length >= 1
  1655. if (!isNonEmptyArray) {
  1656. return fn.call(this, undefined, b, undefined, d);
  1657. } else if (h === undefined && typeof b === 'string' && c && typeof c === 'object' && this.is && val_kevlar_should_maintain_stable_list) {
  1658. if (c.clientSideToggleMenuItemRenderer) {
  1659. h = false;
  1660. } else {
  1661. h = true;
  1662. }
  1663. }
  1664. return fn.call(this, a, b, c, d, e, h)
  1665. }
  1666. gn.originalFn = fn;
  1667. convertionFuncMap.set(fn, gn);
  1668. return gn;
  1669. }
  1670.  
  1671. const fixStampDomArrayStableList = (h) => {
  1672. if (!h.stampDomArray_) return;
  1673. const proto = h.__proto__;
  1674. const f = proto.stampDomArray_;
  1675. if (!proto.stampDomArrayF001_ && typeof f === 'function' && f.length === 6) {
  1676. proto.stampDomArrayF001_ = 1;
  1677. proto.stampDomArray_ = convertionFuncMap.get(f) || createStampDomArrayFn_(f);
  1678. }
  1679. }
  1680.  
  1681. const weakenStampReferences = (() => {
  1682.  
  1683. const DEBUG_STAMP = false;
  1684.  
  1685. const s1 = Symbol();
  1686. const handler1 = {
  1687. get(target, prop, receiver) {
  1688. if (prop === 'object') {
  1689. return kRef(target[s1]); // avoid memory leakage
  1690. }
  1691. if (prop === '__proxy312__') return 1;
  1692. return target[prop];
  1693. }
  1694. };
  1695. const handler2 = {
  1696. get(target, prop, receiver) {
  1697. if (prop === 'indexSplices') {
  1698. return kRef(target[s1]); // avoid memory leakage
  1699. }
  1700. if (prop === '__proxy312__') return 1;
  1701. return target[prop];
  1702. }
  1703. }
  1704. return (h) => {
  1705.  
  1706. if (h.rendererStamperApplyChangeRecord_ || h.stampDomArraySplices_) {
  1707. const proto = h.__proto__;
  1708. if (!proto.yzxer && (proto.rendererStamperApplyChangeRecord_ || proto.stampDomArraySplices_)) {
  1709. proto.yzxer = 1;
  1710.  
  1711. const list = [
  1712. // "rendererStamperObserver_", // 3 ==> rendererStamperApplyChangeRecord_
  1713. "rendererStamperApplyChangeRecord_", // 3
  1714. "forwardRendererStamperChanges_", // 3
  1715. "stampDomArraySplices_", // 3
  1716. "stampDomArray_", // 6
  1717. "deferRenderStamperBinding_", // 3
  1718. ];
  1719. for (const key of list) {
  1720. const pey = `${key}$wq0iw_`;
  1721. const vKey = proto[key];
  1722. if (typeof vKey !== 'function') continue;
  1723. if (proto[pey] || vKey.length === 0) continue;
  1724.  
  1725. if (key === 'stampDomArraySplices_' && vKey.length === 3) {
  1726. proto[pey] = vKey;
  1727. proto[key] = function (a, b, c) {
  1728.  
  1729. if (typeof a === 'string' && typeof b === 'string' && typeof c === 'object' && c && c.indexSplices && c.indexSplices.length >= 1 && !c.indexSplices.rzgjr) {
  1730.  
  1731. c.indexSplices = c.indexSplices.map(e => {
  1732. if (e.__proxy312__) return e;
  1733. e[s1] = mWeakRef(e.object);
  1734. e.object = null;
  1735. return new Proxy(e, handler1);
  1736. });
  1737. c.indexSplices.rzgjr = 1;
  1738.  
  1739. c[s1] = mWeakRef(c.indexSplices);
  1740. c.indexSplices = null;
  1741. c = new Proxy(c, handler2)
  1742. arguments[2] = c;
  1743.  
  1744. }
  1745. // console.log(key, arguments.length, [...arguments]);
  1746. return proto[pey].call(this, a, b, c);
  1747. }
  1748.  
  1749. } else if (key === 'rendererStamperApplyChangeRecord_' && vKey.length === 3) {
  1750.  
  1751. // Nil
  1752.  
  1753. } else if (DEBUG_STAMP) {
  1754.  
  1755. console.log(proto.isRenderer_, 'ms_' + key, vKey.length, h.is)
  1756. proto[pey] = vKey;
  1757. proto[key] = function () {
  1758. if (key === 'rendererStamperApplyChangeRecord_' && typeof arguments[3] === 'object') {
  1759. console.log(key, arguments.length, { value: arguments[3].value, base: arguments[3].base, })
  1760. }
  1761. console.log(key, arguments.length, [...arguments]);
  1762. return proto[pey].apply(this, arguments);
  1763. }
  1764.  
  1765. }
  1766.  
  1767. }
  1768.  
  1769.  
  1770. // const m = (Object.mkss = Object.mkss || new Set());
  1771. // Object.keys(h.__proto__).filter(e => e.toLowerCase().includes('stamp') && typeof h[e] === 'function').forEach(e => m.add(e))
  1772. // console.log([...m])
  1773. }
  1774. }
  1775.  
  1776. }
  1777. })();
  1778.  
  1779. const setupDiscreteTasks = (h, rb) => {
  1780.  
  1781. if (rb) {
  1782. if (h.ky36) return;
  1783. }
  1784.  
  1785.  
  1786. if (typeof h.onYtRendererstamperFinished === 'function' && !(h.onYtRendererstamperFinished.km34)) {
  1787. const f = h.onYtRendererstamperFinished;
  1788. const g = ump3.get(f) || function () {
  1789. if (this.updateChildVisibilityProperties && !this.markDirty) {
  1790. return f.apply(this, arguments);
  1791. }
  1792. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  1793. }
  1794. ump3.set(f, g);
  1795. g.km34 = 1;
  1796. h.onYtRendererstamperFinished = g;
  1797.  
  1798. }
  1799.  
  1800. if (typeof h.onYtUpdateDescriptionAction === 'function' && !(h.onYtUpdateDescriptionAction.km34)) {
  1801. const f = h.onYtUpdateDescriptionAction;
  1802. const g = ump3.get(f) || function (a) {
  1803. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  1804. }
  1805. ump3.set(f, g);
  1806. g.km34 = 1;
  1807. h.onYtUpdateDescriptionAction = g;
  1808.  
  1809. }
  1810.  
  1811. if (typeof h.handleUpdateDescriptionAction === 'function' && !(h.handleUpdateDescriptionAction.km34)) {
  1812. const f = h.handleUpdateDescriptionAction;
  1813. const g = ump3.get(f) || function (a) {
  1814. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  1815. }
  1816. ump3.set(f, g);
  1817. g.km34 = 1;
  1818. h.handleUpdateDescriptionAction = g;
  1819.  
  1820. }
  1821.  
  1822. if (typeof h.handleUpdateLiveChatPollAction === 'function' && !(h.handleUpdateLiveChatPollAction.km34)) {
  1823. const f = h.handleUpdateLiveChatPollAction;
  1824. const g = ump3.get(f) || function (a) {
  1825. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  1826. }
  1827. ump3.set(f, g);
  1828. g.km34 = 1;
  1829. h.handleUpdateLiveChatPollAction = g;
  1830.  
  1831. }
  1832.  
  1833. if (typeof h.onTextChanged === 'function' && !(h.onTextChanged.km34)) {
  1834. const f = h.onTextChanged;
  1835. const g = ump3.get(f) || function () {
  1836. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  1837. }
  1838. ump3.set(f, g);
  1839. g.km34 = 1;
  1840. h.onTextChanged = g;
  1841.  
  1842. }
  1843.  
  1844. if (typeof h.onVideoDataChange === 'function' && !(h.onVideoDataChange.km34)) {
  1845. const f = h.onVideoDataChange;
  1846. const g = ump3.get(f) || function (a) {
  1847. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  1848. }
  1849. ump3.set(f, g);
  1850. g.km34 = 1;
  1851. h.onVideoDataChange = g;
  1852.  
  1853. }
  1854.  
  1855. if (typeof h.onVideoDataChange_ === 'function' && !(h.onVideoDataChange_.km34)) {
  1856. const f = h.onVideoDataChange_;
  1857. const g = ump3.get(f) || function () {
  1858. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  1859. }
  1860. ump3.set(f, g);
  1861. g.km34 = 1;
  1862. h.onVideoDataChange_ = g;
  1863.  
  1864. }
  1865.  
  1866. if (typeof h.addTooltips === 'function' && !(h.addTooltips.km34)) {
  1867.  
  1868. const f = h.addTooltips;
  1869. const g = ump3.get(f) || function () {
  1870. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  1871. }
  1872. ump3.set(f, g);
  1873. g.km34 = 1;
  1874. h.addTooltips = g;
  1875.  
  1876. }
  1877.  
  1878. if (typeof h.addTooltips_ === 'function' && !(h.addTooltips_.km34)) {
  1879.  
  1880. const f = h.addTooltips_;
  1881. const g = ump3.get(f) || function () {
  1882. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  1883. }
  1884. ump3.set(f, g);
  1885. g.km34 = 1;
  1886. h.addTooltips_ = g;
  1887.  
  1888. }
  1889.  
  1890. if (typeof h.updateRenderedElements === 'function' && !(h.updateRenderedElements.km34)) {
  1891.  
  1892. const f = h.updateRenderedElements;
  1893. const g = ump3.get(f) || function () {
  1894. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  1895. }
  1896. ump3.set(f, g);
  1897. g.km34 = 1;
  1898. h.updateRenderedElements = g;
  1899.  
  1900. }
  1901.  
  1902. if (typeof h.loadPage_ === 'function' && !(h.loadPage_.km34)) {
  1903. const f = h.loadPage_;
  1904. const g = ump3.get(f) || function (a) {
  1905. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  1906. }
  1907. ump3.set(f, g);
  1908. g.km34 = 1;
  1909. h.loadPage_ = g;
  1910.  
  1911. }
  1912. if (typeof h.updatePageData_ === 'function' && !(h.updatePageData_.km34)) {
  1913. const f = h.updatePageData_;
  1914. const g = ump3.get(f) || function (a) {
  1915. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  1916. }
  1917. ump3.set(f, g);
  1918. g.km34 = 1;
  1919. h.updatePageData_ = g;
  1920.  
  1921. }
  1922.  
  1923. if (typeof h.onFocus_ === 'function' && !(h.onFocus_.km34)) {
  1924.  
  1925. const f = h.onFocus_;
  1926. const g = ump3.get(f) || function () {
  1927. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  1928. }
  1929. ump3.set(f, g);
  1930. g.km34 = 1;
  1931. h.onFocus_ = g;
  1932.  
  1933. }
  1934.  
  1935. if (typeof h.onBlur_ === 'function' && !(h.onBlur_.km34)) {
  1936.  
  1937. const f = h.onBlur_;
  1938. const g = ump3.get(f) || function () {
  1939. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  1940. }
  1941. ump3.set(f, g);
  1942. g.km34 = 1;
  1943. h.onBlur_ = g;
  1944.  
  1945. }
  1946.  
  1947. if (typeof h.buttonClassChanged_ === 'function' && !(h.buttonClassChanged_.km34)) {
  1948.  
  1949. const f = h.buttonClassChanged_;
  1950. const g = ump3.get(f) || function (a, b) {
  1951. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  1952. }
  1953. ump3.set(f, g);
  1954. g.km34 = 1;
  1955. h.buttonClassChanged_ = g;
  1956.  
  1957. }
  1958.  
  1959. if (typeof h.buttonIconChanged_ === 'function' && !(h.buttonIconChanged_.km34)) {
  1960.  
  1961. const f = h.buttonIconChanged_;
  1962. const g = ump3.get(f) || function (a) {
  1963. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  1964. }
  1965. ump3.set(f, g);
  1966. g.km34 = 1;
  1967. h.buttonIconChanged_ = g;
  1968.  
  1969. }
  1970.  
  1971. if (typeof h.dataChangedInBehavior_ === 'function' && !(h.dataChangedInBehavior_.km34)) {
  1972.  
  1973. const f = h.dataChangedInBehavior_;
  1974. const g = ump3.get(f) || function () {
  1975. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  1976. }
  1977. ump3.set(f, g);
  1978. g.km34 = 1;
  1979. h.dataChangedInBehavior_ = g;
  1980.  
  1981. }
  1982.  
  1983. if (typeof h.continuationsChanged_ === 'function' && !(h.continuationsChanged_.km34)) {
  1984.  
  1985. const f = h.continuationsChanged_;
  1986. const g = ump3.get(f) || function () {
  1987. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  1988. }
  1989. ump3.set(f, g);
  1990. g.km34 = 1;
  1991. h.continuationsChanged_ = g;
  1992.  
  1993. }
  1994.  
  1995. if (typeof h.forceChatPoll_ === 'function' && !(h.forceChatPoll_.km34)) {
  1996.  
  1997. const f = h.forceChatPoll_;
  1998. const g = ump3.get(f) || function (a) {
  1999. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  2000. }
  2001. ump3.set(f, g);
  2002. g.km34 = 1;
  2003. h.forceChatPoll_ = g;
  2004.  
  2005. }
  2006.  
  2007. if (typeof h.onEndpointClick_ === 'function' && !(h.onEndpointClick_.km34)) {
  2008.  
  2009. const f = h.onEndpointClick_;
  2010. const g = ump3.get(f) || function (a) {
  2011. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  2012. }
  2013. ump3.set(f, g);
  2014. g.km34 = 1;
  2015. h.onEndpointClick_ = g;
  2016.  
  2017. }
  2018.  
  2019. if (typeof h.onEndpointTap_ === 'function' && !(h.onEndpointTap_.km34)) {
  2020.  
  2021. const f = h.onEndpointTap_;
  2022. const g = ump3.get(f) || function (a) {
  2023. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  2024. }
  2025. ump3.set(f, g);
  2026. g.km34 = 1;
  2027. h.onEndpointTap_ = g;
  2028.  
  2029. }
  2030.  
  2031. if (typeof h.handleClick_ === 'function' && !(h.handleClick_.km34)) {
  2032.  
  2033. const f = h.handleClick_;
  2034. const g = ump3.get(f) || function (a, b) {
  2035. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  2036. }
  2037. ump3.set(f, g);
  2038. g.km34 = 1;
  2039. h.handleClick_ = g;
  2040.  
  2041. }
  2042.  
  2043. if (typeof h.onReadyStateChange_ === 'function' && !(h.onReadyStateChange_.km34)) {
  2044.  
  2045. const f = h.onReadyStateChange_;
  2046. const g = ump3.get(f) || function () {
  2047. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  2048. }
  2049. ump3.set(f, g);
  2050. g.km34 = 1;
  2051. h.onReadyStateChange_ = g;
  2052.  
  2053. }
  2054.  
  2055. if (typeof h.onReadyStateChangeEntryPoint_ === 'function' && !(h.onReadyStateChangeEntryPoint_.km34)) {
  2056.  
  2057. const f = h.onReadyStateChangeEntryPoint_;
  2058. const g = ump3.get(f) || function () {
  2059. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  2060. }
  2061. ump3.set(f, g);
  2062. g.km34 = 1;
  2063. h.onReadyStateChangeEntryPoint_ = g;
  2064.  
  2065. }
  2066.  
  2067. if (typeof h.readyStateChangeHandler_ === 'function' && !(h.readyStateChangeHandler_.km34)) {
  2068.  
  2069. const f = h.readyStateChangeHandler_;
  2070. const g = ump3.get(f) || function (a) {
  2071. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  2072. }
  2073. ump3.set(f, g);
  2074. g.km34 = 1;
  2075. h.readyStateChangeHandler_ = g;
  2076.  
  2077. }
  2078.  
  2079. if (typeof h.xmlHttpHandler_ === 'function' && !(h.xmlHttpHandler_.km34)) {
  2080.  
  2081. const f = h.xmlHttpHandler_;
  2082. const g = ump3.get(f) || function (a) {
  2083. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  2084. }
  2085. ump3.set(f, g);
  2086. g.km34 = 1;
  2087. h.xmlHttpHandler_ = g;
  2088.  
  2089. }
  2090.  
  2091. if (typeof h.executeCallbacks_ === 'function' && !(h.executeCallbacks_.km34)) {
  2092.  
  2093. const f = h.executeCallbacks_; // overloaded
  2094. const g = ump3.get(f) || function (a) {
  2095. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  2096. }
  2097. ump3.set(f, g);
  2098. g.km34 = 1;
  2099. h.executeCallbacks_ = g;
  2100.  
  2101. }
  2102.  
  2103. if (typeof h.handleInvalidationData_ === 'function' && !(h.handleInvalidationData_.km34)) {
  2104.  
  2105. const f = h.handleInvalidationData_;
  2106. const g = ump3.get(f) || function (a, b) {
  2107. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  2108. }
  2109. ump3.set(f, g);
  2110. g.km34 = 1;
  2111. h.handleInvalidationData_ = g;
  2112.  
  2113. }
  2114.  
  2115. if (typeof h.onInput_ === 'function' && !(h.onInput_.km34)) {
  2116.  
  2117. const f = h.onInput_;
  2118. const g = ump3.get(f) || function () {
  2119. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  2120. }
  2121. ump3.set(f, g);
  2122. g.km34 = 1;
  2123. h.onInput_ = g;
  2124.  
  2125. }
  2126.  
  2127. if (typeof h.trigger_ === 'function' && !(h.trigger_.km34)) {
  2128.  
  2129. const f = h.trigger_;
  2130. const g = ump3.get(f) || function (a) {
  2131. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  2132. }
  2133. ump3.set(f, g);
  2134. g.km34 = 1;
  2135. h.trigger_ = g;
  2136.  
  2137. }
  2138.  
  2139. if (typeof h.requestData_ === 'function' && !(h.requestData_.km34)) {
  2140.  
  2141. const f = h.requestData_;
  2142. const g = ump3.get(f) || function (a) {
  2143. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  2144. }
  2145. ump3.set(f, g);
  2146. g.km34 = 1;
  2147. h.requestData_ = g;
  2148.  
  2149. }
  2150.  
  2151. if (typeof h.onLoadReloadContinuation_ === 'function' && !(h.onLoadReloadContinuation_.km34)) {
  2152.  
  2153. const f = h.onLoadReloadContinuation_;
  2154. const g = ump3.get(f) || function (a, b) {
  2155. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  2156. }
  2157. ump3.set(f, g);
  2158. g.km34 = 1;
  2159. h.onLoadReloadContinuation_ = g;
  2160.  
  2161. }
  2162.  
  2163. if (typeof h.onLoadIncrementalContinuation_ === 'function' && !(h.onLoadIncrementalContinuation_.km34)) {
  2164.  
  2165. const f = h.onLoadIncrementalContinuation_;
  2166. const g = ump3.get(f) || function (a, b) {
  2167. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  2168. }
  2169. ump3.set(f, g);
  2170. g.km34 = 1;
  2171. h.onLoadIncrementalContinuation_ = g;
  2172.  
  2173. }
  2174.  
  2175. if (typeof h.onLoadSeekContinuation_ === 'function' && !(h.onLoadSeekContinuation_.km34)) {
  2176.  
  2177. const f = h.onLoadSeekContinuation_;
  2178. const g = ump3.get(f) || function (a, b) {
  2179. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  2180. }
  2181. ump3.set(f, g);
  2182. g.km34 = 1;
  2183. h.onLoadSeekContinuation_ = g;
  2184.  
  2185. }
  2186. if (typeof h.onLoadReplayContinuation_ === 'function' && !(h.onLoadReplayContinuation_.km34)) {
  2187.  
  2188. const f = h.onLoadReplayContinuation_;
  2189. const g = ump3.get(f) || function (a, b) {
  2190. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  2191. }
  2192. ump3.set(f, g);
  2193. g.km34 = 1;
  2194. h.onLoadReplayContinuation_ = g;
  2195.  
  2196. }
  2197. if (typeof h.onNavigate_ === 'function' && !(h.onNavigate_.km34)) {
  2198.  
  2199. const f = h.onNavigate_;
  2200. const g = ump3.get(f) || function (a) {
  2201. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  2202. }
  2203. ump3.set(f, g);
  2204. g.km34 = 1;
  2205. h.onNavigate_ = g;
  2206.  
  2207. }
  2208.  
  2209. if (typeof h.ytRendererBehaviorDataObserver_ === 'function' && !(h.ytRendererBehaviorDataObserver_.km34)) {
  2210.  
  2211. const f = h.ytRendererBehaviorDataObserver_;
  2212. const g = ump3.get(f) || function () {
  2213. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  2214. }
  2215. ump3.set(f, g);
  2216. g.km34 = 1;
  2217. h.ytRendererBehaviorDataObserver_ = g;
  2218.  
  2219. }
  2220.  
  2221. if (typeof h.ytRendererBehaviorTargetIdObserver_ === 'function' && !(h.ytRendererBehaviorTargetIdObserver_.km34)) {
  2222.  
  2223. const f = h.ytRendererBehaviorTargetIdObserver_;
  2224. const g = ump3.get(f) || function () {
  2225. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  2226. }
  2227. ump3.set(f, g);
  2228. g.km34 = 1;
  2229. h.ytRendererBehaviorTargetIdObserver_ = g;
  2230.  
  2231. }
  2232.  
  2233. if (typeof h.unregisterRenderer_ === 'function' && !(h.unregisterRenderer_.km34)) {
  2234.  
  2235. const f = h.unregisterRenderer_;
  2236. const g = ump3.get(f) || function (a) {
  2237. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  2238. }
  2239. ump3.set(f, g);
  2240. g.km34 = 1;
  2241. h.unregisterRenderer_ = g;
  2242.  
  2243. }
  2244.  
  2245. if (typeof h.textChanged_ === 'function' && !(h.textChanged_.km34)) {
  2246.  
  2247. const f = h.textChanged_;
  2248. const g = ump3.get(f) || function (a) {
  2249. if (void 0 !== this.isAttached) {
  2250. const hostElement = this.hostElement;
  2251. if (!(hostElement instanceof Node) || hostElement.nodeName === 'NOSCRIPT') {
  2252. return;
  2253. }
  2254. }
  2255. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  2256. }
  2257. ump3.set(f, g);
  2258. g.km34 = 1;
  2259. h.textChanged_ = g;
  2260.  
  2261. }
  2262.  
  2263.  
  2264. /**
  2265. *
  2266. * Neglect following
  2267. *
  2268. * h.onYtAction_
  2269. * h.startLoadingWatch [ buggy for yt-player-updated ]
  2270. * h.deferRenderStamperBinding_
  2271. *
  2272. * h.stampDomArray_
  2273. * h.stampDomArraySplices_
  2274. *
  2275. */
  2276.  
  2277.  
  2278. // RP.prototype.searchChanged_ = RP.prototype.searchChanged_;
  2279. // RP.prototype.skinToneChanged_ = RP.prototype.skinToneChanged_;
  2280. // RP.prototype.onEmojiHover_ = RP.prototype.onEmojiHover_;
  2281. // RP.prototype.onSelectCategory_ = RP.prototype.onSelectCategory_;
  2282. // RP.prototype.onShowEmojiVariantSelector = RP.prototype.onShowEmojiVariantSelector;
  2283. // RP.prototype.updateCategoriesAndPlaceholder_ = RP.prototype.updateCategoriesAndPlaceholder_;
  2284.  
  2285. if (typeof h.searchChanged_ === 'function' && !(h.searchChanged_.km34)) {
  2286.  
  2287. const f = h.searchChanged_;
  2288. const g = ump3.get(f) || function () {
  2289. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  2290. }
  2291. ump3.set(f, g);
  2292. g.km34 = 1;
  2293. h.searchChanged_ = g;
  2294.  
  2295. }
  2296.  
  2297. if (typeof h.skinToneChanged_ === 'function' && !(h.skinToneChanged_.km34)) {
  2298.  
  2299. const f = h.skinToneChanged_;
  2300. const g = ump3.get(f) || function (a) {
  2301. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  2302. }
  2303. ump3.set(f, g);
  2304. g.km34 = 1;
  2305. h.skinToneChanged_ = g;
  2306.  
  2307. }
  2308.  
  2309. if (typeof h.onEmojiHover_ === 'function' && !(h.onEmojiHover_.km34)) {
  2310.  
  2311. const f = h.onEmojiHover_;
  2312. const g = ump3.get(f) || function (a) {
  2313. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  2314. }
  2315. ump3.set(f, g);
  2316. g.km34 = 1;
  2317. h.onEmojiHover_ = g;
  2318.  
  2319. }
  2320.  
  2321. if (typeof h.onSelectCategory_ === 'function' && !(h.onSelectCategory_.km34)) {
  2322.  
  2323. const f = h.onSelectCategory_;
  2324. const g = ump3.get(f) || function (a) {
  2325. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  2326. }
  2327. ump3.set(f, g);
  2328. g.km34 = 1;
  2329. h.onSelectCategory_ = g;
  2330.  
  2331. }
  2332.  
  2333. if (typeof h.onShowEmojiVariantSelector === 'function' && !(h.onShowEmojiVariantSelector.km34)) {
  2334.  
  2335. const f = h.onShowEmojiVariantSelector;
  2336. const g = ump3.get(f) || function (a) {
  2337. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  2338. }
  2339. ump3.set(f, g);
  2340. g.km34 = 1;
  2341. h.onShowEmojiVariantSelector = g;
  2342.  
  2343. }
  2344.  
  2345. if (typeof h.updateCategoriesAndPlaceholder_ === 'function' && !(h.updateCategoriesAndPlaceholder_.km34)) {
  2346.  
  2347. const f = h.updateCategoriesAndPlaceholder_;
  2348. const g = ump3.get(f) || function () {
  2349. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  2350. }
  2351. ump3.set(f, g);
  2352. g.km34 = 1;
  2353. h.updateCategoriesAndPlaceholder_ = g;
  2354.  
  2355. }
  2356.  
  2357. if (typeof h.watchPageActiveChanged_ === 'function' && !(h.watchPageActiveChanged_.km34)) {
  2358.  
  2359. const f = h.watchPageActiveChanged_;
  2360. const g = ump3.get(f) || function () {
  2361. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  2362. }
  2363. ump3.set(f, g);
  2364. g.km34 = 1;
  2365. h.watchPageActiveChanged_ = g;
  2366.  
  2367. }
  2368.  
  2369. if (typeof h.activate_ === 'function' && !(h.activate_.km34)) {
  2370.  
  2371. const f = h.activate_;
  2372. const g = ump3.get(f) || function () {
  2373. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  2374. }
  2375. ump3.set(f, g);
  2376. g.km34 = 1;
  2377. h.activate_ = g;
  2378.  
  2379. }
  2380. if (typeof h.onYtPlaylistDataUpdated_ === 'function' && !(h.onYtPlaylistDataUpdated_.km34)) {
  2381.  
  2382. const f = h.onYtPlaylistDataUpdated_;
  2383. const g = ump3.get(f) || function () {
  2384. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  2385. }
  2386. ump3.set(f, g);
  2387. g.km34 = 1;
  2388. h.onYtPlaylistDataUpdated_ = g;
  2389.  
  2390. }
  2391.  
  2392. FIX_stampDomArray_stableList && fixStampDomArrayStableList(h);
  2393. const ENABLE_weakenStampReferencesQ = ENABLE_weakenStampReferences && typeof DocumentTimeline !== 'undefined' && typeof WeakRef !== 'undefined';
  2394. ENABLE_weakenStampReferencesQ && weakenStampReferences(h);
  2395.  
  2396.  
  2397. /**
  2398. *
  2399. * Neglect following
  2400. *
  2401. * h.rendererStamperObserver_
  2402. * h.rendererStamperApplyChangeRecord_
  2403. * h.flushRenderStamperComponentBindings_
  2404. * h.forwardRendererStamperChanges_
  2405. *
  2406. */
  2407.  
  2408. if (typeof h.tryRenderChunk_ === 'function' && !(h.tryRenderChunk_.km34)) {
  2409.  
  2410. const f = h.tryRenderChunk_;
  2411. const g = ump3.get(f) || function () {
  2412. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  2413. }
  2414. ump3.set(f, g);
  2415. g.km34 = 1;
  2416. h.tryRenderChunk_ = g;
  2417.  
  2418. }
  2419.  
  2420.  
  2421. if (typeof h.renderChunk_ === 'function' && !(h.renderChunk_.km34)) {
  2422.  
  2423. const f = h.renderChunk_;
  2424. const g = ump3.get(f) || function () {
  2425. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  2426. }
  2427. ump3.set(f, g);
  2428. g.km34 = 1;
  2429. h.renderChunk_ = g;
  2430.  
  2431. }
  2432.  
  2433. if (typeof h.deepLazyListObserver_ === 'function' && !(h.deepLazyListObserver_.km34)) {
  2434.  
  2435. const f = h.deepLazyListObserver_;
  2436. const g = ump3.get(f) || function () {
  2437. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  2438. }
  2439. ump3.set(f, g);
  2440. g.km34 = 1;
  2441. h.deepLazyListObserver_ = g;
  2442.  
  2443. }
  2444.  
  2445. if (typeof h.onItemsUpdated_ === 'function' && !(h.onItemsUpdated_.km34)) {
  2446.  
  2447. const f = h.onItemsUpdated_;
  2448. const g = ump3.get(f) || function () {
  2449. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  2450. }
  2451. ump3.set(f, g);
  2452. g.km34 = 1;
  2453. h.onItemsUpdated_ = g;
  2454.  
  2455. }
  2456.  
  2457. if (typeof h.requestRenderChunk_ === 'function' && !(h.requestRenderChunk_.km34)) {
  2458.  
  2459. const f = h.requestRenderChunk_;
  2460. const g = ump3.get(f) || function () {
  2461. Promise.resolve().then(() => f.apply(this, arguments)).catch(console.log);
  2462. }
  2463. ump3.set(f, g);
  2464. g.km34 = 1;
  2465. h.requestRenderChunk_ = g;
  2466.  
  2467. }
  2468.  
  2469. /**
  2470. *
  2471. * Neglect following
  2472. *
  2473. * h.dataChanged_ [ buggy for page swtiching ]
  2474. *
  2475. * h.updateChangeRecord_ [ see https://github.com/cyfung1031/userscript-supports/issues/20 ]
  2476. *
  2477. * h.cancelPendingTasks_
  2478. * h.fillRange_
  2479. * h.addTextNodes_
  2480. * h.updateText_
  2481. * h.stampTypeChanged_
  2482. *
  2483. */
  2484.  
  2485.  
  2486. }
  2487.  
  2488. const keyStConnectedCallback = Symbol(); // avoid copying the value
  2489.  
  2490. // const keyStDisconnectedCallback = Symbol(); // avoid copying the value
  2491. const cmf = new WeakMap();
  2492. const dmf = new WeakMap();
  2493.  
  2494. const gvGenerator = (nv) => {
  2495. return function () {
  2496. const cnt = insp(this);
  2497. const hostElement = cnt.hostElement || 0;
  2498. const dollar = hostElement ? (this.$ || indr(this)) : 0;
  2499. let p = (hostElement instanceof HTMLElement) && (dollar || !this.is);
  2500. if (p && (!dollar && !this.is)) {
  2501. const nodeName = hostElement.nodeName;
  2502. if (typeof nodeName !== 'string') {
  2503. // just in case
  2504. } else if (nodeName.startsWith("DOM-")) {
  2505. // dom-if, dom-repeat, etc
  2506. } else {
  2507. // yt element - new model, yt-xxxx, anixxxxxx
  2508. p = false;
  2509. }
  2510. }
  2511. if (p) {
  2512. if (typeof cnt.markDirty === 'function') {
  2513. // the yt element might call markDirty (occasionally)
  2514. p = false;
  2515. } else if (this.is === 'ytd-engagement-panel-section-list-renderer') {
  2516. // see https://github.com/cyfung1031/userscript-supports/issues/20
  2517. p = false;
  2518. }
  2519. }
  2520. if (p) {
  2521.  
  2522. // << dom-repeat & dom-if >>
  2523.  
  2524. // sequence on the same instance
  2525. this[qm57] = (this[qm57] || Promise.resolve()).then(() => nv.apply(this, arguments)).catch(console.log);
  2526. } else {
  2527. nv.apply(this, arguments);
  2528. }
  2529. };
  2530. }
  2531.  
  2532. const setupWeakRef = (h) => {
  2533.  
  2534.  
  2535. if (WEAK_REF_BINDING && !h.kz62 && setup$ && setupD && setupDataHost && (h.is || h.__dataHost)) {
  2536.  
  2537. let skip = false;
  2538. // if (h.is && typeof h.is === 'string' && h.is.length > 15 && h.is.length < 30) {
  2539. // if (h.is.includes('yt-') && !h.$ && h.is.length !== 20 && h.is.length !== 21 && h.is.length !== 22) {
  2540. // skip = true;
  2541. // // return;
  2542. // }
  2543. // }
  2544.  
  2545. h.kz62 = 1;
  2546.  
  2547. //
  2548.  
  2549. setup$(h);
  2550. const hostElement = h.hostElement;
  2551.  
  2552. if (hostElement !== h) {
  2553.  
  2554. for (const s of ['__dataHost', '__CE_shadowRoot', '__template', '__templatizeOwner']) {
  2555. setupD(h, s);
  2556. }
  2557.  
  2558. const dh = h.__dataHost;
  2559. setupDataHost(dh, skip);
  2560. }
  2561.  
  2562. if (hostElement) {
  2563.  
  2564. for (const s of ['__dataHost', '__CE_shadowRoot', '__template', '__templatizeOwner']) {
  2565. setupD(hostElement, s);
  2566. }
  2567.  
  2568. const dh = hostElement.__dataHost;
  2569. setupDataHost(dh, skip);
  2570.  
  2571. aDelay().then(() => {
  2572. setupD(hostElement, '__CE_shadowRoot');
  2573. });
  2574.  
  2575. }
  2576.  
  2577. }
  2578.  
  2579. }
  2580.  
  2581.  
  2582. let nativeHTMLElement = window.HTMLElement;
  2583.  
  2584. try {
  2585.  
  2586. const q = document.createElement('template');
  2587. q.innerHTML = '<ytz-null361></ytz-null361>';
  2588. nativeHTMLElement = q.content.firstChild.constructor
  2589.  
  2590. } catch (e) { }
  2591.  
  2592. if (!nativeHTMLElement.prototype.connectedCallback) {
  2593. nativeHTMLElement.prototype.connectedCallback79 = nativeHTMLElement.prototype.connectedCallback;
  2594. nativeHTMLElement.prototype.connectedCallback = function () {
  2595. let r;
  2596. if (this.connectedCallback79) r = this.connectedCallback79.apply(this, arguments);
  2597.  
  2598. if (WEAK_REF_BINDING && (this instanceof Node) && (this.is || this.__dataHost)) {
  2599. setupWeakRef(this)
  2600. // setupWeakRef(this.__dataHost)
  2601. }
  2602. return r;
  2603. }
  2604. }
  2605.  
  2606. ENABLE_discreteTasking && Object.defineProperty(Object.prototype, 'connectedCallback', {
  2607. get() {
  2608. const f = this[keyStConnectedCallback];
  2609. if (this.is) {
  2610. setupDiscreteTasks(this, true);
  2611. if (f) this.ky36 = 1;
  2612. }
  2613. if (WEAK_REF_BINDING && (this.is || this instanceof Node)) {
  2614. setupWeakRef(this)
  2615. }
  2616. return f;
  2617. },
  2618. set(nv) {
  2619. let gv;
  2620. if (typeof nv === 'function') {
  2621.  
  2622. gv = cmf.get(nv) || gvGenerator(nv);
  2623. if (gv !== nv) {
  2624. cmf.set(nv, gv);
  2625. cmf.set(gv, gv);
  2626. dmf.set(gv, nv);
  2627. }
  2628.  
  2629. } else {
  2630. gv = nv;
  2631. }
  2632. this[keyStConnectedCallback] = gv; // proto or object
  2633. if (this.is) {
  2634. setupDiscreteTasks(this);
  2635. }
  2636. if (WEAK_REF_BINDING && (this.is || this instanceof Node)) {
  2637. setupWeakRef(this)
  2638. }
  2639. return true;
  2640. },
  2641. enumerable: false,
  2642. configurable: true
  2643.  
  2644. });
  2645.  
  2646. const pLoad = new Promise(resolve => {
  2647. if (document.readyState !== 'loading') {
  2648. resolve();
  2649. } else {
  2650. window.addEventListener("DOMContentLoaded", resolve, false);
  2651. }
  2652. });
  2653. pLoad.then(() => {
  2654.  
  2655. let nonce = document.querySelector('style[nonce]');
  2656. nonce = nonce ? nonce.getAttribute('nonce') : null;
  2657. const st = document.createElement('style');
  2658. if (typeof nonce === 'string') st.setAttribute('nonce', nonce);
  2659. st.textContent = "none-element-k47{order:0}";
  2660. st.addEventListener('load', () => {
  2661. pf31.resolve();
  2662. p59 = 1;
  2663. }, false);
  2664. document.body.appendChild(st);
  2665.  
  2666. });
  2667.  
  2668. const prepareLogs = [];
  2669.  
  2670. const skipAdsDetection = new Set(['/robots.txt', '/live_chat', '/live_chat_replay']);
  2671.  
  2672. let winError00 = window.onerror;
  2673.  
  2674. let fix_error_many_stack_state = !FIX_error_many_stack ? 0 : skipAdsDetection.has(location.pathname) ? 2 : 1;
  2675.  
  2676. if (!JSON || !('parse' in JSON)) fix_error_many_stack_state = 0;
  2677.  
  2678. ; FIX_Iframe_NULL_SRC && (() => {
  2679.  
  2680. const emptyBlobUrl = URL.createObjectURL(new Blob([], { type: 'text/html' }));
  2681. const lcOpt = { sensitivity: 'base' };
  2682. document.createElement24 = document.createElement;
  2683. document.createElement = function (t) {
  2684. if (typeof t === 'string' && t.length === 6) {
  2685. if (t.localeCompare('iframe', undefined, lcOpt) === 0) {
  2686. const p = this.createElement24(t);
  2687. try {
  2688. const stack = new Error().stack;
  2689. const isSearchbox = stack.includes('initializeSearchbox'); // see https://greasyfork.org/scripts/473972-youtube-js-engine-tamer/discussions/217084
  2690. if (!isSearchbox) {
  2691. p.src = emptyBlobUrl; // avoid iframe is appended to DOM without any url
  2692. }
  2693. } catch (e) { }
  2694. return p;
  2695. }
  2696. }
  2697. return this.createElement24.apply(this, arguments);
  2698. };
  2699.  
  2700. })();
  2701.  
  2702. ; fix_error_many_stack_state === 1 && (() => {
  2703.  
  2704.  
  2705. let p1 = winError00;
  2706.  
  2707. let stackNeedleDetails = null;
  2708.  
  2709. Object.defineProperty(Object.prototype, 'matchAll', {
  2710. get() {
  2711. stackNeedleDetails = this;
  2712. return true;
  2713. },
  2714. enumerable: true,
  2715. configurable: true
  2716. });
  2717.  
  2718. try {
  2719. JSON.parse("{}");
  2720. } catch (e) {
  2721. console.warn(e)
  2722. fix_error_many_stack_state = 0;
  2723. }
  2724.  
  2725. delete Object.prototype['matchAll'];
  2726.  
  2727. let p2 = window.onerror;
  2728.  
  2729. window.onerror = p1;
  2730.  
  2731. if (fix_error_many_stack_state === 0) return;
  2732.  
  2733. if (stackNeedleDetails) {
  2734. JSON.parse.stackNeedleDetails = stackNeedleDetails;
  2735. stackNeedleDetails.matchAll = true;
  2736. }
  2737.  
  2738. if (p1 === p2) return (fix_error_many_stack_state = 0);
  2739.  
  2740. // p1!==p2
  2741. fix_error_many_stack_state = !stackNeedleDetails ? 4 : 3;
  2742.  
  2743. })();
  2744.  
  2745. ; fix_error_many_stack_state === 2 && (() => {
  2746.  
  2747.  
  2748. let p1 = winError00;
  2749.  
  2750. let objectPrune = null;
  2751. let stackNeedleDetails = null;
  2752.  
  2753. Object.defineProperty(Function.prototype, 'findOwner', {
  2754. get() {
  2755. objectPrune = this;
  2756. return this._findOwner;
  2757. },
  2758. set(nv) {
  2759. this._findOwner = nv;
  2760. return true;
  2761. },
  2762. enumerable: true,
  2763. configurable: true
  2764. });
  2765.  
  2766. Object.defineProperty(Object.prototype, 'matchAll', {
  2767. get() {
  2768. stackNeedleDetails = this;
  2769. return true;
  2770. },
  2771. enumerable: true,
  2772. configurable: true
  2773. });
  2774.  
  2775. try {
  2776. JSON.parse("{}");
  2777. } catch (e) {
  2778. console.warn(e)
  2779. fix_error_many_stack_state = 0;
  2780. }
  2781.  
  2782. delete Function.prototype['findOwner'];
  2783. delete Object.prototype['matchAll'];
  2784.  
  2785. let p2 = window.onerror;
  2786.  
  2787. if (p1 !== p2) return (fix_error_many_stack_state = 4); // p1 != p2
  2788.  
  2789. if (fix_error_many_stack_state == 0) return;
  2790.  
  2791. // the following will only execute when Brave's scriptlets.js is executed.
  2792.  
  2793. prepareLogs.push("fix_error_many_stack_state NB")
  2794.  
  2795. if (stackNeedleDetails) {
  2796. stackNeedleDetails.pattern = null;
  2797. stackNeedleDetails.re = null;
  2798. stackNeedleDetails.expect = null;
  2799. stackNeedleDetails.matchAll = true;
  2800. }
  2801.  
  2802. if (objectPrune) {
  2803. objectPrune.findOwner = objectPrune.mustProcess = objectPrune.logJson = () => { }
  2804. delete objectPrune._findOwner;
  2805. }
  2806.  
  2807. fix_error_many_stack_state = 3;
  2808. JSON.parse.stackNeedleDetails = stackNeedleDetails;
  2809. JSON.parse.objectPrune = objectPrune;
  2810.  
  2811. })();
  2812.  
  2813. ; fix_error_many_stack_state === 3 && (() => {
  2814.  
  2815.  
  2816. let p1 = winError00;
  2817.  
  2818. try {
  2819. JSON.parse("{}");
  2820. } catch (e) {
  2821. console.warn(e)
  2822. fix_error_many_stack_state = 0;
  2823. }
  2824.  
  2825. let p2 = window.onerror;
  2826.  
  2827. if (p1 === p2) return;
  2828.  
  2829. window.onerror = p1;
  2830.  
  2831. if (fix_error_many_stack_state === 0) return;
  2832.  
  2833. fix_error_many_stack_state = 4; // p1 != p2
  2834.  
  2835.  
  2836. })();
  2837.  
  2838. fix_error_many_stack_state === 4 && (() => {
  2839.  
  2840. // the following will only execute when Brave's scriptlets.js is executed.
  2841.  
  2842. prepareLogs.push("fix_error_many_stack_state AB")
  2843.  
  2844. JSON.parseProxy = JSON.parse;
  2845.  
  2846. JSON.parse = ((parse) => {
  2847.  
  2848. parse = parse.bind(JSON); // get a new instance of the current JSON.parse
  2849. return function (text, reviver) {
  2850. const onerror = window.onerror;
  2851. window.onerror = null;
  2852. let r;
  2853. try {
  2854. r = parse(...arguments);
  2855. } catch (e) {
  2856. r = e;
  2857. }
  2858. window.onerror = onerror;
  2859. if (r instanceof Error) {
  2860. throw r;
  2861. }
  2862. return r;
  2863. }
  2864.  
  2865. })(JSON.parse);
  2866.  
  2867.  
  2868. })();
  2869.  
  2870.  
  2871. // << if FIX_yt_player >>
  2872.  
  2873. // credit to @nopeless (https://greasyfork.org/scripts/471489-youtube-player-perf/)
  2874. const PERF_471489_ = true;
  2875. // PERF_471489_ is not exactly the same to Youtube Player perf v0.7
  2876. // This script uses a much gentle way to tamer the JS engine instead.
  2877.  
  2878. // << end >>
  2879.  
  2880. const steppingScaleN = 200; // transform: scaleX(k/N); 0<k<N
  2881.  
  2882.  
  2883.  
  2884. const nilFn = () => { };
  2885.  
  2886. let isMainWindow = false;
  2887. try {
  2888. isMainWindow = window.document === window.top.document
  2889. } catch (e) { }
  2890.  
  2891. let NO_PRELOAD_GENERATE_204_BYPASS = NO_PRELOAD_GENERATE_204 ? false : true;
  2892. let headLinkCollection = null;
  2893.  
  2894. const isCustomElementsProvided = typeof customElements !== "undefined" && typeof (customElements || 0).whenDefined === "function";
  2895.  
  2896. const promiseForCustomYtElementsReady = isCustomElementsProvided ? null : new Promise((callback) => {
  2897. const EVENT_KEY_ON_REGISTRY_READY = "ytI-ce-registry-created";
  2898. if (typeof customElements === 'undefined') {
  2899. if (!('__CE_registry' in document)) {
  2900. // https://github.com/webcomponents/polyfills/
  2901. Object.defineProperty(document, '__CE_registry', {
  2902. get() {
  2903. // return undefined
  2904. },
  2905. set(nv) {
  2906. if (typeof nv == 'object') {
  2907. delete this.__CE_registry;
  2908. this.__CE_registry = nv;
  2909. this.dispatchEvent(new CustomEvent(EVENT_KEY_ON_REGISTRY_READY));
  2910. }
  2911. return true;
  2912. },
  2913. enumerable: false,
  2914. configurable: true
  2915. })
  2916. }
  2917. let eventHandler = (evt) => {
  2918. document.removeEventListener(EVENT_KEY_ON_REGISTRY_READY, eventHandler, false);
  2919. const f = callback;
  2920. callback = null;
  2921. eventHandler = null;
  2922. f();
  2923. };
  2924. document.addEventListener(EVENT_KEY_ON_REGISTRY_READY, eventHandler, false);
  2925. } else {
  2926. callback();
  2927. }
  2928. });
  2929.  
  2930. const whenCEDefined = isCustomElementsProvided
  2931. ? (nodeName) => customElements.whenDefined(nodeName)
  2932. : (nodeName) => promiseForCustomYtElementsReady.then(() => customElements.whenDefined(nodeName));
  2933.  
  2934. // const assertor = (f) => f() || console.assert(false, f + "");
  2935.  
  2936. const fnIntegrity = (f, d) => {
  2937. if (!f || typeof f !== 'function') {
  2938. console.warn('f is not a function', f);
  2939. return;
  2940. }
  2941. let p = f + "", s = 0, j = -1, w = 0;
  2942. for (let i = 0, l = p.length; i < l; i++) {
  2943. const t = p[i];
  2944. if (((t >= 'a' && t <= 'z') || (t >= 'A' && t <= 'Z'))) {
  2945. if (j < i - 1) w++;
  2946. j = i;
  2947. } else {
  2948. s++;
  2949. }
  2950. }
  2951. let itz = `${f.length}.${s}.${w}`;
  2952. if (!d) {
  2953. return itz;
  2954. } else {
  2955. return itz === d;
  2956. }
  2957. };
  2958.  
  2959. const getZqOu = (_yt_player) => {
  2960.  
  2961. const w = 'ZqOu';
  2962.  
  2963. let arr = [];
  2964.  
  2965. for (const [k, v] of Object.entries(_yt_player)) {
  2966.  
  2967. const p = typeof v === 'function' ? v.prototype : 0;
  2968. if (p
  2969. && typeof p.start === 'function' && p.start.length === 0 // Ou
  2970. && typeof p.isActive === 'function' && p.isActive.length === 0
  2971. && typeof p.stop === 'function' && p.stop.length === 0
  2972. && !p.isComplete && !p.getStatus && !p.getResponseHeader && !p.getLastError
  2973. && !p.send && !p.abort
  2974. && !p.sample && !p.initialize && !p.fail && !p.getName
  2975. // && !p.dispose && !p.isDisposed
  2976.  
  2977. ) {
  2978. arr = addProtoToArr(_yt_player, k, arr) || arr;
  2979.  
  2980.  
  2981. }
  2982.  
  2983. }
  2984.  
  2985. if (arr.length === 0) {
  2986.  
  2987. console.warn(`Key does not exist. [${w}]`);
  2988. } else {
  2989.  
  2990. console.log(`[${w}]`, arr);
  2991. return arr[0];
  2992. }
  2993.  
  2994. }
  2995.  
  2996. const getZqQu = (_yt_player) => {
  2997.  
  2998. const w = 'ZqQu';
  2999.  
  3000. let arr = [];
  3001.  
  3002.  
  3003. for (const [k, v] of Object.entries(_yt_player)) {
  3004.  
  3005. const p = typeof v === 'function' ? v.prototype : 0;
  3006. if (p
  3007. && typeof p.start === 'function' && p.start.length === 1 // Qu
  3008. && typeof p.isActive === 'function' && p.isActive.length === 0
  3009. && typeof p.stop === 'function' && p.stop.length === 0
  3010. && !p.isComplete && !p.getStatus && !p.getResponseHeader && !p.getLastError
  3011. && !p.send && !p.abort
  3012. && !p.sample && !p.initialize && !p.fail && !p.getName
  3013. // && !p.dispose && !p.isDisposed
  3014.  
  3015. ) {
  3016. arr = addProtoToArr(_yt_player, k, arr) || arr;
  3017.  
  3018.  
  3019. }
  3020.  
  3021. }
  3022.  
  3023. if (arr.length === 0) {
  3024.  
  3025. console.warn(`Key does not exist. [${w}]`);
  3026. } else {
  3027.  
  3028. console.log(`[${w}]`, arr);
  3029. return arr[0];
  3030. }
  3031.  
  3032. }
  3033.  
  3034.  
  3035. const getVG = (_yt_player) => {
  3036. const w = 'VG';
  3037.  
  3038. let arr = [];
  3039.  
  3040. for (const [k, v] of Object.entries(_yt_player)) {
  3041.  
  3042. const p = typeof v === 'function' ? v.prototype : 0;
  3043. if (p
  3044. && typeof p.show === 'function' && p.show.length === 1
  3045. && typeof p.hide === 'function' && p.hide.length === 0
  3046. && typeof p.stop === 'function' && p.stop.length === 0) {
  3047.  
  3048. arr = addProtoToArr(_yt_player, k, arr) || arr;
  3049.  
  3050. }
  3051.  
  3052. }
  3053.  
  3054.  
  3055. if (arr.length === 0) {
  3056.  
  3057. console.warn(`Key does not exist. [${w}]`);
  3058. } else {
  3059.  
  3060. console.log(`[${w}]`, arr);
  3061. return arr[0];
  3062. }
  3063.  
  3064.  
  3065.  
  3066. }
  3067.  
  3068.  
  3069. const getzo = (_yt_player) => {
  3070. const w = 'zo';
  3071.  
  3072. let arr = [];
  3073.  
  3074. for (const [k, v] of Object.entries(_yt_player)) {
  3075.  
  3076. if (
  3077. typeof v === 'function' && v.length === 3 && k.length < 3
  3078. && (v + "").includes("a.style[b]=c")
  3079. ) {
  3080.  
  3081. arr.push(k);
  3082.  
  3083. }
  3084.  
  3085. }
  3086.  
  3087.  
  3088. if (arr.length === 0) {
  3089.  
  3090. console.warn(`Key does not exist. [${w}]`);
  3091. } else {
  3092.  
  3093. console.log(`[${w}]`, arr);
  3094. return arr[0];
  3095. }
  3096.  
  3097. }
  3098.  
  3099. const addProtoToArr = (parent, key, arr) => {
  3100.  
  3101.  
  3102. let isChildProto = false;
  3103. for (const sr of arr) {
  3104. if (parent[key].prototype instanceof parent[sr]) {
  3105. isChildProto = true;
  3106. break;
  3107. }
  3108. }
  3109.  
  3110. if (isChildProto) return;
  3111.  
  3112. arr = arr.filter(sr => {
  3113. if (parent[sr].prototype instanceof parent[key]) {
  3114. return false;
  3115. }
  3116. return true;
  3117. });
  3118.  
  3119. arr.push(key);
  3120.  
  3121. return arr;
  3122.  
  3123.  
  3124. }
  3125.  
  3126. const getuG = (_yt_player) => {
  3127.  
  3128. const w = 'uG';
  3129.  
  3130. let arr = [];
  3131.  
  3132. for (const [k, v] of Object.entries(_yt_player)) {
  3133.  
  3134.  
  3135. const p = typeof v === 'function' ? v.prototype : 0;
  3136.  
  3137. if (p
  3138. && typeof p.createElement === 'function' && p.createElement.length === 2
  3139. && typeof p.detach === 'function' && p.detach.length === 0
  3140. && typeof p.update === 'function' && p.update.length === 1
  3141. && typeof p.updateValue === 'function' && p.updateValue.length === 2
  3142. ) {
  3143.  
  3144. arr = addProtoToArr(_yt_player, k, arr) || arr;
  3145.  
  3146. }
  3147.  
  3148. }
  3149.  
  3150.  
  3151.  
  3152.  
  3153.  
  3154. if (arr.length === 0) {
  3155.  
  3156. console.warn(`Key does not exist. [${w}]`);
  3157. } else {
  3158.  
  3159. console.log(`[${w}]`, arr);
  3160. return arr[0];
  3161. }
  3162.  
  3163. }
  3164.  
  3165.  
  3166. const getQT = (_yt_player) => {
  3167. const w = 'QT';
  3168.  
  3169. let arr = [];
  3170. let brr = new Map();
  3171.  
  3172. for (const [k, v] of Object.entries(_yt_player)) {
  3173.  
  3174. const p = typeof v === 'function' ? v.prototype : 0;
  3175. if (p) {
  3176. let q = 0;
  3177. if (typeof p.handleGlobalKeyUp === 'function' && p.handleGlobalKeyUp.length === 7) q += 400;
  3178. else if (typeof p.handleGlobalKeyUp === 'function' && p.handleGlobalKeyUp.length === 8) q += 300;
  3179. else if (typeof p.handleGlobalKeyUp === 'function') q += 200;
  3180.  
  3181. if (typeof p.handleGlobalKeyUp === 'function' && p.handleGlobalKeyUp.length === 0) q -= 600; // avoid SV
  3182.  
  3183. if (q < 200) continue; // p.handleGlobalKeyUp must be available
  3184.  
  3185. if (typeof p.handleGlobalKeyDown === 'function' && p.handleGlobalKeyDown.length === 8) q += 80;
  3186. if (typeof p.handleGlobalKeyDown === 'function' && p.handleGlobalKeyDown.length === 7) q += 30;
  3187. if (typeof p.step === 'function' && p.step.length === 1) q += 10;
  3188. if (typeof p.step === 'function' && p.step.length !== 1) q += 5;
  3189.  
  3190.  
  3191. // differentiate QT and DX
  3192.  
  3193. q += 280;
  3194. if (typeof p.cueVideoByPlayerVars === 'function') q += 4;
  3195. if (typeof p.loadVideoByPlayerVars === 'function') q += 4;
  3196. if (typeof p.preloadVideoByPlayerVars === 'function') q += 4;
  3197. if (typeof p.seekBy === 'function') q += 4;
  3198. if (typeof p.seekTo === 'function') q += 4;
  3199. if (typeof p.getStoryboardFormat === 'function') q += 4;
  3200. if (typeof p.getDuration === 'function') q += 4;
  3201. if (typeof p.loadModule === 'function') q += 4;
  3202. if (typeof p.unloadModule === 'function') q += 4;
  3203. if (typeof p.getOption === 'function') q += 4;
  3204. if (typeof p.getOptions === 'function') q += 4;
  3205. if (typeof p.setOption === 'function') q += 4;
  3206. if (typeof p.addCueRange === 'function') q += 4;
  3207. if (typeof p.getDebugText === 'function') q += 4;
  3208. if (typeof p.getCurrentBroadcastId === 'function') q += 4;
  3209. if (typeof p.setSizeStyle === 'function') q += 4;
  3210. if (typeof p.showControls === 'function') q += 4;
  3211. if (typeof p.hideControls === 'function') q += 4;
  3212. if (typeof p.getVideoContentRect === 'function') q += 4;
  3213. if (typeof p.toggleFullscreen === 'function') q += 4;
  3214. if (typeof p.isFullscreen === 'function') q += 4;
  3215. if (typeof p.cancelPlayback === 'function') q += 4;
  3216. if (typeof p.getProgressState === 'function') q += 4;
  3217. if (typeof p.isInline === 'function') q += 4;
  3218. if (typeof p.setInline === 'function') q += 4;
  3219. if (typeof p.toggleSubtitles === 'function') q += 4;
  3220. if (typeof p.getPlayerSize === 'function') q += 4;
  3221. if (typeof p.wakeUpControls === 'function') q += 4;
  3222. if (typeof p.setCenterCrop === 'function') q += 4;
  3223. if (typeof p.getLoopVideo === 'function') q += 4;
  3224. if (typeof p.setLoopVideo === 'function') q += 4;
  3225.  
  3226.  
  3227. if (q > 0) arr = addProtoToArr(_yt_player, k, arr) || arr;
  3228.  
  3229. if (q > 0) brr.set(k, q);
  3230.  
  3231. }
  3232.  
  3233. }
  3234.  
  3235. if (arr.length === 0) {
  3236.  
  3237. console.warn(`Key does not exist. [${w}]`);
  3238. } else {
  3239.  
  3240. arr = arr.map(key => [key, (brr.get(key) || 0)]);
  3241.  
  3242. if (arr.length > 1) arr.sort((a, b) => b[1] - a[1]);
  3243.  
  3244. if (arr.length > 2) console.log(`[${w}]`, arr);
  3245. return arr[0][0];
  3246. }
  3247.  
  3248.  
  3249.  
  3250. }
  3251.  
  3252.  
  3253.  
  3254. const getSV = (_yt_player) => {
  3255. const w = 'SV';
  3256.  
  3257. let arr = [];
  3258. let brr = new Map();
  3259.  
  3260. for (const [k, v] of Object.entries(_yt_player)) {
  3261.  
  3262. const p = typeof v === 'function' ? v.prototype : 0;
  3263. if (p) {
  3264. let q = 0;
  3265. if (typeof p.handleGlobalKeyUp === 'function' && p.handleGlobalKeyUp.length === 7) q += 400;
  3266. else if (typeof p.handleGlobalKeyUp === 'function' && p.handleGlobalKeyUp.length === 8) q += 300;
  3267. else if (typeof p.handleGlobalKeyUp === 'function') q += 200;
  3268.  
  3269. if (typeof p.handleGlobalKeyUp === 'function' && p.handleGlobalKeyUp.length === 0) q += 600; // SV
  3270.  
  3271. if (q < 200) continue; // p.handleGlobalKeyUp must be available
  3272.  
  3273. if (typeof p.handleGlobalKeyDown === 'function' && p.handleGlobalKeyDown.length === 8) q += 80;
  3274. if (typeof p.handleGlobalKeyDown === 'function' && p.handleGlobalKeyDown.length === 7) q += 30;
  3275. if (typeof p.step === 'function' && p.step.length === 1) q += 10;
  3276. if (typeof p.step === 'function' && p.step.length !== 1) q += 5;
  3277.  
  3278.  
  3279. // differentiate QT and DX
  3280.  
  3281.  
  3282. q += 280;
  3283.  
  3284. if (typeof p.cueVideoByPlayerVars === 'function') q -= 4;
  3285. if (typeof p.loadVideoByPlayerVars === 'function') q -= 4;
  3286. if (typeof p.preloadVideoByPlayerVars === 'function') q -= 4;
  3287. if (typeof p.seekBy === 'function') q -= 4;
  3288. if (typeof p.seekTo === 'function') q -= 4;
  3289. if (typeof p.getStoryboardFormat === 'function') q -= 4;
  3290. if (typeof p.getDuration === 'function') q -= 4;
  3291. if (typeof p.loadModule === 'function') q -= 4;
  3292. if (typeof p.unloadModule === 'function') q -= 4;
  3293. if (typeof p.getOption === 'function') q -= 4;
  3294. if (typeof p.getOptions === 'function') q -= 4;
  3295. if (typeof p.setOption === 'function') q -= 4;
  3296. if (typeof p.addCueRange === 'function') q -= 4;
  3297. if (typeof p.getDebugText === 'function') q -= 4;
  3298. if (typeof p.getCurrentBroadcastId === 'function') q -= 4;
  3299. if (typeof p.setSizeStyle === 'function') q -= 4;
  3300. if (typeof p.showControls === 'function') q -= 4;
  3301. if (typeof p.hideControls === 'function') q -= 4;
  3302. if (typeof p.getVideoContentRect === 'function') q -= 4;
  3303. if (typeof p.toggleFullscreen === 'function') q -= 4;
  3304. if (typeof p.isFullscreen === 'function') q -= 4;
  3305. if (typeof p.cancelPlayback === 'function') q -= 4;
  3306. if (typeof p.getProgressState === 'function') q -= 4;
  3307. if (typeof p.isInline === 'function') q -= 4;
  3308. if (typeof p.setInline === 'function') q -= 4;
  3309. if (typeof p.toggleSubtitles === 'function') q -= 4;
  3310. if (typeof p.getPlayerSize === 'function') q -= 4;
  3311. if (typeof p.wakeUpControls === 'function') q -= 4;
  3312. if (typeof p.setCenterCrop === 'function') q -= 4;
  3313. if (typeof p.getLoopVideo === 'function') q -= 4;
  3314. if (typeof p.setLoopVideo === 'function') q -= 4;
  3315.  
  3316.  
  3317. if (q > 0) arr = addProtoToArr(_yt_player, k, arr) || arr;
  3318.  
  3319. if (q > 0) brr.set(k, q);
  3320.  
  3321. }
  3322.  
  3323. }
  3324.  
  3325. if (arr.length === 0) {
  3326.  
  3327. console.warn(`Key does not exist. [${w}]`);
  3328. } else {
  3329.  
  3330. arr = arr.map(key => [key, (brr.get(key) || 0)]);
  3331.  
  3332. if (arr.length > 1) arr.sort((a, b) => b[1] - a[1]);
  3333.  
  3334. if (arr.length > 2) console.log(`[${w}]`, arr);
  3335. return arr[0][0];
  3336. }
  3337.  
  3338.  
  3339.  
  3340. }
  3341.  
  3342.  
  3343.  
  3344.  
  3345. const getDX = (_yt_player) => {
  3346. const w = 'DX';
  3347.  
  3348. let arr = [];
  3349. let brr = new Map();
  3350.  
  3351. for (const [k, v] of Object.entries(_yt_player)) {
  3352.  
  3353. const p = typeof v === 'function' ? v.prototype : 0;
  3354. if (p) {
  3355. let q = 0;
  3356. if (typeof p.handleGlobalKeyUp === 'function' && p.handleGlobalKeyUp.length === 7) q += 400;
  3357. else if (typeof p.handleGlobalKeyUp === 'function' && p.handleGlobalKeyUp.length === 8) q += 300;
  3358. else if (typeof p.handleGlobalKeyUp === 'function') q += 200;
  3359.  
  3360. if (typeof p.handleGlobalKeyUp === 'function' && p.handleGlobalKeyUp.length === 0) q -= 600; // avoid SV
  3361.  
  3362.  
  3363. if (!(typeof p.init === 'function' && p.init.length === 0)) q -= 300; // init is required
  3364.  
  3365. if (q < 200) continue; // p.handleGlobalKeyUp must be available
  3366.  
  3367. if (typeof p.handleGlobalKeyDown === 'function' && p.handleGlobalKeyDown.length === 8) q += 80;
  3368. if (typeof p.handleGlobalKeyDown === 'function' && p.handleGlobalKeyDown.length === 7) q += 30;
  3369. if (typeof p.step === 'function' && p.step.length === 1) q += 10;
  3370. if (typeof p.step === 'function' && p.step.length !== 1) q += 5;
  3371.  
  3372.  
  3373. // differentiate QT and DX
  3374.  
  3375.  
  3376. q += 280;
  3377.  
  3378. if (typeof p.cueVideoByPlayerVars === 'function') q -= 4;
  3379. if (typeof p.loadVideoByPlayerVars === 'function') q -= 4;
  3380. if (typeof p.preloadVideoByPlayerVars === 'function') q -= 4;
  3381. if (typeof p.seekBy === 'function') q -= 4;
  3382. if (typeof p.seekTo === 'function') q -= 4;
  3383. if (typeof p.getStoryboardFormat === 'function') q -= 4;
  3384. if (typeof p.getDuration === 'function') q -= 4;
  3385. if (typeof p.loadModule === 'function') q -= 4;
  3386. if (typeof p.unloadModule === 'function') q -= 4;
  3387. if (typeof p.getOption === 'function') q -= 4;
  3388. if (typeof p.getOptions === 'function') q -= 4;
  3389. if (typeof p.setOption === 'function') q -= 4;
  3390. if (typeof p.addCueRange === 'function') q -= 4;
  3391. if (typeof p.getDebugText === 'function') q -= 4;
  3392. if (typeof p.getCurrentBroadcastId === 'function') q -= 4;
  3393. if (typeof p.setSizeStyle === 'function') q -= 4;
  3394. if (typeof p.showControls === 'function') q -= 4;
  3395. if (typeof p.hideControls === 'function') q -= 4;
  3396. if (typeof p.getVideoContentRect === 'function') q -= 4;
  3397. if (typeof p.toggleFullscreen === 'function') q -= 4;
  3398. if (typeof p.isFullscreen === 'function') q -= 4;
  3399. if (typeof p.cancelPlayback === 'function') q -= 4;
  3400. if (typeof p.getProgressState === 'function') q -= 4;
  3401. if (typeof p.isInline === 'function') q -= 4;
  3402. if (typeof p.setInline === 'function') q -= 4;
  3403. if (typeof p.toggleSubtitles === 'function') q -= 4;
  3404. if (typeof p.getPlayerSize === 'function') q -= 4;
  3405. if (typeof p.wakeUpControls === 'function') q -= 4;
  3406. if (typeof p.setCenterCrop === 'function') q -= 4;
  3407. if (typeof p.getLoopVideo === 'function') q -= 4;
  3408. if (typeof p.setLoopVideo === 'function') q -= 4;
  3409.  
  3410.  
  3411. if (q > 0) arr = addProtoToArr(_yt_player, k, arr) || arr;
  3412.  
  3413. if (q > 0) brr.set(k, q);
  3414.  
  3415. }
  3416.  
  3417. }
  3418.  
  3419. if (arr.length === 0) {
  3420.  
  3421. console.warn(`Key does not exist. [${w}]`);
  3422. } else {
  3423.  
  3424. arr = arr.map(key => [key, (brr.get(key) || 0)]);
  3425.  
  3426. if (arr.length > 1) arr.sort((a, b) => b[1] - a[1]);
  3427.  
  3428. if (arr.length > 2) console.log(`[${w}]`, arr);
  3429. return arr[0][0];
  3430. }
  3431.  
  3432.  
  3433.  
  3434. }
  3435.  
  3436.  
  3437.  
  3438. const isPrepareCachedV = (FIX_avoid_incorrect_video_meta ? true : false) && (window === top);
  3439.  
  3440. let pageSetupVideoId = null; // set at finish; '' for indeterminate state
  3441. let pageSetupState = 0;
  3442.  
  3443. isPrepareCachedV && (() => {
  3444.  
  3445. pageSetupVideoId = '';
  3446. const clearCachedV = () => {
  3447. pageSetupVideoId = '';
  3448. pageSetupState = 0;
  3449. }
  3450. document.addEventListener('yt-navigate-start', clearCachedV, false); // user action
  3451. document.addEventListener('yt-navigate-cache', clearCachedV, false); // pop state
  3452. document.addEventListener('yt-page-data-fetched', clearCachedV, false); // still consider invalid until url is ready in yt-navigate-finish
  3453. document.addEventListener('yt-navigate-finish', () => {
  3454. pageSetupState = 1;
  3455. try {
  3456. const url = new URL(location.href);
  3457. if (!url || url.pathname !== '/watch') {
  3458. pageSetupVideoId = '';
  3459. } else {
  3460. pageSetupVideoId = url.searchParams.get('v') || '';
  3461. }
  3462. } catch (e) {
  3463. pageSetupVideoId = '';
  3464. }
  3465. }, false);
  3466.  
  3467. })();
  3468.  
  3469. let videoPlayingY = null;
  3470.  
  3471. isPrepareCachedV && (() => {
  3472.  
  3473. let getNext = true;
  3474. let videoPlayingX = {
  3475. get videoId() {
  3476. if (getNext) {
  3477. getNext = false;
  3478.  
  3479. let elements = document.querySelectorAll('ytd-watch-flexy[video-id]');
  3480. const arr = [];
  3481. for (const element of elements) {
  3482. if (!element.closest('[hidden]')) arr.push(element);
  3483. }
  3484. if (arr.length !== 1) this.__videoId__ = '';
  3485. else {
  3486. this.__videoId__ = arr[0].getAttribute('video-id');
  3487. }
  3488.  
  3489. }
  3490. return this.__videoId__ || '';
  3491. }
  3492. }
  3493.  
  3494. videoPlayingY = videoPlayingX;
  3495. const handler = (evt) => {
  3496. const target = (evt || 0).target;
  3497. if (target instanceof HTMLVideoElement) {
  3498. getNext = true;
  3499. }
  3500. }
  3501. document.addEventListener('loadedmetadata', handler, true);
  3502. document.addEventListener('durationchange', handler, true);
  3503.  
  3504. })();
  3505.  
  3506.  
  3507.  
  3508. const cleanContext = async (win) => {
  3509. const waitFn = requestAnimationFrame; // shall have been binded to window
  3510. try {
  3511. let mx = 16; // MAX TRIAL
  3512. const frameId = 'vanillajs-iframe-v1';
  3513. /** @type {HTMLIFrameElement | null} */
  3514. let frame = document.getElementById(frameId);
  3515. let removeIframeFn = null;
  3516. if (!frame) {
  3517. frame = document.createElement('iframe');
  3518. frame.id = frameId;
  3519. const blobURL = typeof webkitCancelAnimationFrame === 'function' ? (frame.src = URL.createObjectURL(new Blob([], { type: 'text/html' }))) : null; // avoid Brave Crash
  3520. frame.sandbox = 'allow-same-origin'; // script cannot be run inside iframe but API can be obtained from iframe
  3521. let n = document.createElement('noscript'); // wrap into NOSCRPIT to avoid reflow (layouting)
  3522. n.appendChild(frame);
  3523. while (!document.documentElement && mx-- > 0) await new Promise(waitFn); // requestAnimationFrame here could get modified by YouTube engine
  3524. const root = document.documentElement;
  3525. root.appendChild(n); // throw error if root is null due to exceeding MAX TRIAL
  3526. if (blobURL) Promise.resolve().then(() => URL.revokeObjectURL(blobURL));
  3527.  
  3528. removeIframeFn = (setTimeout) => {
  3529. const removeIframeOnDocumentReady = (e) => {
  3530. e && win.removeEventListener("DOMContentLoaded", removeIframeOnDocumentReady, false);
  3531. e = n;
  3532. n = win = removeIframeFn = 0;
  3533. setTimeout ? setTimeout(() => e.remove(), 200) : e.remove();
  3534. }
  3535. if (!setTimeout || document.readyState !== 'loading') {
  3536. removeIframeOnDocumentReady();
  3537. } else {
  3538. win.addEventListener("DOMContentLoaded", removeIframeOnDocumentReady, false);
  3539. }
  3540. }
  3541. }
  3542. while (!frame.contentWindow && mx-- > 0) await new Promise(waitFn);
  3543. const fc = frame.contentWindow;
  3544. if (!fc) throw "window is not found."; // throw error if root is null due to exceeding MAX TRIAL
  3545. try {
  3546. const { requestAnimationFrame, setTimeout, clearTimeout, cancelAnimationFrame, setInterval, clearInterval, requestIdleCallback, getComputedStyle } = fc;
  3547. const res = { requestAnimationFrame, setTimeout, clearTimeout, cancelAnimationFrame, setInterval, clearInterval, requestIdleCallback, getComputedStyle };
  3548. for (let k in res) res[k] = res[k].bind(win); // necessary
  3549. if (removeIframeFn) Promise.resolve(res.setTimeout).then(removeIframeFn);
  3550. res.animate = fc.HTMLElement.prototype.animate;
  3551. res.perfNow = fc.performance.now;
  3552. return res;
  3553. } catch (e) {
  3554. if (removeIframeFn) removeIframeFn();
  3555. return null;
  3556. }
  3557. } catch (e) {
  3558. console.warn(e);
  3559. return null;
  3560. }
  3561. };
  3562.  
  3563. const promiseForYtActionCalled = new Promise(resolve => {
  3564. if (typeof AbortSignal !== 'undefined') {
  3565. let hn = () => {
  3566. if (!hn) return;
  3567. hn = null;
  3568. resolve(document.querySelector('ytd-app'));
  3569. };
  3570. document.addEventListener('yt-action', hn, { capture: true, passive: true, once: true });
  3571. } else {
  3572. let hn = () => {
  3573. if (!hn) return;
  3574. document.removeEventListener('yt-action', hn, true);
  3575. hn = null;
  3576. resolve(document.querySelector('ytd-app'));
  3577. };
  3578. document.addEventListener('yt-action', hn, true);
  3579. }
  3580. });
  3581.  
  3582.  
  3583.  
  3584. cleanContext(window).then(__CONTEXT__ => {
  3585. if (!__CONTEXT__) return null;
  3586.  
  3587. const { requestAnimationFrame, setTimeout, clearTimeout, cancelAnimationFrame, setInterval, clearInterval, animate, requestIdleCallback, getComputedStyle, perfNow } = __CONTEXT__;
  3588.  
  3589.  
  3590. performance.now17 = perfNow.bind(performance);
  3591.  
  3592.  
  3593.  
  3594. __requestAnimationFrame__ = requestAnimationFrame;
  3595.  
  3596. let rafPromise = null;
  3597.  
  3598. const getRafPromise = () => rafPromise || (rafPromise = new Promise(resolve => {
  3599. requestAnimationFrame(hRes => {
  3600. rafPromise = null;
  3601. resolve(hRes);
  3602. });
  3603. }));
  3604.  
  3605.  
  3606. const wmComputedStyle = new WeakMap();
  3607.  
  3608. if (!window.__native__getComputedStyle__ && !window.__jst__getComputedStyle__ && typeof window.getComputedStyle === 'function' && window.getComputedStyle.length === 1) {
  3609. window.__native__getComputedStyle__ = getComputedStyle;
  3610. if (ENABLE_COMPUTEDSTYLE_CACHE) {
  3611. window.__original__getComputedStyle__ = window.getComputedStyle;
  3612. window.getComputedStyle = function (elem) {
  3613. if (!(elem instanceof Element) || (arguments.length === 2 && arguments[1]) || (arguments.length > 2)) {
  3614. return window.__native__getComputedStyle__(...arguments);
  3615. }
  3616. let cs = wmComputedStyle.get(elem);
  3617. if (!cs) {
  3618. cs = window.__native__getComputedStyle__(elem);
  3619. wmComputedStyle.set(elem, cs);
  3620. }
  3621. return cs;
  3622. };
  3623. } else {
  3624. window.__original__getComputedStyle__ = null;
  3625. }
  3626. window.__jst__getComputedStyle__ = window.getComputedStyle;
  3627. }
  3628.  
  3629. NO_SCHEDULING_DUE_TO_COMPUTEDSTYLE && promiseForYtActionCalled.then(() => {
  3630. if (typeof window.__jst__getComputedStyle__ === 'function' && window.__jst__getComputedStyle__.length === 1 && window.__jst__getComputedStyle__ !== window.getComputedStyle) {
  3631. window.getComputedStyle = window.__jst__getComputedStyle__;
  3632. }
  3633. });
  3634.  
  3635. const isUrlInEmbed = location.href.includes('.youtube.com/embed/');
  3636. const isAbortSignalSupported = typeof AbortSignal !== "undefined";
  3637.  
  3638. const promiseForTamerTimeout = new Promise(resolve => {
  3639. !isUrlInEmbed && isAbortSignalSupported && document.addEventListener('yt-action', function () {
  3640. setTimeout(resolve, 480);
  3641. }, { capture: true, passive: true, once: true });
  3642. !isUrlInEmbed && isAbortSignalSupported && typeof customElements === "object" && whenCEDefined('ytd-app').then(() => {
  3643. setTimeout(resolve, 1200);
  3644. });
  3645. setTimeout(resolve, 3000);
  3646. });
  3647.  
  3648. const promiseForPageInitied = new Promise(resolve => {
  3649. !isUrlInEmbed && isAbortSignalSupported && document.addEventListener('yt-action', function () {
  3650. setTimeout(resolve, 450);
  3651. }, { capture: true, passive: true, once: true });
  3652. !isUrlInEmbed && isAbortSignalSupported && typeof customElements === "object" && whenCEDefined('ytd-app').then(() => {
  3653. setTimeout(resolve, 900);
  3654. });
  3655. setTimeout(resolve, 1800);
  3656. });
  3657.  
  3658. NO_PRELOAD_GENERATE_204_BYPASS || promiseForPageInitied.then(() => {
  3659. NO_PRELOAD_GENERATE_204_BYPASS = true;
  3660. headLinkCollection = null;
  3661. });
  3662.  
  3663.  
  3664. NATIVE_CANVAS_ANIMATION && (() => {
  3665.  
  3666. observablePromise(() => {
  3667. HTMLCanvasElement.prototype.animate = animate;
  3668. }, promiseForTamerTimeout).obtain();
  3669.  
  3670. })();
  3671.  
  3672. FIX_ytAction_ && (async () => {
  3673.  
  3674. const ytdApp = await new Promise(resolve => {
  3675.  
  3676. whenCEDefined('ytd-app').then(() => {
  3677. const ytdApp = document.querySelector('ytd-app');
  3678. if (ytdApp) {
  3679. resolve(ytdApp);
  3680. return;
  3681. }
  3682. let mo = new MutationObserver(() => {
  3683. const ytdApp = document.querySelector('ytd-app');
  3684. if (!ytdApp) return;
  3685. if (mo) {
  3686. mo.disconnect();
  3687. mo.takeRecords();
  3688. mo = null;
  3689. }
  3690. resolve(ytdApp);
  3691. });
  3692. mo.observe(document, { subtree: true, childList: true });
  3693. });
  3694.  
  3695. });
  3696.  
  3697. if (!ytdApp) return;
  3698. const cProto = insp(ytdApp).constructor.prototype;
  3699.  
  3700. if (!cProto) return;
  3701. let mbd = 0;
  3702.  
  3703. const fixer = (_ytdApp) => {
  3704. const ytdApp = insp(_ytdApp);
  3705. if (ytdApp && typeof ytdApp.onYtActionBoundListener_ === 'function' && !ytdApp.onYtActionBoundListener57_) {
  3706. ytdApp.onYtActionBoundListener57_ = ytdApp.onYtActionBoundListener_;
  3707. ytdApp.onYtActionBoundListener_ = ytdApp.onYtAction_.bind(ytdApp);
  3708. mbd++;
  3709. }
  3710. }
  3711.  
  3712. observablePromise(() => {
  3713.  
  3714. if (typeof cProto.created === 'function' && !cProto.created56) {
  3715. cProto.created56 = cProto.created;
  3716. cProto.created = function (...args) {
  3717. const r = this.created56(...args);
  3718. fixer(this);
  3719. return r;
  3720. };
  3721. mbd++;
  3722. }
  3723.  
  3724. if (typeof cProto.onYtAction_ === 'function' && !cProto.onYtAction57_) {
  3725. cProto.onYtAction57_ = cProto.onYtAction_;
  3726. cProto.onYtAction_ = function (...args) {
  3727. Promise.resolve().then(() => this.onYtAction57_(...args));
  3728. };
  3729. mbd++;
  3730. }
  3731.  
  3732. if (ytdApp) fixer(ytdApp);
  3733.  
  3734. /*
  3735. const actionRouter_ = ytdApp ? ytdApp.actionRouter_ : null;
  3736. if (actionRouter_ && typeof actionRouter_.handleAction === 'function' && !actionRouter_.handleAction57) {
  3737. actionRouter_.handleAction57 = actionRouter_.handleAction;
  3738. actionRouter_.handleAction = function (...args) {
  3739. Promise.resolve().then(() => this.handleAction57(...args));
  3740. }
  3741. mbd++;
  3742. }
  3743. */
  3744.  
  3745. // if(mbd === 3) return 1;
  3746. if (mbd >= 3) return 1;
  3747.  
  3748. }, new Promise(r => setTimeout(r, 1000))).obtain();
  3749.  
  3750. })();
  3751.  
  3752. const observablePromise = (proc, timeoutPromise) => {
  3753. let promise = null;
  3754. return {
  3755. obtain() {
  3756. if (!promise) {
  3757. promise = new Promise(resolve => {
  3758. let mo = null;
  3759. const f = () => {
  3760. let t = proc();
  3761. if (t) {
  3762. mo.disconnect();
  3763. mo.takeRecords();
  3764. mo = null;
  3765. resolve(t);
  3766. }
  3767. }
  3768. mo = new MutationObserver(f);
  3769. mo.observe(document, { subtree: true, childList: true })
  3770. f();
  3771. timeoutPromise && timeoutPromise.then(() => {
  3772. resolve(null)
  3773. });
  3774. });
  3775. }
  3776. return promise
  3777. }
  3778. }
  3779. }
  3780.  
  3781. // let _yt_player_promise = null;
  3782. /*
  3783. const getYtPlayerPromise = () => {
  3784. if (!_yt_player_promise) {
  3785. _yt_player_promise = new Promise(resolve => {
  3786. let cid = setInterval(() => {
  3787. let t = (((window || 0)._yt_player || 0) || 0);
  3788. if (t) {
  3789. clearInterval(cid);
  3790. resolve(t);
  3791. }
  3792. }, 1);
  3793. promiseForTamerTimeout.then(() => {
  3794. resolve(null)
  3795. });
  3796. });
  3797. }
  3798. return _yt_player_promise;
  3799. }
  3800. */
  3801. const _yt_player_observable = observablePromise(() => {
  3802. return (((window || 0)._yt_player || 0) || 0);
  3803. }, promiseForTamerTimeout);
  3804.  
  3805. const polymerObservable = observablePromise(() => {
  3806. const Polymer = window.Polymer;
  3807. if (typeof Polymer !== 'function') return;
  3808. if (!(Polymer.Base || 0).connectedCallback || !(Polymer.Base || 0).disconnectedCallback) return;
  3809. return Polymer;
  3810. }, promiseForTamerTimeout);
  3811.  
  3812. const schedulerInstanceObservable = observablePromise(() => {
  3813. return (((window || 0).ytglobal || 0).schedulerInstanceInstance_ || 0);
  3814. }, promiseForTamerTimeout);
  3815.  
  3816. const timelineObservable = observablePromise(() => {
  3817. let t = (((document || 0).timeline || 0) || 0);
  3818. if (t && typeof t._play === 'function') {
  3819. return t;
  3820. }
  3821. }, promiseForTamerTimeout);
  3822. const animationObservable = observablePromise(() => {
  3823. let t = (((window || 0).Animation || 0) || 0);
  3824. if (t && typeof t === 'function' && t.length === 2 && typeof t.prototype._updatePromises === 'function') {
  3825. return t;
  3826. }
  3827. }, promiseForTamerTimeout);
  3828.  
  3829.  
  3830.  
  3831.  
  3832. const generalEvtHandler = async (_evKey, _fvKey, _debug) => {
  3833.  
  3834. const evKey = `${_evKey}`;
  3835. const fvKey = `${_fvKey}`;
  3836. const debug = !!_debug;
  3837.  
  3838. const _yt_player = await _yt_player_observable.obtain();
  3839.  
  3840.  
  3841. if (!_yt_player || typeof _yt_player !== 'object') return;
  3842.  
  3843.  
  3844. const getArr = (_yt_player) => {
  3845.  
  3846. let arr = [];
  3847.  
  3848. for (const [k, v] of Object.entries(_yt_player)) {
  3849.  
  3850. const p = typeof v === 'function' ? v.prototype : 0;
  3851. if (p
  3852. && typeof p[evKey] === 'function' && p[evKey].length >= 0 && !p[fvKey]
  3853.  
  3854. ) {
  3855. arr = addProtoToArr(_yt_player, k, arr) || arr;
  3856.  
  3857. }
  3858.  
  3859. }
  3860.  
  3861. if (arr.length === 0) {
  3862.  
  3863. console.warn(`Key prop [${evKey}] does not exist.`);
  3864. } else {
  3865.  
  3866. return arr;
  3867. }
  3868.  
  3869. };
  3870.  
  3871. const arr = getArr(_yt_player);
  3872.  
  3873.  
  3874. if (!arr) return;
  3875.  
  3876. debug && console.log(`FIX_${evKey}`, arr);
  3877.  
  3878. const f = function (...args) {
  3879. Promise.resolve().then(() => this[fvKey](...args));
  3880. };
  3881.  
  3882.  
  3883. for (const k of arr) {
  3884.  
  3885. const g = _yt_player;
  3886. const gk = g[k];
  3887. const gkp = gk.prototype;
  3888.  
  3889. debug && console.log(237, k, gkp)
  3890.  
  3891. if (typeof gkp[evKey] == 'function' && !gkp[fvKey]) {
  3892. gkp[fvKey] = gkp[evKey];
  3893. gkp[evKey] = f;
  3894. }
  3895. }
  3896.  
  3897.  
  3898.  
  3899.  
  3900. }
  3901.  
  3902. FIX_onVideoDataChange && generalEvtHandler('onVideoDataChange', 'onVideoDataChange57');
  3903. // FIX_onClick && generalEvtHandler('onClick', 'onClick57');
  3904. FIX_onStateChange && generalEvtHandler('onStateChange', 'onStateChange57');
  3905. FIX_onLoopRangeChange && generalEvtHandler('onLoopRangeChange', 'onLoopRangeChange57');
  3906. if (FIX_VideoEVENTS_v2) {
  3907. const FIX_VideoEVENTS_DEBUG = 0;
  3908. generalEvtHandler('onVideoProgress', 'onVideoProgress57', FIX_VideoEVENTS_DEBUG); // --
  3909. // generalEvtHandler('onAutoplayBlocked', 'onAutoplayBlocked57', FIX_VideoEVENTS_DEBUG);
  3910. // generalEvtHandler('onLoadProgress', 'onLoadProgress57', FIX_VideoEVENTS_DEBUG); // << CAUSE ISSUE >>
  3911. generalEvtHandler('onFullscreenChange', 'onFullscreenChange57', FIX_VideoEVENTS_DEBUG); // --
  3912. // generalEvtHandler('onLoadedMetadata', 'onLoadedMetadata57', FIX_VideoEVENTS_DEBUG);
  3913. // generalEvtHandler('onDrmOutputRestricted', 'onDrmOutputRestricted57', FIX_VideoEVENTS_DEBUG);
  3914. // generalEvtHandler('onAirPlayActiveChange', 'onAirPlayActiveChange57', FIX_VideoEVENTS_DEBUG);
  3915. // generalEvtHandler('onAirPlayAvailabilityChange', 'onAirPlayAvailabilityChange57', FIX_VideoEVENTS_DEBUG);
  3916. // generalEvtHandler('onApiChange', 'onApiChange57', FIX_VideoEVENTS_DEBUG);
  3917.  
  3918. }
  3919. // onMutedAutoplayChange
  3920. // onVolumeChange
  3921. // onPlaybackRateChange
  3922.  
  3923. // onAirPlayActiveChange
  3924. // onAirPlayAvailabilityChange
  3925. // onApiChange
  3926. // onAutoplayBlocked
  3927. // onDrmOutputRestricted
  3928. // onFullscreenChange
  3929. // onLoadProgress
  3930. // onLoadedMetadata
  3931. // onVideoDataChange
  3932. // onVideoProgress
  3933.  
  3934.  
  3935. (ENABLE_discreteTasking || UNLOAD_DETACHED_POLYMER) && (async () => {
  3936.  
  3937. const Polymer = await polymerObservable.obtain();
  3938. if (!Polymer) return;
  3939.  
  3940.  
  3941. if (UNLOAD_DETACHED_POLYMER && typeof Polymer.Base.detached === 'function' && !Polymer.Base.detached92 && Polymer.Base.detached.length === 0) {
  3942. Polymer.Base.detached92 = Polymer.Base.detached;
  3943.  
  3944. const detachedPlus = async function (elem) {
  3945. await delay300.then();
  3946. if (elem.isAttached !== false) return;
  3947. await delay300.then();
  3948. if (elem.isAttached !== false) return;
  3949.  
  3950. if (elem.__dataClientsReady === true) elem.__dataClientsReady = false;
  3951. // if (elem.__dataEnabled === true) elem.__dataEnabled = false;
  3952. if (elem.__dataReady === true) elem.__dataReady = false;
  3953.  
  3954. elem.__dataLinkedPaths = elem.__dataToNotify = elem.__dataPendingClients = null;
  3955. elem.__dataHasPaths = false;
  3956. // elem.__dataCompoundStorage = null;
  3957. elem.__dataHost = null;
  3958. elem.__dataTemp = null;
  3959. elem.__dataClientsInitialized = false;
  3960.  
  3961.  
  3962. // elem.data = {};
  3963. elem.data = null;
  3964. elem.__dataPending = null;
  3965. elem.__dataOld = null;
  3966. elem.__dataInstanceProps = null;
  3967.  
  3968. elem.__dataCounter = 0;
  3969. elem.__serializing = false;
  3970.  
  3971. }
  3972. Polymer.Base.detached = function () {
  3973. Promise.resolve(this).then(detachedPlus);
  3974. return Polymer.Base.detached92();
  3975. };
  3976. }
  3977.  
  3978.  
  3979. if (ENABLE_discreteTasking) {
  3980.  
  3981. Polymer.Base.__connInit__ = function () {
  3982. setupDiscreteTasks(this);
  3983. // if (WEAK_REF_BINDING && (this.is || this instanceof Node)) {
  3984. // setupWeakRef(this)
  3985. // }
  3986. }
  3987.  
  3988.  
  3989. /** @type {Function} */
  3990. const connectedCallbackK = function (...args) {
  3991. !this.mh35 && typeof this.__connInit__ === 'function' && this.__connInit__();
  3992. const r = this[qm53](...args);
  3993. !this.mh35 && typeof this.__connInit__ === 'function' && this.__connInit__();
  3994. this.mh35 = 1;
  3995. return r;
  3996. };
  3997.  
  3998. connectedCallbackK.m353 = 1;
  3999.  
  4000.  
  4001. const qt53 = Polymer.Base.connectedCallback;
  4002. Polymer.Base[qm53] = dmf.get(qt53) || qt53;
  4003.  
  4004. Polymer.Base.connectedCallback = connectedCallbackK;
  4005.  
  4006.  
  4007. /** @type {Function} */
  4008. const createdK = function (...args) {
  4009. !this.mh36 && typeof this.__connInit__ === 'function' && this.__connInit__();
  4010. const r = this[qn53](...args);
  4011. !this.mh36 && typeof this.__connInit__ === 'function' && this.__connInit__();
  4012. this.mh36 = 1;
  4013. return r;
  4014. };
  4015.  
  4016.  
  4017. createdK.m353 = 1;
  4018. Polymer.Base[qn53] = Polymer.Base.created;
  4019. Polymer.Base.created = createdK;
  4020.  
  4021. }
  4022.  
  4023. })();
  4024.  
  4025.  
  4026. /*
  4027.  
  4028. e.nativeAppendChild = d.prototype.appendChild,
  4029. d.prototype.appendChild = function(h) {
  4030. return function(l) {
  4031. if (l instanceof DocumentFragment) {
  4032. var m = Array.from(l.children);
  4033. l = h.nativeAppendChild.call(this, l);
  4034. if (this.isConnected) {
  4035. m = g(m);
  4036. for (var p = m.next(); !p.done; p = m.next())
  4037. YD(p.value)
  4038. }
  4039. return l
  4040. }
  4041. m = l instanceof Element && l.isConnected;
  4042. p = h.nativeAppendChild.call(this, l);
  4043. m && ZD(l);
  4044. this.isConnected && YD(l);
  4045. return p
  4046. }
  4047. }(e),
  4048.  
  4049. */
  4050.  
  4051. CHANGE_appendChild && !Node.prototype.appendChild73 && Node.prototype.appendChild && (() => {
  4052.  
  4053. let __src__ = '';
  4054. const handlerCanplay = (evt) => {
  4055. const a = evt.target;
  4056. console.log('[yt-js-engine-tamer]', `video element added to dom | canplay`, mWeakRef(a), a.readyState, a.networkState, a.currentTime);
  4057. if (a.currentTime < 1e-8 && a.currentTime > -1e-9 && a.autoplay === false) a.currentTime += 1e-8;
  4058. };
  4059.  
  4060. const handlerTimeupdate = (evt) => {
  4061. const a = evt.target;
  4062. console.log('[yt-js-engine-tamer]', `video element added to dom | ontimeupdate`, mWeakRef(a), a.readyState, a.networkState, a.currentTime);
  4063. if (a.duration < 2.01 && a.duration > 1.99 && a.currentSrc === __src__) {
  4064. try {
  4065. URL.revokeObjectURL(__src__);
  4066. __src__ = '';
  4067. } finally {
  4068. console.log('[yt-js-engine-tamer]', `video element added to dom | revokeObjectURL`, mWeakRef(a), a.readyState, a.networkState, a.currentTime);
  4069. }
  4070. }
  4071. };
  4072.  
  4073. const f = Node.prototype.appendChild73 = Node.prototype.appendChild;
  4074. if (f) Node.prototype.appendChild = function (a) {
  4075. if (this instanceof Element) { // exclude DocumentFragment
  4076. try {
  4077. if (a instanceof HTMLVideoElement && FIX_VIDEO_BLOCKING) {
  4078. const src = `${a.src}`;
  4079. const b = src.length > 5 && src.startsWith('blob:') && typeof a.ontimeupdate === 'function' && a.autoplay === false && a.paused === true && a.isConnected === false && typeof nextBrowserTick === 'function' && typeof AbortSignal !== 'undefined';
  4080. if (b) {
  4081. __src__ = src;
  4082. a.addEventListener('canplay', handlerCanplay, { once: true, passive: true, capture: false });
  4083. a.addEventListener('timeupdate', handlerTimeupdate, { once: true, passive: true, capture: false });
  4084. }
  4085. console.log('[yt-js-engine-tamer]', `video element added to dom | treatment = ${b}`, mWeakRef(a), a.readyState, a.networkState);
  4086. } else {
  4087. let checkFragmentA = true;
  4088. if (!NO_PRELOAD_GENERATE_204_BYPASS && document.head === this) {
  4089. if (headLinkCollection === null) headLinkCollection = document.head.getElementsByTagName('LINK');
  4090. for (const node of headLinkCollection) {
  4091. if (node.rel === 'preload' && node.as === 'fetch') {
  4092. node.rel = 'prefetch'; // see https://github.com/GoogleChromeLabs/quicklink
  4093. }
  4094. }
  4095. } else if (this.nodeName.startsWith('YT-')) { // yt-animated-rolling-number, yt-attributed-string
  4096. checkFragmentA = false;
  4097. }
  4098. if ((a instanceof DocumentFragment) && checkFragmentA && a.firstElementChild === null) {
  4099. // no element in fragmentA
  4100. let doNormal = false;
  4101. for (let child = a.firstChild; child instanceof Node; child = child.nextSibling) {
  4102. if (child.nodeType === 3) { doNormal = true; break; }
  4103. }
  4104. if (!doNormal) return a;
  4105. }
  4106. }
  4107. } catch (e) {
  4108. console.log(e);
  4109. }
  4110. }
  4111. return arguments.length === 1 && this.appendChild73 ? this.appendChild73(a) : (this.appendChild73 || Node.prototype.appendChild73 || f).apply(this, arguments);
  4112. }
  4113.  
  4114.  
  4115. })();
  4116.  
  4117. if (FIX_Shady) {
  4118.  
  4119. observablePromise(() => {
  4120. const { ShadyDOM, ShadyCSS } = window;
  4121. if (ShadyDOM) {
  4122. ShadyDOM.handlesDynamicScoping = false; // 9 of 10
  4123. ShadyDOM.noPatch = true; // 1 of 10
  4124. ShadyDOM.patchOnDemand = false; // 1 of 10
  4125. ShadyDOM.preferPerformance = true; // 1 of 10
  4126. ShadyDOM.querySelectorImplementation = undefined; // 1 of 10
  4127. }
  4128. if (ShadyCSS) {
  4129. ShadyCSS.nativeCss = true; // 1 of 10
  4130. ShadyCSS.nativeShadow = true; // 6 of 10
  4131. ShadyCSS.cssBuild = undefined; // 1 of 10
  4132. ShadyCSS.disableRuntime = true; // 1 of 10
  4133. }
  4134. if (ShadyDOM && ShadyCSS) return 1;
  4135. }, promiseForTamerTimeout).obtain(); // clear until 1 is return
  4136.  
  4137. }
  4138.  
  4139.  
  4140. // let schedulerInstancePropOfTimerType = '';
  4141. // let schedulerInstancePropOfTimerId = '';
  4142. (FIX_schedulerInstanceInstance & 2) && (async () => {
  4143.  
  4144. const schedulerInstanceInstance_ = await schedulerInstanceObservable.obtain();
  4145.  
  4146. if (!schedulerInstanceInstance_) return;
  4147.  
  4148. const checkOK = typeof schedulerInstanceInstance_.start === 'function' && !schedulerInstanceInstance_.start993 && !schedulerInstanceInstance_.stop && !schedulerInstanceInstance_.cancel && !schedulerInstanceInstance_.terminate && !schedulerInstanceInstance_.interupt;
  4149. if (checkOK) {
  4150.  
  4151. schedulerInstanceInstance_.start993 = schedulerInstanceInstance_.start;
  4152.  
  4153. let requestingFn = null;
  4154. let requestingArgs = null;
  4155.  
  4156. const f = function () {
  4157. requestingFn = this.fn;
  4158. requestingArgs = [...arguments];
  4159. return 12373;
  4160. };
  4161.  
  4162. const fakeFns = [
  4163. f.bind({ fn: requestAnimationFrame }),
  4164. f.bind({ fn: setInterval }),
  4165. f.bind({ fn: setTimeout }),
  4166. f.bind({ fn: requestIdleCallback })
  4167. ];
  4168.  
  4169. let mzt = 0;
  4170.  
  4171. let _fnSelectorProp = null;
  4172. const mkFns = new Array(4);
  4173.  
  4174. /*
  4175. case 1:
  4176. var a = this.K;
  4177. this.g = this.I ? window.requestIdleCallback(a, {
  4178. timeout: 3E3
  4179. }) : window.setTimeout(a, ma);
  4180. break;
  4181. case 2:
  4182. this.g = window.setTimeout(this.M, this.N);
  4183. break;
  4184. case 3:
  4185. this.g = window.requestAnimationFrame(this.L);
  4186. break;
  4187. case 4:
  4188. this.g = window.setTimeout(this.J, 0)
  4189. }
  4190.  
  4191. */
  4192. const startFnHandler = {
  4193. get(target, prop, receiver) {
  4194. if (prop === '$$12377$$') return true;
  4195. if (prop === '$$12378$$') return target;
  4196.  
  4197. // console.log('get',prop)
  4198. return target[prop]
  4199. },
  4200. set(target, prop, value, receiver) {
  4201. // console.log('set', prop, value)
  4202.  
  4203. if (value >= 1 && value <= 4) _fnSelectorProp = prop;
  4204. if (value === 12373 && _fnSelectorProp) {
  4205.  
  4206. const schedulerTypeSelection = target[_fnSelectorProp];
  4207. const timerIdProp = prop;
  4208.  
  4209. // if (schedulerTypeSelection && schedulerTypeSelection >= 1 && schedulerTypeSelection <= 4 && timerIdProp) {
  4210. // schedulerInstancePropOfTimerType = _fnSelectorProp || '';
  4211. // schedulerInstancePropOfTimerId = timerIdProp || '';
  4212. // }
  4213.  
  4214. if (schedulerTypeSelection === 3 && requestingFn === requestAnimationFrame) { // rAF(fn)
  4215. target[timerIdProp] = baseRAF.apply(window, requestingArgs);
  4216. } else if (schedulerTypeSelection === 2 && requestingFn === setTimeout) { // setTimeout(fn, delay)
  4217. // rare
  4218. target[timerIdProp] = mkFns[2].apply(window, requestingArgs);
  4219. } else if (schedulerTypeSelection === 4 && requestingFn === setTimeout && !requestingArgs[1]) { // setTimeout(fn, 0)
  4220. // often
  4221. if ((FIX_schedulerInstanceInstance & 4) && typeof nextBrowserTick == 'function') {
  4222. const f = requestingArgs[0];
  4223. const tir = ++mzt;
  4224. nextBrowserTick(() => {
  4225. if (target[timerIdProp] === -tir) f();
  4226. });
  4227. target[_fnSelectorProp] = 940;
  4228. target[timerIdProp] = -tir;
  4229. } else {
  4230. const f = requestingArgs[0];
  4231. const tir = ++mzt;
  4232. Promise.resolve().then(() => {
  4233. if (target[timerIdProp] === -tir) f();
  4234. });
  4235. target[_fnSelectorProp] = 930;
  4236. target[timerIdProp] = -tir;
  4237. }
  4238. } else if (schedulerTypeSelection === 1 && (requestingFn === requestIdleCallback || requestingFn === setTimeout)) { // setTimeout(requestIdleCallback)
  4239. // often
  4240. if (requestingFn === requestIdleCallback) {
  4241. target[timerIdProp] = requestIdleCallback.apply(window, requestingArgs);
  4242. } else {
  4243. target[timerIdProp] = mkFns[2].apply(window, requestingArgs);
  4244. }
  4245. } else {
  4246. target[_fnSelectorProp] = 0;
  4247. target[timerIdProp] = 0;
  4248. }
  4249. } else {
  4250. target[prop] = value;
  4251. }
  4252. return true;
  4253. }
  4254. };
  4255.  
  4256. let startBusy = false;
  4257. schedulerInstanceInstance_.start = function () {
  4258. if (startBusy) return;
  4259. startBusy = true;
  4260. try {
  4261. mkFns[0] = window.requestAnimationFrame;
  4262. mkFns[1] = window.setInterval;
  4263. mkFns[2] = window.setTimeout;
  4264. mkFns[3] = window.requestIdleCallback;
  4265. const tThis = this['$$12378$$'] || this;
  4266. window.requestAnimationFrame = fakeFns[0]
  4267. window.setInterval = fakeFns[1]
  4268. window.setTimeout = fakeFns[2]
  4269. window.requestIdleCallback = fakeFns[3]
  4270. _fnSelectorProp = null;
  4271. tThis.start993.call(new Proxy(tThis, startFnHandler));
  4272. _fnSelectorProp = null;
  4273. window.requestAnimationFrame = mkFns[0];
  4274. window.setInterval = mkFns[1];
  4275. window.setTimeout = mkFns[2];
  4276. window.requestIdleCallback = mkFns[3];
  4277. } catch (e) {
  4278. console.warn(e);
  4279. }
  4280. startBusy = false;
  4281. }
  4282.  
  4283. schedulerInstanceInstance_.start.toString = schedulerInstanceInstance_.start993.toString.bind(schedulerInstanceInstance_.start993);
  4284.  
  4285. }
  4286. })();
  4287.  
  4288. FIX_yt_player && (async () => {
  4289. // rAf scheduling
  4290.  
  4291. const _yt_player = await _yt_player_observable.obtain();
  4292.  
  4293. if (!_yt_player || typeof _yt_player !== 'object') return;
  4294.  
  4295. let keyZqOu = getZqOu(_yt_player);
  4296.  
  4297.  
  4298. if (!keyZqOu) return;
  4299.  
  4300.  
  4301. const g = _yt_player
  4302. let k = keyZqOu
  4303.  
  4304. const gk = g[k];
  4305. if (typeof gk !== 'function') return;
  4306. const gkp = gk.prototype;
  4307.  
  4308. let dummyObject = new gk;
  4309. let nilFunc = () => { };
  4310.  
  4311. let nilObj = {};
  4312.  
  4313. // console.log(1111111111)
  4314.  
  4315. let keyBoolD = '';
  4316. let keyWindow = '';
  4317. let keyFuncC = '';
  4318. let keyCidj = '';
  4319.  
  4320. for (const [t, y] of Object.entries(dummyObject)) {
  4321. if (y instanceof Window) keyWindow = t;
  4322. }
  4323.  
  4324. const dummyObjectProxyHandler = {
  4325. get(target, prop) {
  4326. let v = target[prop]
  4327. if (v instanceof Window && !keyWindow) {
  4328. keyWindow = t;
  4329. }
  4330. let y = typeof v === 'function' ? nilFunc : typeof v === 'object' ? nilObj : v;
  4331. if (prop === keyWindow) y = {
  4332. requestAnimationFrame(f) {
  4333. return 3;
  4334. },
  4335. cancelAnimationFrame() {
  4336.  
  4337. }
  4338. }
  4339. if (!keyFuncC && typeof v === 'function' && !(prop in target.constructor.prototype)) {
  4340. keyFuncC = prop;
  4341. }
  4342. // console.log('[get]', prop, typeof target[prop])
  4343.  
  4344.  
  4345. return y;
  4346. },
  4347. set(target, prop, value) {
  4348.  
  4349. if (typeof value === 'boolean' && !keyBoolD) {
  4350. keyBoolD = prop;
  4351. }
  4352. if (typeof value === 'number' && !keyCidj && value >= 2) {
  4353. keyCidj = prop;
  4354. }
  4355.  
  4356. // console.log('[set]', prop, value)
  4357. target[prop] = value
  4358.  
  4359. return true;
  4360. }
  4361. };
  4362.  
  4363. dummyObject.start.call(new Proxy(dummyObject, dummyObjectProxyHandler));
  4364.  
  4365. // console.log('gkp.start',gkp.start);
  4366. // console.log('gkp.stop',gkp.stop);
  4367. gkp._activation = false;
  4368.  
  4369. gkp.start = function () {
  4370. // p59 || console.log(12100)
  4371. if (!this._activation) {
  4372. this._activation = true;
  4373. getRafPromise().then(() => {
  4374. this._activation = false;
  4375. if (this[keyCidj]) {
  4376. Promise.resolve().then(this[keyFuncC]);
  4377. }
  4378. });
  4379. }
  4380. this[keyCidj] = 1;
  4381. this[keyBoolD] = true;
  4382. }
  4383. ;
  4384. gkp.stop = function () {
  4385. this[keyCidj] = null
  4386. }
  4387.  
  4388.  
  4389. /*
  4390. g[k].start = function() {
  4391. this.stop();
  4392. this.D = true;
  4393. var a = requestAnimationFrame
  4394. , b = cancelAnimationFrame;
  4395. this.j = a.call(this.B, this.C)
  4396. }
  4397. ;
  4398. g[k].stop = function() {
  4399. if (this.isActive()) {
  4400. var a = requestAnimationFrame
  4401. , b = cancelAnimationFrame;
  4402. b.call(this.B, this.j)
  4403. }
  4404. this.j = null
  4405. }
  4406. */
  4407.  
  4408. const keyzo = PERF_471489_ ? getzo(_yt_player) : null;
  4409.  
  4410. if (keyzo) {
  4411.  
  4412. k = keyzo;
  4413.  
  4414. const attrUpdateFn = g[k];
  4415. // console.log(5992, attrUpdateFn)
  4416. g['$$original$$' + k] = attrUpdateFn;
  4417. const zoTransform = async (a, c) => {
  4418.  
  4419. let transformType = '';
  4420. let transformValue = 0;
  4421. let transformUnit = '';
  4422. let transformTypeI = 0;
  4423.  
  4424. const aStyle = a.style;
  4425.  
  4426. if (c.length < 9) {
  4427.  
  4428. } else if (c.startsWith('scalex(0.') || (c === 'scalex(0)' || c === 'scalex(1)')) {
  4429. let p = c.substring(7, c.length - 1);
  4430. let q = p.length >= 1 ? parseFloat(p) : -1;
  4431. if (q > -1e-5 && q < 1 + 1e-5) {
  4432. transformType = 'scaleX'
  4433. transformValue = q;
  4434. transformUnit = '';
  4435. transformTypeI = 1;
  4436. }
  4437. } else if (c.startsWith('translateX(') && c.endsWith('px)')) {
  4438. let p = c.substring(11, c.length - 3);
  4439. let q = p.length >= 1 ? parseFloat(p) : NaN;
  4440. if (typeof q === 'number' && !isNaN(q)) {
  4441. transformType = 'translateX'
  4442. transformValue = q;
  4443. transformUnit = 'px';
  4444. transformTypeI = 2;
  4445. } else if (p === 'NaN') {
  4446. return;
  4447. }
  4448. } else if (c.startsWith('scaley(0.') || (c === 'scaley(0)' || c === 'scaley(1)')) {
  4449. let p = c.substring(7, c.length - 1);
  4450. let q = p.length >= 1 ? parseFloat(p) : -1;
  4451. if (q > -1e-5 && q < 1 + 1e-5) {
  4452. transformType = 'scaleY'
  4453. transformValue = q;
  4454. transformUnit = '';
  4455. transformTypeI = 1;
  4456. }
  4457. } else if (c.startsWith('translateY(') && c.endsWith('px)')) {
  4458. let p = c.substring(11, c.length - 3);
  4459. let q = p.length >= 1 ? parseFloat(p) : NaN;
  4460. if (typeof q === 'number' && !isNaN(q)) {
  4461. transformType = 'translateY'
  4462. transformValue = q;
  4463. transformUnit = 'px';
  4464. transformTypeI = 2;
  4465. } else if (p === 'NaN') {
  4466. return;
  4467. }
  4468. } else if (c.startsWith('scalex(') && c.includes('e-')) {
  4469. // scalex(1.252057684158767e-16)
  4470. // scalex(3.0393632069734948e-9)
  4471. let p = c.substring(7, c.length - 1);
  4472. let q = p.length >= 1 ? parseFloat(p) : -1;
  4473. if (q > -1e-5 && q < 1e-5) {
  4474. transformType = 'scaleX'
  4475. transformValue = 0;
  4476. transformUnit = '';
  4477. transformTypeI = 1;
  4478. }
  4479. } else if (c.startsWith('scaley(') && c.includes('e-')) {
  4480. let p = c.substring(7, c.length - 1);
  4481. let q = p.length >= 1 ? parseFloat(p) : -1;
  4482. if (q > -1e-5 && q < 1e-5) {
  4483. transformType = 'scaleY'
  4484. transformValue = 0;
  4485. transformUnit = '';
  4486. transformTypeI = 1;
  4487. }
  4488. }
  4489.  
  4490. if (transformTypeI === 1) {
  4491. const q = Math.round(transformValue * steppingScaleN) / steppingScaleN;
  4492. const vz = toFixed2(q, 3);
  4493. c = `${transformType}(${vz})`;
  4494. const cv = aStyle.transform;
  4495. if (c === cv) return;
  4496. aStyle.transform = c;
  4497. } else if (transformTypeI === 2) {
  4498. const q = transformValue;
  4499. const vz = toFixed2(q, 1);
  4500. c = `${transformType}(${vz}${transformUnit})`;
  4501. const cv = aStyle.transform;
  4502. if (c === cv) return;
  4503. aStyle.transform = c;
  4504. } else { // eg empty
  4505. const cv = aStyle.transform;
  4506. if (!c && !cv) return;
  4507. else if (c === cv) return;
  4508. aStyle.transform = c;
  4509. }
  4510.  
  4511. };
  4512.  
  4513. const elmTransformTemp = new WeakMap();
  4514. const elmPropTemps = {
  4515. 'display': new WeakMap(),
  4516. 'width': new WeakMap(),
  4517. 'height': new WeakMap(),
  4518. 'outlineWidth': new WeakMap(),
  4519. 'position': new WeakMap(),
  4520. 'padding': new WeakMap(),
  4521. "cssText": new WeakMap(),
  4522. "right": new WeakMap(),
  4523. "left": new WeakMap(),
  4524. "top": new WeakMap(),
  4525. "bottom": new WeakMap(),
  4526. "transitionDelay": new WeakMap(),
  4527. "marginLeft": new WeakMap(),
  4528. "marginTop": new WeakMap(),
  4529. "marginRight": new WeakMap(),
  4530. "marginBottom": new WeakMap(),
  4531. }
  4532.  
  4533. const ns5 = Symbol();
  4534. const nextModify = (a, c, m, f, immediate) => {
  4535. const a_ = a;
  4536. const m_ = m;
  4537. const noKey = !m_.has(a_);
  4538. if (immediate || noKey) {
  4539. m_.set(a_, ns5);
  4540. f(a_, c);
  4541. noKey && nextBrowserTick_(() => {
  4542. const d = m_.get(a_);
  4543. if (d === undefined) return;
  4544. m_.delete(a_);
  4545. if (d !== ns5) f(a_, d);
  4546. });
  4547. } else {
  4548. m_.set(a_, c);
  4549. }
  4550. };
  4551.  
  4552. const set66 = new Set();
  4553. // const set77 = new Set(['top', 'left', 'bottom', 'right']); // caption positioning - immediate change
  4554.  
  4555. const modifiedFn = function (a, b, c, immediateChange = false) { // arrow function does not have function.prototype
  4556.  
  4557. // console.log(140000, a, b, c);
  4558. if (typeof c === 'number' && typeof b === 'string' && a instanceof HTMLElement) {
  4559. const num = c;
  4560. c = `${num}`;
  4561. if (c.length > 5) c = (num < 10 && num > -10) ? toFixed2(num, 3) : toFixed2(num, 1);
  4562. }
  4563.  
  4564. if (typeof b === 'string' && typeof c === 'string' && a instanceof HTMLElement) {
  4565.  
  4566. let elmPropTemp = null;
  4567.  
  4568. if (b === "transform") {
  4569.  
  4570. nextModify(a, c, elmTransformTemp, zoTransform, immediateChange);
  4571. return;
  4572.  
  4573. } else if (elmPropTemp = elmPropTemps[b]) {
  4574.  
  4575. // if (c.length > 5 && c.includes('.')) {
  4576. // console.log(123213, c)
  4577. // }
  4578.  
  4579. const b_ = b;
  4580. nextModify(a, c, elmPropTemp, (a, c) => {
  4581. const style = a.style;
  4582. const cv = style[b_];
  4583. if (!cv && !c) return;
  4584. if (cv === c) return;
  4585. style[b_] = c;
  4586. }, immediateChange);
  4587. return;
  4588.  
  4589. } else if (b === "outline-width") {
  4590.  
  4591. const b_ = 'outlineWidth';
  4592. elmPropTemp = elmPropTemps[b_];
  4593. nextModify(a, c, elmPropTemp, (a, c) => {
  4594. const style = a.style;
  4595. const cv = style[b_];
  4596. if (!cv && !c) return;
  4597. if (cv === c) return;
  4598. style[b_] = c;
  4599. }, immediateChange);
  4600. return;
  4601.  
  4602. } else if (b === 'maxWidth' || b === 'maxHeight') {
  4603. // I think these can be directly assigned.
  4604.  
  4605. const b_ = b;
  4606. const style = a.style;
  4607. const cv = style[b_];
  4608. if (!cv && !c) return;
  4609. if (cv === c) return;
  4610. style[b_] = c;
  4611. return;
  4612.  
  4613. } else {
  4614. // if(immediate && elmPropTemps[b]){
  4615. // console.log(5191, b)
  4616. // }
  4617. // caption-window
  4618. // margin-left max-height max-width font-family fill color font-size background white-space margin
  4619. // text-align background-color
  4620. // console.log(27304, a, b, c)
  4621. if (!set66.has(b)) {
  4622. set66.add(b);
  4623. nextBrowserTick_(() => {
  4624. if (!a.classList.contains('caption-window') && !a.classList.contains('ytp-caption-segment')) {
  4625. console.log(27304, a, b, c)
  4626. }
  4627. })
  4628. }
  4629. }
  4630.  
  4631. attrUpdateFn.call(this, a, b, c);
  4632. return;
  4633. } else if (typeof (b || 0) === 'object') {
  4634.  
  4635. // this is to fix caption positioning
  4636. // const immediate = (a.id || 0).length > 14 && (('top' in b) || ('left' in b) || ('right' in b) || ('bottom' in b));
  4637. const immediate = (a.id || 0).length > 14;
  4638. for (const [k, v] of Object.entries(b)) {
  4639. modifiedFn.call(this, a, k, v, immediate);
  4640. }
  4641.  
  4642. } else {
  4643. console.log(27306, a, b, c);
  4644.  
  4645. attrUpdateFn.call(this, a, b, c);
  4646. return;
  4647. }
  4648.  
  4649. // console.log(130000, a, b, c);
  4650.  
  4651. };
  4652. g[k] = modifiedFn;
  4653.  
  4654.  
  4655. /*
  4656.  
  4657. g.zo = function(a, b, c) {
  4658. if ("string" === typeof b)
  4659. (b = yo(a, b)) && (a.style[b] = c);
  4660. else
  4661. for (var d in b) {
  4662. c = a;
  4663. var e = b[d]
  4664. , f = yo(c, d);
  4665. f && (c.style[f] = e)
  4666. }
  4667. }
  4668.  
  4669.  
  4670. */
  4671.  
  4672.  
  4673. }
  4674.  
  4675.  
  4676.  
  4677. const keyuG = PERF_471489_ ? getuG(_yt_player) : null;
  4678.  
  4679. if (keyuG) {
  4680.  
  4681. k = keyuG;
  4682.  
  4683. const gk = g[k];
  4684. const gkp = gk.prototype;
  4685.  
  4686.  
  4687. /** @type { Map<string, WeakMap<any, any>> } */
  4688. const ntLogs = new Map();
  4689.  
  4690. if (typeof gkp.updateValue === 'function' && gkp.updateValue.length === 2 && !gkp.updateValue31) {
  4691.  
  4692. gkp.updateValue31 = gkp.updateValue;
  4693. gkp.updateValue = function (a, b) {
  4694. if (typeof a !== 'string') return this.updateValue31(a, b);
  4695.  
  4696. const element = this.element;
  4697. if (!(element instanceof HTMLElement)) return this.updateValue31(a, b);
  4698.  
  4699. let ntLog = ntLogs.get(a);
  4700. if (!ntLog) ntLogs.set(a, (ntLog = new WeakMap()));
  4701.  
  4702. let cache = ntLog.get(element);
  4703. if (cache && cache.value === b) {
  4704. return;
  4705. }
  4706. if (!cache) {
  4707. this.__oldValueByUpdateValue__ = null;
  4708. ntLog.set(element, cache = { value: b });
  4709. } else {
  4710. this.__oldValueByUpdateValue__ = cache.value;
  4711. cache.value = b;
  4712. }
  4713.  
  4714. return this.updateValue31(a, b);
  4715. }
  4716.  
  4717. /*
  4718. g.k.update = function(a) {
  4719. for (var b = g.u(Object.keys(a)), c = b.next(); !c.done; c = b.next())
  4720. c = c.value,
  4721. this.updateValue(c, a[c])
  4722. }
  4723. ;
  4724. g.k.updateValue = function(a, b) {
  4725. (a = this.Td["{{" + a + "}}"]) && wG(this, a[0], a[1], b)
  4726. }
  4727. */
  4728.  
  4729. }
  4730.  
  4731.  
  4732. }
  4733.  
  4734.  
  4735.  
  4736.  
  4737. })();
  4738.  
  4739.  
  4740. FIX_yt_player && FIX_SHORTCUTKEYS > 0 && (async () => {
  4741. // keyboard shortcut keys controller
  4742.  
  4743. const _yt_player = await _yt_player_observable.obtain();
  4744.  
  4745. if (!_yt_player || typeof _yt_player !== 'object') return;
  4746.  
  4747. keyboardController(_yt_player);
  4748.  
  4749. })();
  4750.  
  4751. FIX_yt_player && (async () => {
  4752. // timer scheduling
  4753.  
  4754. const _yt_player = await _yt_player_observable.obtain();
  4755.  
  4756. if (!_yt_player || typeof _yt_player !== 'object') return;
  4757.  
  4758. let keyZqQu = getZqQu(_yt_player);
  4759.  
  4760. if (!keyZqQu) return;
  4761.  
  4762. const g = _yt_player
  4763. let k = keyZqQu
  4764.  
  4765. const gk = g[k];
  4766. if (typeof gk !== 'function') return;
  4767. const gkp = gk.prototype;
  4768.  
  4769. const extractKeysZqQu = () => {
  4770.  
  4771.  
  4772. let _keyeC = '';
  4773. try {
  4774. gkp.stop.call(new Proxy({
  4775. isActive: () => { }
  4776. }, {
  4777. set(target, prop, value) {
  4778. if (value === 0) _keyeC = prop;
  4779. return true;
  4780. }
  4781. }));
  4782. } catch (e) { }
  4783. if (!_keyeC) return;
  4784. const keyeC = _keyeC;
  4785.  
  4786. let keyC = ''; // this.C = this.ST.bind(this)
  4787. let keyhj = ''; // 1000ms
  4788. try {
  4789. gkp.start.call(new Proxy({
  4790. stop: () => { },
  4791. [keyeC]: 0,
  4792. }, {
  4793. get(target, prop) {
  4794. if (prop in target) return target[prop];
  4795. if (!keyC) {
  4796. keyC = prop;
  4797. return null; // throw error
  4798. }
  4799. else if (!keyhj) {
  4800. keyhj = prop;
  4801. }
  4802.  
  4803. }
  4804. }));
  4805. } catch (e) {
  4806. if (!keyC || !keyhj) {
  4807. console.log(e)
  4808. }
  4809. }
  4810.  
  4811. if (!keyC || !keyhj) return;
  4812. let keyST = '';
  4813. let keyj = '';
  4814. let keyB = '';
  4815. let keyxa = '';
  4816.  
  4817. const possibleKs = new Set();
  4818.  
  4819. for (const [k, v] of Object.entries(gkp)) {
  4820. if (k === 'stop' || k === 'start' || k === 'isActive' || k === 'constructor' || k === keyeC || k === keyC || k === keyhj) {
  4821. continue;
  4822. }
  4823. if (typeof v === 'function') {
  4824. const m = /this\.(\w+)\.call\(this\.(\w+)\)/.exec(v + '');
  4825. if (m) {
  4826. keyST = k;
  4827. keyj = m[1];
  4828. keyB = m[2];
  4829. } else {
  4830. possibleKs.add(k);
  4831. }
  4832. }
  4833. }
  4834.  
  4835. if (!keyST || !keyj || !keyB) return;
  4836.  
  4837. for (const k of possibleKs) {
  4838. if (k === keyST || k === keyj || k === keyB) {
  4839. continue;
  4840. }
  4841. const v = gkp[k];
  4842. if (typeof v === 'function' && (v + '').includes(`this.stop();delete this.${keyj};delete this.${keyB}`)) {
  4843. keyxa = k;
  4844. }
  4845. }
  4846.  
  4847. return [keyeC, keyC, keyhj, keyST, keyj, keyB, keyxa];
  4848.  
  4849. }
  4850.  
  4851. const keys = extractKeysZqQu();
  4852. if (!keys || !keys.length) return;
  4853. const [keyeC, keyC, keyhj, keyST, keyj, keyB, keyxa] = keys; // [timerId, binded executorFn, 1000ms, executorFn, dataJ, objectB, disposeFn]
  4854.  
  4855. if (!keyeC || !keyC || !keyhj || !keyST || !keyj || !keyB || !keyxa) return;
  4856.  
  4857. let disposeKeys = null;
  4858.  
  4859. gkp[keyxa] = function () {
  4860. // dispose
  4861. if (!disposeKeys) {
  4862. disposeKeys = Object.getOwnPropertyNames(this).filter(key => {
  4863. if (key != keyeC && key != keyC && key != keyhj && key != keyST && key != keyj && key != keyB && key != keyxa) {
  4864. const t = typeof this[key];
  4865. return t === 'undefined' || t === 'object'
  4866. }
  4867. return false;
  4868. });
  4869. }
  4870. for (const key of disposeKeys) {
  4871. const v = this[key];
  4872. if ((v || 0).length >= 1) v.length = 0; // function (){if(this.fn)for(;this.fn.length;)this.fn.shift()()}
  4873. }
  4874. if (this[keyeC] > 0) this.stop();
  4875. this[keyj] = null;
  4876. this[keyB] = null;
  4877. };
  4878.  
  4879. gkp.start = function (a) {
  4880. if (this[keyeC] > 0) this.stop();
  4881. const delay = void 0 !== a ? a : this[keyhj];
  4882. this[keyeC] = window.setTimeout(this[keyC], delay);
  4883. };
  4884. gkp.stop = function () {
  4885. if (this[keyeC] > 0) {
  4886. window.clearTimeout(this[keyeC]);
  4887. this[keyeC] = 0;
  4888. }
  4889. };
  4890.  
  4891. gkp.isActive = function () {
  4892. return this[keyeC] > 0;
  4893. };
  4894.  
  4895. gkp[keyST] = function () {
  4896. this.stop(); // this[keyeC] = 0;
  4897. const fn = this[keyj];
  4898. const obj = this[keyB];
  4899. let skip = false;
  4900. if (!fn) skip = true;
  4901. else if (IGNORE_bufferhealth_CHECK && obj) {
  4902. let m;
  4903. if ((m = obj[keyC]) instanceof Map || (m = obj[keyj]) instanceof Map) {
  4904. if (m.has("bufferhealth")) skip = true;
  4905. }
  4906. }
  4907. if (!skip) {
  4908. fn.call(obj);
  4909. }
  4910. };
  4911.  
  4912.  
  4913.  
  4914.  
  4915. /*
  4916.  
  4917. g.k.eC = 0;
  4918. g.k.xa = function() {
  4919. g.Qu.Vf.xa.call(this);
  4920. this.stop();
  4921. delete this.j;
  4922. delete this.B
  4923. }
  4924. ;
  4925. g.k.start = function(a) {
  4926. this.stop();
  4927. this.eC = g.gg(this.C, void 0 !== a ? a : this.hj)
  4928. }
  4929. ;
  4930. g.k.stop = function() {
  4931. this.isActive() && g.Sa.clearTimeout(this.eC);
  4932. this.eC = 0
  4933. }
  4934. ;
  4935. g.k.isActive = function() {
  4936. return 0 != this.eC
  4937. }
  4938. ;
  4939. g.k.ST = function() {
  4940. this.eC = 0;
  4941. this.j && this.j.call(this.B)
  4942. }
  4943. ;
  4944. */
  4945.  
  4946.  
  4947.  
  4948.  
  4949. })();
  4950.  
  4951. FIX_Animation_n_timeline && (async () => {
  4952.  
  4953. const [timeline, Animation] = await Promise.all([timelineObservable.obtain(), animationObservable.obtain()]);
  4954.  
  4955. if (!timeline || !Animation) return;
  4956.  
  4957. const aniProto = Animation.prototype;
  4958. // aniProto.sequenceNumber = 0; // native YouTube engine bug - sequenceNumber is not set
  4959.  
  4960. const getXroto = (x) => {
  4961. try {
  4962. return x.__proto__;
  4963. } catch (e) { }
  4964. return null;
  4965. }
  4966. const timProto = getXroto(timeline);
  4967. if (!timProto) return;
  4968. if (
  4969. (
  4970. typeof timProto.getAnimations === 'function' && typeof timProto.play === 'function' &&
  4971. typeof timProto._discardAnimations === 'function' && typeof timProto._play === 'function' &&
  4972. typeof timProto._updateAnimationsPromises === 'function' && !timProto.nofCQ &&
  4973. typeof aniProto._updatePromises === 'function' && !aniProto.nofYH
  4974. )
  4975.  
  4976. ) {
  4977.  
  4978. timProto.nofCQ = 1;
  4979. aniProto.nofYH = 1;
  4980.  
  4981. const originalAnimationsWithPromises = ((_updateAnimationsPromises) => {
  4982.  
  4983.  
  4984. /*
  4985. v.animationsWithPromises = v.animationsWithPromises.filter(function (c) {
  4986. return c._updatePromises();
  4987. });
  4988. */
  4989.  
  4990. const p = Array.prototype.filter;
  4991.  
  4992. let res = null;
  4993. Array.prototype.filter = function () {
  4994.  
  4995. res = this;
  4996. return this;
  4997.  
  4998. };
  4999.  
  5000. _updateAnimationsPromises.call({});
  5001.  
  5002. Array.prototype.filter = p;
  5003.  
  5004. if (res && typeof res.length === 'number') {
  5005. /** @type {any[]} */
  5006. const _res = res;
  5007. return _res;
  5008. }
  5009.  
  5010.  
  5011. return null;
  5012.  
  5013.  
  5014.  
  5015.  
  5016. })(timProto._updateAnimationsPromises);
  5017.  
  5018. if (!originalAnimationsWithPromises || typeof originalAnimationsWithPromises.length !== 'number') return;
  5019.  
  5020. // console.log('originalAnimationsWithPromises', originalAnimationsWithPromises)
  5021.  
  5022. aniProto._updatePromises31 = aniProto._updatePromises;
  5023.  
  5024. /*
  5025. aniProto._updatePromises = function(){
  5026. console.log('eff',this._oldPlayState, this.playState)
  5027. return this._updatePromises31.apply(this, arguments)
  5028. }
  5029. */
  5030.  
  5031. aniProto._updatePromises = function () {
  5032. var oldPlayState = this._oldPlayState;
  5033. var newPlayState = this.playState;
  5034. // console.log('ett', oldPlayState, newPlayState)
  5035. if (newPlayState !== oldPlayState) {
  5036. this._oldPlayState = newPlayState;
  5037. if (this._readyPromise) {
  5038. if ("idle" == newPlayState) {
  5039. this._rejectReadyPromise();
  5040. this._readyPromise = void 0;
  5041. } else if ("pending" == oldPlayState) {
  5042. this._resolveReadyPromise();
  5043. } else if ("pending" == newPlayState) {
  5044. this._readyPromise = void 0;
  5045. }
  5046. }
  5047. if (this._finishedPromise) {
  5048. if ("idle" == newPlayState) {
  5049. this._rejectFinishedPromise();
  5050. this._finishedPromise = void 0;
  5051. } else if ("finished" == newPlayState) {
  5052. this._resolveFinishedPromise();
  5053. } else if ("finished" == oldPlayState) {
  5054. this._finishedPromise = void 0;
  5055. }
  5056. }
  5057. }
  5058. return this._readyPromise || this._finishedPromise;
  5059. };
  5060.  
  5061.  
  5062. let restartWebAnimationsNextTickFlag = false;
  5063.  
  5064. const looperMethodT = () => {
  5065.  
  5066. const runnerFn = (hRes) => {
  5067. var b = timeline;
  5068. b.currentTime = hRes;
  5069. b._discardAnimations();
  5070. if (0 == b._animations.length) {
  5071. restartWebAnimationsNextTickFlag = false;
  5072. } else {
  5073. getRafPromise().then(runnerFn);
  5074. }
  5075. }
  5076.  
  5077. const restartWebAnimationsNextTick = () => {
  5078. if (!restartWebAnimationsNextTickFlag) {
  5079. restartWebAnimationsNextTickFlag = true;
  5080. getRafPromise().then(runnerFn);
  5081. }
  5082. }
  5083.  
  5084. return { restartWebAnimationsNextTick }
  5085. };
  5086.  
  5087.  
  5088. const looperMethodN = () => {
  5089.  
  5090. const acs = document.createElement('a-f');
  5091. acs.id = 'a-f';
  5092.  
  5093. if (!document.getElementById('afscript')) {
  5094. const style = document.createElement('style');
  5095. style.id = 'afscript';
  5096. style.textContent = `
  5097. @keyFrames aF1 {
  5098. 0% {
  5099. order: 0;
  5100. }
  5101. 100% {
  5102. order: 1;
  5103. }
  5104. }
  5105. #a-f[id] {
  5106. visibility: collapse !important;
  5107. position: fixed !important;
  5108. display: block !important;
  5109. top: -100px !important;
  5110. left: -100px !important;
  5111. margin:0 !important;
  5112. padding:0 !important;
  5113. outline:0 !important;
  5114. border:0 !important;
  5115. z-index:-1 !important;
  5116. width: 0px !important;
  5117. height: 0px !important;
  5118. contain: strict !important;
  5119. pointer-events: none !important;
  5120. animation: 1ms steps(2, jump-none) 0ms infinite alternate forwards running aF1 !important;
  5121. }
  5122. `;
  5123. (document.head || document.documentElement).appendChild(style);
  5124. }
  5125.  
  5126. document.documentElement.insertBefore(acs, document.documentElement.firstChild);
  5127.  
  5128. const _onanimationiteration = function (evt) {
  5129. const hRes = evt.timeStamp;
  5130. var b = timeline;
  5131. b.currentTime = hRes;
  5132. b._discardAnimations();
  5133. if (0 == b._animations.length) {
  5134. restartWebAnimationsNextTickFlag = false;
  5135. acs.onanimationiteration = null;
  5136. } else {
  5137. acs.onanimationiteration = _onanimationiteration;
  5138. }
  5139.  
  5140. }
  5141.  
  5142.  
  5143.  
  5144. const restartWebAnimationsNextTick = () => {
  5145. if (!restartWebAnimationsNextTickFlag) {
  5146. restartWebAnimationsNextTickFlag = true;
  5147. acs.onanimationiteration = _onanimationiteration;
  5148.  
  5149. }
  5150. }
  5151.  
  5152. return { restartWebAnimationsNextTick }
  5153. };
  5154.  
  5155.  
  5156.  
  5157. const { restartWebAnimationsNextTick } = ('onanimationiteration' in document.documentElement) ? looperMethodN() : looperMethodT();
  5158.  
  5159.  
  5160. // console.log(571, timProto);
  5161. timProto._play = function (c) {
  5162. c = new Animation(c, this);
  5163. this._animations.push(c);
  5164. restartWebAnimationsNextTick();
  5165. c._updatePromises();
  5166. c._animation.play();
  5167. c._updatePromises();
  5168. return c
  5169. }
  5170.  
  5171. const animationsWithPromisesMap = new Set(originalAnimationsWithPromises);
  5172. originalAnimationsWithPromises.length = 0;
  5173. originalAnimationsWithPromises.push = null;
  5174. originalAnimationsWithPromises.splice = null;
  5175. originalAnimationsWithPromises.slice = null;
  5176. originalAnimationsWithPromises.indexOf = null;
  5177. originalAnimationsWithPromises.unshift = null;
  5178. originalAnimationsWithPromises.shift = null;
  5179. originalAnimationsWithPromises.pop = null;
  5180. originalAnimationsWithPromises.filter = null;
  5181. originalAnimationsWithPromises.forEach = null;
  5182. originalAnimationsWithPromises.map = null;
  5183.  
  5184.  
  5185. const _updateAnimationsPromises = () => {
  5186. animationsWithPromisesMap.forEach(c => {
  5187. if (!c._updatePromises()) animationsWithPromisesMap.delete(c);
  5188. });
  5189. /*
  5190. v.animationsWithPromises = v.animationsWithPromises.filter(function (c) {
  5191. return c._updatePromises();
  5192. });
  5193. */
  5194. }
  5195.  
  5196. timProto._updateAnimationsPromises31 = timProto._updateAnimationsPromises;
  5197.  
  5198. timProto._updateAnimationsPromises = _updateAnimationsPromises;
  5199.  
  5200. delete timProto._updateAnimationsPromises;
  5201. Object.defineProperty(timProto, '_updateAnimationsPromises', {
  5202. get() {
  5203. if (animationsWithPromisesMap.size === 0) return nilFn;
  5204. return _updateAnimationsPromises;
  5205. },
  5206. set(nv) {
  5207. delete this._updateAnimationsPromises;
  5208. this._updateAnimationsPromises = nv;
  5209. },
  5210. enumerable: true,
  5211. configurable: true,
  5212. });
  5213.  
  5214.  
  5215. let pdFinished = Object.getOwnPropertyDescriptor(aniProto, 'finished');
  5216. aniProto.__finished_native_get__ = pdFinished.get;
  5217. if (typeof pdFinished.get === 'function' && !pdFinished.set && pdFinished.configurable === true && pdFinished.enumerable === true) {
  5218.  
  5219.  
  5220. Object.defineProperty(aniProto, 'finished', {
  5221. get() {
  5222. this._finishedPromise || (!animationsWithPromisesMap.has(this) && animationsWithPromisesMap.add(this),
  5223. this._finishedPromise = new Promise((resolve, reject) => {
  5224. this._resolveFinishedPromise = function () {
  5225. resolve(this)
  5226. };
  5227. this._rejectFinishedPromise = function () {
  5228. reject({
  5229. type: DOMException.ABORT_ERR,
  5230. name: "AbortError"
  5231. })
  5232. };
  5233. }),
  5234. "finished" == this.playState && this._resolveFinishedPromise());
  5235. return this._finishedPromise
  5236. },
  5237. set: undefined,
  5238. enumerable: true,
  5239. configurable: true
  5240. });
  5241.  
  5242. }
  5243.  
  5244.  
  5245.  
  5246. let pdReady = Object.getOwnPropertyDescriptor(aniProto, 'ready');
  5247. aniProto.__ready_native_get__ = pdReady.get;
  5248. if (typeof pdReady.get === 'function' && !pdReady.set && pdReady.configurable === true && pdReady.enumerable === true) {
  5249.  
  5250. Object.defineProperty(aniProto, 'ready', {
  5251. get() {
  5252. this._readyPromise || (!animationsWithPromisesMap.has(this) && animationsWithPromisesMap.add(this),
  5253. this._readyPromise = new Promise((resolve, reject) => {
  5254. this._resolveReadyPromise = function () {
  5255. resolve(this)
  5256. };
  5257. this._rejectReadyPromise = function () {
  5258. reject({
  5259. type: DOMException.ABORT_ERR,
  5260. name: "AbortError"
  5261. })
  5262. };
  5263. }),
  5264. "pending" !== this.playState && this._resolveReadyPromise());
  5265. return this._readyPromise
  5266. },
  5267. set: undefined,
  5268. enumerable: true,
  5269. configurable: true
  5270. });
  5271.  
  5272. }
  5273.  
  5274.  
  5275. if (IGNORE_bindAnimationForCustomEffect && typeof aniProto._rebuildUnderlyingAnimation === 'function' && !aniProto._rebuildUnderlyingAnimation21 && aniProto._rebuildUnderlyingAnimation.length === 0) {
  5276.  
  5277. aniProto._rebuildUnderlyingAnimation21 = aniProto._rebuildUnderlyingAnimation;
  5278. const _rebuildUnderlyingAnimation = function () {
  5279. // if (isNaN(this._sequenceNumber)) return; // do not rebuild underlying animation if native animation is used.
  5280. this.effect && this.effect._onsample && (this.effect._onsample = null);
  5281. return this._rebuildUnderlyingAnimation21();
  5282. }
  5283. aniProto._rebuildUnderlyingAnimation = _rebuildUnderlyingAnimation;
  5284. // delete aniProto._rebuildUnderlyingAnimation;
  5285. // Object.defineProperty(aniProto, '_rebuildUnderlyingAnimation', {
  5286. // get() {
  5287. // if (isNaN(this._sequenceNumber)) return nilFn;
  5288. // return this._rebuildUnderlyingAnimation21;
  5289. // },
  5290. // set(nv) {
  5291. // delete this._rebuildUnderlyingAnimation;
  5292. // this._rebuildUnderlyingAnimation = nv;
  5293. // },
  5294. // enumerable: true,
  5295. // configurable: true
  5296. // });
  5297. }
  5298.  
  5299.  
  5300. /*
  5301.  
  5302.  
  5303. function f(c) {
  5304. var b = v.timeline;
  5305. b.currentTime = c;
  5306. b._discardAnimations();
  5307. 0 == b._animations.length ? d = !1 : requestAnimationFrame(f)
  5308. }
  5309. var h = window.requestAnimationFrame;
  5310. window.requestAnimationFrame = function(c) {
  5311. return h(function(b) {
  5312. v.timeline._updateAnimationsPromises();
  5313. c(b);
  5314. v.timeline._updateAnimationsPromises()
  5315. })
  5316. }
  5317. ;
  5318. v.AnimationTimeline = function() {
  5319. this._animations = [];
  5320. this.currentTime = void 0
  5321. }
  5322. ;
  5323. v.AnimationTimeline.prototype = {
  5324. getAnimations: function() {
  5325. this._discardAnimations();
  5326. return this._animations.slice()
  5327. },
  5328. _updateAnimationsPromises: function() {
  5329. v.animationsWithPromises = v.animationsWithPromises.filter(function(c) {
  5330. return c._updatePromises()
  5331. })
  5332. },
  5333. _discardAnimations: function() {
  5334. this._updateAnimationsPromises();
  5335. this._animations = this._animations.filter(function(c) {
  5336. return "finished" != c.playState && "idle" != c.playState
  5337. })
  5338. },
  5339. _play: function(c) {
  5340. c = new v.Animation(c,this);
  5341. this._animations.push(c);
  5342. v.restartWebAnimationsNextTick();
  5343. c._updatePromises();
  5344. c._animation.play();
  5345. c._updatePromises();
  5346. return c
  5347. },
  5348. play: function(c) {
  5349. c && c.remove();
  5350. return this._play(c)
  5351. }
  5352. };
  5353. var d = !1;
  5354. v.restartWebAnimationsNextTick = function() {
  5355. d || (d = !0,
  5356. requestAnimationFrame(f))
  5357. }
  5358. ;
  5359. var a = new v.AnimationTimeline;
  5360. v.timeline = a;
  5361. try {
  5362. Object.defineProperty(window.document, "timeline", {
  5363. configurable: !0,
  5364. get: function() {
  5365. return a
  5366. }
  5367. })
  5368. } catch (c) {}
  5369. try {
  5370. window.document.timeline = a
  5371. } catch (c) {}
  5372.  
  5373. */
  5374.  
  5375.  
  5376.  
  5377. /*
  5378.  
  5379. var g = window.getComputedStyle;
  5380. Object.defineProperty(window, "getComputedStyle", {
  5381. configurable: !0,
  5382. enumerable: !0,
  5383. value: function() {
  5384. v.timeline._updateAnimationsPromises();
  5385. var e = g.apply(this, arguments);
  5386. h() && (e = g.apply(this, arguments));
  5387. v.timeline._updateAnimationsPromises();
  5388. return e
  5389. }
  5390. });
  5391.  
  5392. */
  5393.  
  5394.  
  5395.  
  5396.  
  5397. }
  5398.  
  5399.  
  5400.  
  5401.  
  5402. })();
  5403.  
  5404. !isUrlInEmbed && Promise.resolve().then(() => {
  5405.  
  5406. // ==================================== FIX_avoid_incorrect_video_meta ====================================
  5407.  
  5408.  
  5409.  
  5410. class LimitedSizeSet extends Set {
  5411. constructor(n) {
  5412. super();
  5413.  
  5414. this.limit = n;
  5415. }
  5416.  
  5417. add(key) {
  5418. if (!super.has(key)) {
  5419. super.add(key); // Set the key with a dummy value (true)
  5420. while (super.size > this.limit) {
  5421. const firstKey = super.values().next().value; // Get the first (oldest) key
  5422. super.delete(firstKey); // Delete the oldest key
  5423. }
  5424. }
  5425. }
  5426.  
  5427. removeAdd(key) {
  5428. super.delete(key);
  5429. super.add(key);
  5430. }
  5431.  
  5432. }
  5433.  
  5434. // const wk3 = new WeakMap();
  5435.  
  5436. // let mtxVideoId = '';
  5437. // let aje3 = [];
  5438. const mfvContinuationRecorded = new LimitedSizeSet(8); // record all success continuation keys
  5439. const mfyContinuationIgnored = new LimitedSizeSet(8); // ignore continuation keys by copying the keys in the past
  5440. let mtzlastAllowedContinuation = ''; // the key stored at the last success; clear when scheduling changes
  5441. let mtzCount = 0; // the key keeps unchanged
  5442. // let mjtNextMainKey = '';
  5443. let mjtRecordedPrevKey = ''; // the key stored at the last success (no clear)
  5444. let mjtLockPreviousKey = ''; // the key before fetch() should be discarded. (uncertain continuation)
  5445. let mbCId322 = 0; // cid for delay fetchUpdatedMetadata
  5446. // let allowNoDelay322=false;
  5447. let mbDelayBelowNCalls = 0; // after N calls, by pass delay; reset when scheduling changes
  5448.  
  5449. let mpKey22 = ''; // last success continutation key & url pair
  5450. let mpUrl22 = ''; // last success continutation key & url pair
  5451. let mpKey21 = ''; // latest requested continutation key & url pair
  5452. let mpUrl21 = ''; // latest requested continutation key & url pair
  5453.  
  5454.  
  5455. async function sha1Hex(message) {
  5456. const msgUint8 = new TextEncoder().encode(message); // encode as (utf-8) Uint8Array
  5457. const hashBuffer = await crypto.subtle.digest("SHA-1", msgUint8); // hash the message
  5458. const hashArray = Array.from(new Uint8Array(hashBuffer)); // convert buffer to byte array
  5459. const hashHex = hashArray
  5460. .map((b) => b.toString(16).padStart(2, "0"))
  5461. .join(""); // convert bytes to hex string
  5462. return hashHex;
  5463. }
  5464.  
  5465. async function continuationLog(a, ...args) {
  5466. let b = a;
  5467. try {
  5468. if (advanceLogging) b = await sha1Hex(a);
  5469. let c = args.map(e => {
  5470. return e === a ? b : e
  5471. });
  5472. console.log(...c)
  5473. } catch (e) { console.warn(e) }
  5474. }
  5475.  
  5476. function copyPreviousContiuationToIgnored374(toClearRecorded) {
  5477.  
  5478.  
  5479. if (mfvContinuationRecorded.length > 0) {
  5480. for (const [e, d] of mfvContinuationRecorded) {
  5481. mfyContinuationIgnored.removeAdd(e);
  5482. }
  5483. toClearRecorded && mfvContinuationRecorded.clear();
  5484. }
  5485.  
  5486. }
  5487.  
  5488. function setup_ytTaskEmitterBehavior_TaskMgr374(taskMgr) {
  5489.  
  5490. const tmProto = taskMgr.constructor.prototype;
  5491. if (tmProto && typeof tmProto.addJob === 'function' && tmProto.addJob.length === 3 && typeof tmProto.cancelJob === 'function' && tmProto.cancelJob.length === 1) {
  5492.  
  5493. if (!tmProto.addJob714) {
  5494.  
  5495. tmProto.addJob714 = tmProto.addJob;
  5496.  
  5497. tmProto.addJob = function (a, b, c) {
  5498. const jobId = this.addJob714(a, b, c);
  5499. if (jobId > 0) {
  5500. // const ez = wk3.get(this);
  5501. // const dz = ez ? ez.data?.updatedMetadataEndpoint?.updatedMetadataEndpoint : null;
  5502. // aje3.push({mtx, jobId, a,b,c, element: this, dz, data: (ez?.data || null) })
  5503.  
  5504. this.__lastJobId863__ = jobId;
  5505. }
  5506. return jobId;
  5507. }
  5508.  
  5509. }
  5510.  
  5511. if (!tmProto.cancelJob714) {
  5512.  
  5513. tmProto.cancelJob714 = tmProto.cancelJob;
  5514.  
  5515. tmProto.cancelJob = function (a) {
  5516. const res = this.cancelJob714(a);
  5517. // if (a > 0) {
  5518. // for (const e of aje3) {
  5519. // if (e.jobId === a) e.cancelled = true;
  5520. // }
  5521. // }
  5522. return res;
  5523. }
  5524.  
  5525. }
  5526.  
  5527. }
  5528. }
  5529.  
  5530.  
  5531. const FIX_avoid_incorrect_video_meta_bool = FIX_avoid_incorrect_video_meta && isPrepareCachedV && check_for_set_key_order;
  5532.  
  5533.  
  5534. FIX_avoid_incorrect_video_meta_bool && whenCEDefined('ytd-video-primary-info-renderer').then(() => {
  5535. let dummy;
  5536. let cProto;
  5537. // let mc = 4;
  5538. // dummy = await observablePromise(() => {
  5539. // const r = document.querySelector('ytd-video-primary-info-renderer');
  5540. // if (!r) return;
  5541. // let cProto = insp(r).constructor.prototype;
  5542. // if (cProto.fetchUpdatedMetadata) return r;
  5543. // if (--mc < 0) return -1;
  5544. // return null;
  5545. // }).obtain();
  5546. dummy = document.createElement('ytd-video-primary-info-renderer');
  5547. if (!(dummy instanceof Element)) return;
  5548. // console.log(5022, dummy)
  5549. cProto = insp(dummy).constructor.prototype;
  5550.  
  5551. cProto.__getEmittorTaskMgr859__ = function () {
  5552. let taskMgr_ = null;
  5553. try {
  5554. taskMgr_ = (this.ytTaskEmitterBehavior || 0).getTaskManager() || null;
  5555. } catch (e) { }
  5556. return taskMgr_;
  5557. }
  5558. if (typeof cProto.fetchUpdatedMetadata === 'function' && cProto.fetchUpdatedMetadata.length === 1 && !cProto.fetchUpdatedMetadata717) {
  5559. // console.log(1234, cProto, cProto.is)
  5560. cProto.fetchUpdatedMetadata717 = cProto.fetchUpdatedMetadata;
  5561.  
  5562. let c_;
  5563. cProto.fetchUpdatedMetadata718 = function (a) {
  5564. // delay or immediate call the actual fetchUpdatedMetadata
  5565.  
  5566. let doImmediately = false;
  5567. if (a && typeof a === 'string' && mjtRecordedPrevKey && mjtRecordedPrevKey === mpKey22 && a === mpKey22 && (!pageSetupVideoId || pageSetupVideoId !== mpUrl22)) {
  5568.  
  5569. if (!pageSetupVideoId && videoPlayingY.videoId === mpUrl22) doImmediately = true;
  5570.  
  5571. } else if (typeof a !== 'string' || mbDelayBelowNCalls > 3 || !mpKey22 || (mpKey22 === a && mpKey22 !== mjtLockPreviousKey) || (mjtLockPreviousKey && mjtLockPreviousKey !== a)) {
  5572.  
  5573. doImmediately = true;
  5574.  
  5575. }
  5576.  
  5577. if (mbCId322) {
  5578. clearTimeout(mbCId322);
  5579. mbCId322 = 0;
  5580. }
  5581.  
  5582. if (doImmediately) return this.fetchUpdatedMetadata717(a);
  5583.  
  5584. let delay = mjtLockPreviousKey === a ? 8000 : 800;
  5585.  
  5586. mbCId322 = setTimeout(() => {
  5587. this.fetchUpdatedMetadata717(a);
  5588. }, delay);
  5589.  
  5590. console.log('[yt-js-engine-tamer]', '5190 delayed fetchUpdatedMetadata', delay);
  5591.  
  5592. }
  5593.  
  5594. cProto.fetchUpdatedMetadata = function (a) {
  5595.  
  5596. if (!pageSetupState) {
  5597. if (c_) clearTimeout(c_);
  5598. c_ = setTimeout(() => {
  5599. this.fetchUpdatedMetadata718(a);
  5600. }, 300);
  5601. return;
  5602. }
  5603.  
  5604. // pageSetupState == 0
  5605.  
  5606. try {
  5607.  
  5608. mbDelayBelowNCalls++;
  5609.  
  5610. if (arguments.length > 1 || !(a === undefined || (typeof a === 'string' && a))) {
  5611. console.warn("CAUTION: fetchUpdatedMetadata coding might have to be updated.");
  5612. }
  5613.  
  5614. // console.log('fum377', a)
  5615. if (typeof a === 'string' && mfyContinuationIgnored.has(a)) {
  5616. console.log('[yt-js-engine-tamer]', '5040 skip fetchUpdatedMetadata', a);
  5617. return;
  5618. }
  5619.  
  5620. if (!a && (this.data || 0).updatedMetadataEndpoint) {
  5621. if (mjtRecordedPrevKey && mjtLockPreviousKey !== mjtRecordedPrevKey) {
  5622. mjtLockPreviousKey = mjtRecordedPrevKey;
  5623. LOG_FETCHMETA_UPDATE && continuationLog(mjtLockPreviousKey, '5150 Lock Key', mjtLockPreviousKey);
  5624. }
  5625. // mjtNextMainKey = true;
  5626. mtzlastAllowedContinuation = '';
  5627. mtzCount = 0;
  5628. // allowNoDelay322 = false;
  5629. // fetch new metadata, cancel all previous continuations
  5630. copyPreviousContiuationToIgnored374(true);
  5631. } else if (typeof a === 'string') {
  5632. const videoPlayingId = videoPlayingY.videoId;
  5633.  
  5634. // if(mjtNextMainKey === true) mjtNextMainKey = a;
  5635.  
  5636. let update21 = !!pageSetupVideoId;
  5637. if (mpKey22 === a && mpUrl22 === videoPlayingId && mpUrl22 && videoPlayingId && (!pageSetupVideoId || pageSetupVideoId === videoPlayingId)) {
  5638. update21 = true;
  5639. } else if (mpKey22 === a && mpUrl22 !== pageSetupVideoId) {
  5640. LOG_FETCHMETA_UPDATE && continuationLog(mpKey22, '5060 mpUrl22 mismatched', mpKey22, mpUrl22, pageSetupVideoId || '(null)', videoPlayingId || '(null)');
  5641. return;
  5642. }
  5643. if (update21) {
  5644. mpKey21 = a;
  5645. mpUrl21 = pageSetupVideoId || videoPlayingId;
  5646. }
  5647.  
  5648. if (!mfvContinuationRecorded.has(a)) mfvContinuationRecorded.add(a);
  5649. }
  5650. LOG_FETCHMETA_UPDATE && continuationLog(a, '5180 fetchUpdatedMetadata\t', a, pageSetupVideoId || '(null)', videoPlayingY.videoId || '(null)');
  5651. // if (!pageSetupVideoId && typeof a === 'string' && a.length > 40) return; // ignore incorrect continuation
  5652. // if(a === mjtNextMainKey) allowNoDelay322 = false;
  5653. return this.fetchUpdatedMetadata718(a);
  5654.  
  5655. } catch (e) {
  5656. console.log('Code Error in fetchUpdatedMetadata', e);
  5657. }
  5658. return this.fetchUpdatedMetadata717(a)
  5659. }
  5660. }
  5661.  
  5662.  
  5663. if (typeof cProto.scheduleInitialUpdatedMetadataRequest === 'function' && cProto.scheduleInitialUpdatedMetadataRequest.length === 0 && !cProto.scheduleInitialUpdatedMetadataRequest717) {
  5664. // console.log(1234, cProto, cProto.is)
  5665. cProto.scheduleInitialUpdatedMetadataRequest717 = cProto.scheduleInitialUpdatedMetadataRequest;
  5666. let mJob = null;
  5667.  
  5668. cProto.scheduleInitialUpdatedMetadataRequest = function () {
  5669.  
  5670. try {
  5671.  
  5672. if (arguments.length > 0) {
  5673. console.warn("CAUTION: scheduleInitialUpdatedMetadataRequest coding might have to be updated.");
  5674. }
  5675. // mfy = mfv;
  5676.  
  5677. // mjtNextMainKey = '';
  5678. mtzlastAllowedContinuation = '';
  5679. mtzCount = 0;
  5680. if (mbCId322) {
  5681. clearTimeout(mbCId322);
  5682. mbCId322 = 0;
  5683. }
  5684. mbDelayBelowNCalls = 0;
  5685. // allowNoDelay322 = false;
  5686. copyPreviousContiuationToIgnored374(true);
  5687.  
  5688. const taskMgr = this.__getEmittorTaskMgr859__();
  5689. if (FIX_avoid_incorrect_video_meta_emitterBehavior && taskMgr && !taskMgr.addJob714 && taskMgr.addJob && taskMgr.cancelJob) setup_ytTaskEmitterBehavior_TaskMgr374(taskMgr);
  5690. if (FIX_avoid_incorrect_video_meta_emitterBehavior && taskMgr && !taskMgr.addJob714) {
  5691. console.log('[yt-js-engine-tamer]', 'scheduleInitialUpdatedMetadataRequest error 507');
  5692. }
  5693.  
  5694. // prevent depulicated schedule job by clearing previous JobId
  5695. if (taskMgr && typeof taskMgr.addLowPriorityJob === 'function' && taskMgr.addLowPriorityJob.length === 2 && typeof taskMgr.cancelJob === 'function' && taskMgr.cancelJob.length === 1) {
  5696.  
  5697. let res;
  5698.  
  5699. if (mJob) {
  5700. const job = mJob;
  5701. mJob = null;
  5702. console.log('cancelJob', job)
  5703. taskMgr.cancelJob(job); // clear previous [Interval Meta Update] job
  5704. // p.cancelJob(a,b);
  5705. }
  5706.  
  5707. // const updatedMetadataEndpoint = this.data?.updatedMetadataEndpoint?.updatedMetadataEndpoint
  5708.  
  5709. let pza = taskMgr.__lastJobId863__;
  5710. try { res = this.scheduleInitialUpdatedMetadataRequest717(); } catch (e) { }
  5711. let pzb = taskMgr.__lastJobId863__
  5712. if (pza !== pzb) {
  5713. mJob = pzb; // set [Interval Meta Update] jobId
  5714. }
  5715.  
  5716. // if (updatedMetadataEndpoint && updatedMetadataEndpoint.videoId) {
  5717. // mtxVideoId = updatedMetadataEndpoint.videoId || ''; // set the current target VideoId
  5718. // } else {
  5719. // mtxVideoId = ''; // sometimes updatedMetadataEndpoint is not ready
  5720. // }
  5721.  
  5722. return res;
  5723.  
  5724. } else {
  5725. console.log('[yt-js-engine-tamer]', 'scheduleInitialUpdatedMetadataRequest error 601');
  5726. }
  5727.  
  5728. } catch (e) {
  5729. console.log('Code Error in scheduleInitialUpdatedMetadataRequest', e);
  5730. }
  5731.  
  5732.  
  5733. return this.scheduleInitialUpdatedMetadataRequest717();
  5734. }
  5735. }
  5736.  
  5737.  
  5738. });
  5739.  
  5740. FIX_avoid_incorrect_video_meta_bool && promiseForYtActionCalled.then((ytAppDom) => {
  5741. let dummy;
  5742. let cProto;
  5743. dummy = ytAppDom;
  5744. if (!(dummy instanceof Element)) return;
  5745. cProto = insp(dummy).constructor.prototype;
  5746. if (typeof cProto.sendServiceAjax_ === 'function' && cProto.sendServiceAjax_.length === 4 && !cProto.sendServiceAjax717_) {
  5747. // console.log(1234, cProto, cProto.is);
  5748. // cProto.handleServiceRequest717_ = cProto.handleServiceRequest_;
  5749. // cProto.handleServiceRequest_ = function (a, b, c, d) {
  5750. // console.log(123401, arguments);
  5751. // return this.handleServiceRequest717_(a, b, c, d);
  5752. // }
  5753.  
  5754. // cProto.handleServiceRequest717_ = cProto.handleServiceRequest_;
  5755.  
  5756. // cProto.handleServiceRequest_ = function(a,b,c,d){
  5757. // console.log(59901, a?.is, b?.updatedMetadataEndpoint?.videoId, c?.continuation)
  5758. // if(a?.is === 'ytd-video-primary-info-renderer' && b?.updatedMetadataEndpoint?.videoId && c?.continuation && typeof c?.continuation ==='string'){
  5759. // console.log('mfv', c.continuation);
  5760. // mfv.add( c.continuation);
  5761. // }
  5762. // return this.handleServiceRequest717_(a,b,c,d);
  5763. // }
  5764.  
  5765. function extraArguments322(a, b, c) {
  5766. let is = (a || 0).is;
  5767. let videoId = ((b || 0).updatedMetadataEndpoint || 0).videoId;
  5768. let continuation = (c || 0).continuation;
  5769. if (typeof is !== 'string') is = null;
  5770. if (typeof videoId !== 'string') videoId = null;
  5771. if (typeof continuation !== 'string') continuation = null;
  5772. return { is, videoId, continuation };
  5773. }
  5774.  
  5775. cProto.sendServiceAjax717_ = cProto.sendServiceAjax_;
  5776. cProto.sendServiceAjax_ = function (a, b, c, d) {
  5777.  
  5778. // console.log(8001)
  5779. try {
  5780.  
  5781. const { is, videoId, continuation } = extraArguments322(a, b, c);
  5782.  
  5783. if ((videoId || continuation) && (is !== 'ytd-video-primary-info-renderer')) {
  5784. console.warn("CAUTION: sendServiceAjax_ coding might have to be updated.");
  5785. }
  5786.  
  5787. if (pageSetupVideoId && videoId && continuation) {
  5788. if (mpKey21 && mpUrl21 && mpKey21 === continuation && mpUrl21 !== pageSetupVideoId) {
  5789. mfyContinuationIgnored.removeAdd(continuation);
  5790. mfvContinuationRecorded.delete(continuation);
  5791. return;
  5792. }
  5793. }
  5794.  
  5795. if (mjtLockPreviousKey && mjtLockPreviousKey !== continuation && continuation) {
  5796. copyPreviousContiuationToIgnored374(false);
  5797. mfyContinuationIgnored.delete(continuation);
  5798. mfvContinuationRecorded.removeAdd(continuation);
  5799. mfyContinuationIgnored.removeAdd(mjtLockPreviousKey);
  5800. mfvContinuationRecorded.delete(mjtLockPreviousKey);
  5801. mjtLockPreviousKey = '';
  5802. }
  5803. // if (mjtNextMainKey === continuation) {
  5804. // copyPreviousContiuationToIgnored(false);
  5805. // mfyContinuationIgnored.delete(continuation);
  5806. // mfvContinuationRecorded.add(continuation);
  5807. // }
  5808.  
  5809.  
  5810. if (mfyContinuationIgnored && continuation) {
  5811. if (mfyContinuationIgnored.has(continuation)) {
  5812. LOG_FETCHMETA_UPDATE && continuationLog(continuation, '5260 matched01', continuation)
  5813. return;
  5814. }
  5815. }
  5816.  
  5817. // console.log(59902, a?.is, b,c,d)
  5818. // console.log(59903, a?.is, b?.updatedMetadataEndpoint?.videoId, c?.continuation)
  5819. if (is === 'ytd-video-primary-info-renderer' && videoId && continuation && !mfvContinuationRecorded.has(continuation)) {
  5820. // console.log('mfv377', continuation);
  5821. mfvContinuationRecorded.add(continuation);
  5822. }
  5823.  
  5824. // if (videoId) {
  5825. // if (!pageSetupVideoId) return; // ignore page not ready
  5826. // // if (mtxVideoId && b.updatedMetadataEndpoint.videoId !== mtxVideoId) return; // ignore videoID not matched
  5827. // if (videoId !== pageSetupVideoId) {
  5828. // return;
  5829. // }
  5830. // }
  5831.  
  5832. } catch (e) {
  5833. console.log('Coding Error in sendServiceAjax_', e)
  5834. }
  5835. // console.log(8002)
  5836. // console.log(123402, arguments);
  5837. // console.log(5162, 'a',a?.is,'b',b,'c',c,'d',d);
  5838.  
  5839. // console.log(5211, b?.updatedMetadataEndpoint?.kdkw33);
  5840. // if(b &&b.updatedMetadataEndpoint && !b.updatedMetadataEndpoint.kdkw33){
  5841. // b.updatedMetadataEndpoint = new Proxy(b.updatedMetadataEndpoint, {
  5842. // get(target, prop, receiver){
  5843. // console.log('xxs99', target.videoId, mtx)
  5844. // if(prop ==='kdkw33') return 1;
  5845. // console.log(3322, prop, target)
  5846. // if(prop === 'initialDelayMs') {
  5847. // throw new Error("ABCC");
  5848. // }
  5849. // return target[prop];
  5850. // },
  5851. // set(target, prop, value, receiver){
  5852.  
  5853. // if(prop ==='kdkw33') return true;
  5854. // target[prop]=value;
  5855. // return true;
  5856. // }
  5857. // });
  5858. // }
  5859. // console.log(5533, b?.updatedMetadataEndpoint?.kdkw33)
  5860. return this.sendServiceAjax717_(a, b, c, d);
  5861. }
  5862. }
  5863.  
  5864. function delayClearOtherKeys(lztContinuation) {
  5865. // // schedule delayed removal if mfyContinuationIgnored is not empty
  5866. // getRafPromise().then(() => {
  5867. // // assume the repeat continuation could be only for popstate which is triggered by user interaction
  5868. // // foreground page only
  5869.  
  5870. // });
  5871.  
  5872.  
  5873. if (lztContinuation !== mtzlastAllowedContinuation) return;
  5874. if (lztContinuation !== mpKey21 || lztContinuation !== mpKey22) return;
  5875. if (!mfyContinuationIgnored.size) return;
  5876. if (mfyContinuationIgnored.size > 1) {
  5877. LOG_FETCHMETA_UPDATE && continuationLog(lztContinuation, 'delayClearOtherKeys, current = ', lztContinuation);
  5878. }
  5879. mfyContinuationIgnored.forEach((value, key) => {
  5880. if (key !== lztContinuation) {
  5881. mfyContinuationIgnored.delete(key);
  5882. LOG_FETCHMETA_UPDATE && continuationLog(key, 'previous continuation removed from ignored store', key);
  5883. }
  5884. });
  5885.  
  5886. }
  5887. if (typeof cProto.getCancellableNetworkPromise_ === 'function' && cProto.getCancellableNetworkPromise_.length === 5 && !cProto.getCancellableNetworkPromise717_) {
  5888. cProto.getCancellableNetworkPromise717_ = cProto.getCancellableNetworkPromise_;
  5889. cProto.getCancellableNetworkPromise_ = function (a, b, c, d, e) {
  5890.  
  5891. // console.log(8003)
  5892. try {
  5893.  
  5894.  
  5895. const { is, videoId, continuation } = extraArguments322(b, c, d);
  5896.  
  5897. if ((videoId || continuation) && (is !== 'ytd-video-primary-info-renderer')) {
  5898. console.warn("CAUTION: getCancellableNetworkPromise_ coding might have to be updated.");
  5899. }
  5900.  
  5901. if (pageSetupVideoId && videoId && continuation) {
  5902. if (mpKey21 && mpUrl21 && mpKey21 === continuation && mpUrl21 !== pageSetupVideoId) {
  5903. mfyContinuationIgnored.removeAdd(continuation);
  5904. mfvContinuationRecorded.delete(continuation);
  5905. return;
  5906. }
  5907. }
  5908.  
  5909. if (mjtLockPreviousKey && mjtLockPreviousKey !== continuation && continuation) {
  5910. copyPreviousContiuationToIgnored374(false);
  5911. mfyContinuationIgnored.delete(continuation);
  5912. mfvContinuationRecorded.removeAdd(continuation);
  5913. mfyContinuationIgnored.removeAdd(mjtLockPreviousKey);
  5914. mfvContinuationRecorded.delete(mjtLockPreviousKey);
  5915. mjtLockPreviousKey = '';
  5916. }
  5917.  
  5918. // if (mjtNextMainKey === continuation) {
  5919. // copyPreviousContiuationToIgnored(false);
  5920. // mfyContinuationIgnored.delete(continuation);
  5921. // mfvContinuationRecorded.add(continuation);
  5922. // }
  5923.  
  5924. const lztContinuation = continuation;
  5925.  
  5926. if (mfyContinuationIgnored && lztContinuation && typeof lztContinuation === 'string') {
  5927. if (mfyContinuationIgnored.has(lztContinuation)) {
  5928. LOG_FETCHMETA_UPDATE && continuationLog(lztContinuation, '5360 matched02', lztContinuation)
  5929. return;
  5930. }
  5931. }
  5932.  
  5933. // if (videoId) {
  5934. // if (!pageSetupVideoId) return; // ignore page not ready
  5935. // // if (mtxVideoId && c.updatedMetadataEndpoint.videoId !== mtxVideoId) return; // ignore videoID not matched
  5936. // if (videoId !== pageSetupVideoId) {
  5937. // return;
  5938. // }
  5939. // }
  5940.  
  5941. if (typeof lztContinuation === 'string' && mtzlastAllowedContinuation !== lztContinuation) {
  5942. mtzlastAllowedContinuation = lztContinuation;
  5943. // console.log(70401, lztContinuation, mfyContinuationIgnored.size)
  5944.  
  5945. LOG_FETCHMETA_UPDATE && continuationLog(lztContinuation, '5382 Continuation sets to\t', lztContinuation, `C${mtzCount}.R${mfvContinuationRecorded.size}.I${mfyContinuationIgnored.size}`);
  5946. mjtRecordedPrevKey = lztContinuation;
  5947. if (mjtLockPreviousKey === lztContinuation) mjtLockPreviousKey = '';
  5948. // if (mfyContinuationIgnored.size > 0) {
  5949. // delayClearOtherKeys(lztContinuation);
  5950. // }
  5951. mtzCount = 0;
  5952. // allowNoDelay322 = false;
  5953. } else if (typeof lztContinuation === 'string' && mtzlastAllowedContinuation && mtzlastAllowedContinuation === lztContinuation) {
  5954. // repeated
  5955. if (mtzCount > 1e9) mtzCount = 1e4;
  5956. ++mtzCount;
  5957. LOG_FETCHMETA_UPDATE && continuationLog(lztContinuation, '5386 Same Continuation\t\t', lztContinuation, `C${mtzCount}.R${mfvContinuationRecorded.size}.I${mfyContinuationIgnored.size}`);
  5958.  
  5959. // if (mtzCount >= 3) allowNoDelay322 = true;
  5960. if (mtzCount >= 3 && mfyContinuationIgnored.size > 0) {
  5961. Promise.resolve(lztContinuation).then(delayClearOtherKeys).catch(console.warn);
  5962. }
  5963. if (mtzCount === 5) {
  5964. mfvContinuationRecorded.clear();
  5965. mfvContinuationRecorded.add(lztContinuation);
  5966. }
  5967.  
  5968. }
  5969.  
  5970. if (typeof lztContinuation === 'string' && lztContinuation && (pageSetupVideoId || videoPlayingY.videoId)) {
  5971. mpKey22 = lztContinuation;
  5972. mpUrl22 = pageSetupVideoId || videoPlayingY.videoId;
  5973. }
  5974.  
  5975. if (mbCId322) {
  5976. clearTimeout(mbCId322);
  5977. mbCId322 = 0;
  5978. }
  5979. } catch (e) {
  5980. console.log('Coding Error in getCancellableNetworkPromise_', e)
  5981. }
  5982.  
  5983. // console.log(8004)
  5984. // console.log(123403, arguments);
  5985. // if(c.updatedMetadataEndpoint) console.log(123404, pageSetupVideoId, JSON.stringify(c.updatedMetadataEndpoint))
  5986.  
  5987. // console.log(5163, a?.is,b,c,d,e);
  5988. return this.getCancellableNetworkPromise717_(a, b, c, d, e);
  5989. }
  5990. }
  5991. });
  5992.  
  5993. // ==================================== FIX_avoid_incorrect_video_meta ====================================
  5994.  
  5995.  
  5996. FIX_ytdExpander_childrenChanged && whenCEDefined('ytd-expander').then(() => {
  5997.  
  5998. let dummy;
  5999. let cProto;
  6000.  
  6001. dummy = document.createElement('ytd-expander');
  6002. cProto = insp(dummy).constructor.prototype;
  6003.  
  6004. if (fnIntegrity(cProto.initChildrenObserver, '0.48.21') && fnIntegrity(cProto.childrenChanged, '0.40.22')) {
  6005.  
  6006. cProto.initChildrenObserver14 = cProto.initChildrenObserver;
  6007. cProto.childrenChanged14 = cProto.childrenChanged;
  6008.  
  6009. cProto.initChildrenObserver = function () {
  6010. var a = this;
  6011. this.observer = new MutationObserver(function () {
  6012. a.childrenChanged()
  6013. }
  6014. );
  6015. this.observer.observe(this.content, {
  6016. subtree: !0,
  6017. childList: !0,
  6018. attributes: !0,
  6019. characterData: !0
  6020. });
  6021. this.childrenChanged()
  6022. }
  6023. ;
  6024. cProto.childrenChanged = function () {
  6025. if (this.alwaysToggleable) {
  6026. this.canToggle = this.alwaysToggleable;
  6027. } else if (!this.canToggleJobId) {
  6028. this.canToggleJobId = 1;
  6029. getRafPromise().then(() => {
  6030. this.canToggleJobId = 0;
  6031. this.calculateCanCollapse()
  6032. })
  6033. }
  6034. }
  6035.  
  6036. // console.log(cProto.initChildrenObserver)
  6037. console.debug('ytd-expander-fix-childrenChanged');
  6038.  
  6039. }
  6040.  
  6041. });
  6042.  
  6043.  
  6044. FIX_paper_ripple_animate && whenCEDefined('paper-ripple').then(() => {
  6045.  
  6046. let dummy;
  6047. let cProto;
  6048. dummy = document.createElement('paper-ripple');
  6049. cProto = insp(dummy).constructor.prototype;
  6050.  
  6051. if (fnIntegrity(cProto.animate, '0.74.5')) {
  6052.  
  6053.  
  6054. cProto.animate34 = cProto.animate;
  6055. cProto.animate = function () {
  6056. if (this._animating) {
  6057. var a;
  6058. const ripples = this.ripples;
  6059. for (a = 0; a < ripples.length; ++a) {
  6060. var b = ripples[a];
  6061. b.draw();
  6062. this.$.background.style.opacity = b.outerOpacity;
  6063. b.isOpacityFullyDecayed && !b.isRestingAtMaxRadius && this.removeRipple(b)
  6064. }
  6065. if ((this.shouldKeepAnimating || 0) !== ripples.length) {
  6066. if (!this._boundAnimate38) this._boundAnimate38 = this.animate.bind(this);
  6067. getRafPromise().then(this._boundAnimate38);
  6068. } else {
  6069. this.onAnimationComplete()
  6070. }
  6071. }
  6072. }
  6073.  
  6074. console.debug('FIX_paper_ripple_animate')
  6075.  
  6076. // console.log(cProto.animate)
  6077.  
  6078. }
  6079.  
  6080. });
  6081.  
  6082. if (FIX_doIdomRender) {
  6083.  
  6084. const xsetTimeout = function (f, d) {
  6085. if (xsetTimeout.m511 === 1 && !d) {
  6086. xsetTimeout.m511 = 2;
  6087. getRafPromise().then(f);
  6088. } else {
  6089. return setTimeout.apply(window, arguments)
  6090. }
  6091.  
  6092. }
  6093.  
  6094. const xrequestAnimationFrame = function (f) {
  6095. const h = f + "";
  6096. if (h.startsWith("function(){setTimeout(function(){") && h.endsWith("})}")) {
  6097. xsetTimeout.m511 = 1;
  6098. f();
  6099. xsetTimeout.m511 = 0;
  6100. } else if (h.includes("requestAninmationFrameResolver")) {
  6101. getRafPromise().then(f);
  6102. } else {
  6103. return requestAnimationFrame.apply(window, arguments);
  6104. }
  6105. }
  6106.  
  6107. let busy = false;
  6108. const doIdomRender = function () {
  6109. if (busy) {
  6110. return this.doIdomRender13.apply(this, arguments);
  6111. }
  6112. busy = true;
  6113. const { requestAnimationFrame, setTimeout } = window;
  6114. window.requestAnimationFrame = xrequestAnimationFrame;
  6115. window.setTimeout = xsetTimeout;
  6116. let r = this.doIdomRender13.apply(this, arguments);
  6117. window.requestAnimationFrame = requestAnimationFrame;
  6118. window.setTimeout = setTimeout;
  6119. busy = false;
  6120. return r;
  6121. };
  6122. for (const ytTag of ['ytd-lottie-player', 'yt-attributed-string', 'yt-image', 'yt-icon-shape', 'yt-button-shape', 'yt-button-view-model', 'yt-icon-badge-shape']) {
  6123.  
  6124.  
  6125. whenCEDefined(ytTag).then(() => {
  6126.  
  6127. let dummy;
  6128. let cProto;
  6129. dummy = document.createElement(ytTag);
  6130. cProto = insp(dummy).constructor.prototype;
  6131.  
  6132. cProto.doIdomRender13 = cProto.doIdomRender;
  6133. cProto.doIdomRender = doIdomRender;
  6134.  
  6135. if (cProto.doIdomRender13 === cProto.templatingFn) cProto.templatingFn = doIdomRender;
  6136.  
  6137. console.debug('FIX_doIdomRender', ytTag)
  6138.  
  6139.  
  6140.  
  6141. });
  6142.  
  6143. }
  6144.  
  6145. }
  6146.  
  6147.  
  6148.  
  6149. });
  6150.  
  6151. });
  6152.  
  6153.  
  6154.  
  6155.  
  6156. if (isMainWindow) {
  6157.  
  6158. console.groupCollapsed(
  6159. "%cYouTube JS Engine Tamer",
  6160. "background-color: #EDE43B ; color: #000 ; font-weight: bold ; padding: 4px ;"
  6161. );
  6162.  
  6163.  
  6164.  
  6165. console.log("Script is loaded.");
  6166. console.log("This script changes the core mechanisms of the YouTube JS engine.");
  6167.  
  6168. console.log("This script is experimental and subject to further changes.");
  6169.  
  6170. console.log("This might boost your YouTube performance.");
  6171.  
  6172. console.log("CAUTION: This might break your YouTube.");
  6173.  
  6174.  
  6175. if (prepareLogs.length >= 1) {
  6176. console.log(" =========================================================================== ");
  6177.  
  6178. for (const msg of prepareLogs) {
  6179. console.log(msg)
  6180. }
  6181.  
  6182. console.log(" =========================================================================== ");
  6183. }
  6184.  
  6185. console.groupEnd();
  6186.  
  6187. }
  6188.  
  6189.  
  6190.  
  6191. })();