- // ==UserScript==
- // @name YouTube RM3 - Reduce Memory Usage by Reusing Components
- // @namespace Violentmonkey Scripts
- // @version 0.1.0019
- // @license MIT
- // @match https://www.youtube.com/*
- // @match https://studio.youtube.com/live_chat*
- //
- //
- // @author CY Fung
- // @run-at document-start
- // @grant none
- // @unwrap
- // @allFrames true
- // @inject-into page
- //
- // @compatible firefox Violentmonkey
- // @compatible firefox Tampermonkey
- // @compatible firefox FireMonkey
- // @compatible chrome Violentmonkey
- // @compatible chrome Tampermonkey
- // @compatible opera Violentmonkey
- // @compatible opera Tampermonkey
- // @compatible safari Stay
- // @compatible edge Violentmonkey
- // @compatible edge Tampermonkey
- // @compatible brave Violentmonkey
- // @compatible brave Tampermonkey
- //
- // @description A simple tool that runs in the background to reuse YouTube components, thereby reducing memory usage over time.
- // @description:en A simple tool that runs in the background to reuse YouTube components, thereby reducing memory usage over time.
- // @description:ja YouTubeコンポーネントを再利用することで、長期的なメモリ使用量の削減を目指す、バックグラウンドで実行されるシンプルなツールです。
- // @description:zh-TW 一個在背景執行的簡易工具,可重複利用 YouTube 元件,從而在長期減少記憶體使用量。
- // @description:zh-CN 一个在后台运行的简单工具,通过重复利用 YouTube 组件,从而在长期减少内存使用量。
- //
- // ==/UserScript==
-
- const rm3 = window.rm3 = {};
- // console.log(3001);
-
- (() => {
-
- const DEBUG_OPT = false;
- const CONFIRM_TIME = 4000;
- const CHECK_INTERVAL = 400;
- const DEBUG_dataChangeReflection = true;
-
-
- /** @type {globalThis.PromiseConstructor} */
- const Promise = (async () => { })().constructor; // YouTube hacks Promise in WaterFox Classic and "Promise.resolve(0)" nevers resolve.
-
- // https://qiita.com/piroor/items/02885998c9f76f45bfa0
- // https://gist.github.com/piroor/829ecb32a52c2a42e5393bbeebe5e63f
- function uniq(array) {
- return [...new Set(array)];
- };
-
-
- rm3.uniq = uniq; // [[debug]]
- DEBUG_OPT && (rm3.location= location.href);
-
-
- rm3.inspect = () => {
- return uniq([...document.getElementsByTagName('*')].filter(e => e?.polymerController?.createComponent_).map(e => e.nodeName)); // [[debug]]
- }
-
-
- const insp = o => o ? (o.polymerController || o.inst || o || 0) : (o || 0);
- const indr = o => insp(o).$ || o.$ || 0;
-
- const getProto = (element) => {
- if (element) {
- const cnt = insp(element);
- return cnt.constructor.prototype || null;
- }
- return null;
- }
-
-
- const LinkedArray = (() => {
-
-
- class Node {
- constructor(value) {
- this.value = value;
- this.next = null;
- this.prev = null;
- }
- }
-
- class LinkedArray {
- constructor() {
- this.head = null;
- this.tail = null;
- this.length = 0;
- }
-
- push(value) {
- const newNode = new Node(value);
- if (this.length === 0) {
- this.head = newNode;
- this.tail = newNode;
- } else {
- this.tail.next = newNode;
- newNode.prev = this.tail;
- this.tail = newNode;
- }
- this.length++;
- return this.length;
- }
-
- pop() {
- if (this.length === 0) return undefined;
- const removedNode = this.tail;
- if (this.length === 1) {
- this.head = null;
- this.tail = null;
- } else {
- this.tail = removedNode.prev;
- this.tail.next = null;
- removedNode.prev = null;
- }
- this.length--;
- return removedNode.value;
- }
-
- unshift(value) {
- const newNode = new Node(value);
- if (this.length === 0) {
- this.head = newNode;
- this.tail = newNode;
- } else {
- newNode.next = this.head;
- this.head.prev = newNode;
- this.head = newNode;
- }
- this.length++;
- return this.length;
- }
-
- shift() {
- if (this.length === 0) return undefined;
- const removedNode = this.head;
- if (this.length === 1) {
- this.head = null;
- this.tail = null;
- } else {
- this.head = removedNode.next;
- this.head.prev = null;
- removedNode.next = null;
- }
- this.length--;
- return removedNode.value;
- }
-
- size() {
- return this.length;
- }
-
- // Get a node by index (0-based)
- getNode(index) {
- if (index < 0 || index >= this.length) return null;
-
- let current;
- let counter;
-
- // Optimization: start from closest end
- if (index < this.length / 2) {
- current = this.head;
- counter = 0;
- while (counter !== index) {
- current = current.next;
- counter++;
- }
- } else {
- current = this.tail;
- counter = this.length - 1;
- while (counter !== index) {
- current = current.prev;
- counter--;
- }
- }
- return current;
- }
-
- // Get value by index
- get(index) {
- const node = this.getNode(index);
- return node ? node.value : undefined;
- }
-
- // Find the first node with the given value and return both node and index
- findNode(value) {
- let current = this.head;
- let idx = 0;
- while (current) {
- if (current.value === value) {
- return { node: current, index: idx };
- }
- current = current.next;
- idx++;
- }
- return { node: null, index: -1 };
- }
-
- toArray() {
- const arr = [];
- let current = this.head;
- while (current) {
- arr.push(current.value);
- current = current.next;
- }
- return arr;
- }
-
- // Insert a new value before a given node (provided you already have the node reference)
- insertBeforeNode(node, newValue) {
- if (!node) {
- this.unshift(newValue);
- return true;
- }
-
- if (node === this.head) {
- // If the target is the head, just unshift
- this.unshift(newValue);
- } else {
- const newNode = new Node(newValue);
- const prevNode = node.prev;
-
- prevNode.next = newNode;
- newNode.prev = prevNode;
- newNode.next = node;
- node.prev = newNode;
-
- this.length++;
- }
- return true;
- }
-
- // Insert a new value after a given node (provided you already have the node reference)
- insertAfterNode(node, newValue) {
-
- if (!node) {
- this.push(newValue);
- return true;
- }
-
- if (node === this.tail) {
- // If the target is the tail, just push
- this.push(newValue);
- } else {
- const newNode = new Node(newValue);
- const nextNode = node.next;
-
- node.next = newNode;
- newNode.prev = node;
- newNode.next = nextNode;
- nextNode.prev = newNode;
-
- this.length++;
- }
- return true;
- }
-
- // Insert a new value before the first occurrence of an existing value (search by value)
- insertBefore(existingValue, newValue) {
- const { node } = this.findNode(existingValue);
- if (!node) return false; // Not found
- return this.insertBeforeNode(node, newValue);
- }
-
- // Insert a new value after the first occurrence of an existing value (search by value)
- insertAfter(existingValue, newValue) {
- const { node } = this.findNode(existingValue);
- if (!node) return false; // Not found
- return this.insertAfterNode(node, newValue);
- }
-
-
-
- // Delete a given node from the list
- deleteNode(node) {
- if (!node) return false;
-
- if (this.length === 1 && node === this.head && node === this.tail) {
- // Only one element in the list
- this.head = null;
- this.tail = null;
- } else if (node === this.head) {
- // Node is the head
- this.head = node.next;
- this.head.prev = null;
- node.next = null;
- } else if (node === this.tail) {
- // Node is the tail
- this.tail = node.prev;
- this.tail.next = null;
- node.prev = null;
- } else {
- // Node is in the middle
- const prevNode = node.prev;
- const nextNode = node.next;
- prevNode.next = nextNode;
- nextNode.prev = prevNode;
- node.prev = null;
- node.next = null;
- }
-
- this.length--;
- return true;
- }
-
- }
-
-
- LinkedArray.Node = Node;
- return LinkedArray;
- })();
-
-
-
- class LimitedSizeSet extends Set {
- constructor(n) {
- super();
- this.limit = n;
- }
-
- add(key) {
- if (!super.has(key)) {
- super.add(key);
- let n = super.size - this.limit;
- if (n > 0) {
- const iterator = super.values();
- do {
- const firstKey = iterator.next().value; // Get the first (oldest) key
- super.delete(firstKey); // Delete the oldest key
- } while (--n > 0)
- }
- }
- }
-
- removeAdd(key) {
- super.delete(key);
- this.add(key);
- }
-
- }
-
-
-
- if (!document.createElement9512 && typeof document.createElement === 'function' && document.createElement.length === 1) {
-
- // sizing of Map / Set. Shall limit ?
-
- const hookTos = new Set(); // [[debug]]
- DEBUG_OPT && (rm3.hookTos = hookTos);
-
- // const reusePool = new Map(); // xx858
- const entryRecords = new WeakMap(); // a weak link between element and record
-
- // rm3.list = [];
-
- const operations = rm3.operations = new Set(); // to find out the "oldest elements"
-
- const availablePools = rm3.availablePools = new Map(); // those "old elements" can be used
- let lastTimeCheck = 0;
-
- const reuseRecord_ = new LimitedSizeSet(256); // [[debug]]
- const reuseCount_ = new Map();
-
- let noTimeCheck = false;
-
- // const defaultValues = new Map();
- // const noValues = new Map();
-
- const timeCheck = () => {
- // regularly check elements are old enough to put into the available pools
- // note: the characterists of YouTube components are non-volatile. So don't need to waste time to check weakRef.deref() is null or not for removing in operations.
-
- const ct = Date.now();
- if (ct - lastTimeCheck < CHECK_INTERVAL || noTimeCheck) return;
- lastTimeCheck = ct;
- noTimeCheck = true;
-
- // 16,777,216
- if (hookTos.size > 777216) hookTos.clear(); // just debug usage, dont concern
- if (operations.size > 7777216) {
- // extremely old elements in operations mean they have no attach/detach action. so no reuse as well. they are just trash in memory.
- // as no checking of the weakRef.deref() being null or not, those trash could be already cleaned. However we don't concern this.
- // (not to count whether they are actual memory trash or not)
- const half = operations.size >>> 1;
- let i = 0;
- for (const value of operations) {
- if (i++ > half) break;
- operations.delete(value);
- }
- }
-
- // {
- // // smallest to largest
- // // past to recent
-
- // const iterator = operations[Symbol.iterator]();
- // console.log(1831, '------------------------')
- // while (true) {
- // const iteratorResult = iterator.next(); // 順番に値を取りだす
- // if (iteratorResult.done) break; // 取り出し終えたなら、break
- // console.log(1835, iteratorResult.value[3])
- // }
-
- // console.log(1839, '------------------------')
- // }
-
- // Set iterator
- // s.add(2) s.add(6) s.add(1) s.add(3)
- // next: 2 -> 6 -> 1 -> 3
- // op1 (oldest) -> op2 -> op3 -> op4 (latest)
- const iterator = operations[Symbol.iterator]();
-
- const targetTime = ct - CONFIRM_TIME;
-
- const pivotNodes = new WeakMap();
-
- while (true) {
- const iteratorResult = iterator.next(); // 順番に値を取りだす
- if (iteratorResult.done) break; // 取り出し終えたなら、break
- const entryRecord = iteratorResult.value;
- if (entryRecord[3] > targetTime) break;
-
- if (!entryRecord[4] && entryRecord[1] < 0 && entryRecord[2] > 0) {
- const element = entryRecord[0].deref();
- const eKey = (element || 0).__rm3Tag003__;
- if (!eKey) {
- operations.delete(entryRecord);
- } else if (element.isConnected === false && insp(element).isAttached === false) {
- entryRecord[4] = true;
-
- let availablePool = availablePools.get(eKey);
- if (!availablePool) availablePools.set(eKey, availablePool = new LinkedArray());
- if (!(availablePool instanceof LinkedArray)) throw new Error();
- DEBUG_OPT && console.log(3885,'add key', eKey, availablePools.size)
- // rm3.showSize = ()=>availablePools.size
- // setTimeout(()=>{
- // // window?.euu1 = availablePools
- // // window?.euu2 = availablePools.size
- // console.log(availablePools.size)
- // }, 8000)
- let pivotNode = pivotNodes.get(availablePool);
- if (!pivotNode) pivotNodes.set(availablePool, pivotNode = availablePool.head) // cached the previous newest node (head) as pivotNode
-
- availablePool.insertBeforeNode(pivotNode, entryRecord); // head = newest, tail = oldest
-
- }
- }
-
- }
- noTimeCheck = false;
-
- }
-
- const attachedDefine = function () {
-
- Promise.resolve().then(timeCheck);
- try {
- const hostElement = this?.hostElement;
- if (hostElement instanceof HTMLElement) {
- const entryRecord = entryRecords.get(hostElement);
- if (entryRecord && entryRecord[0].deref() === hostElement && hostElement.isConnected === true && this?.isAttached === true) {
- noTimeCheck = true;
- const ct = Date.now();
- entryRecord[1] = ct;
- entryRecord[2] = -1;
- entryRecord[3] = ct;
- operations.delete(entryRecord);
- operations.add(entryRecord);
- noTimeCheck = false;
- // note: because of performance prespective, deletion for availablePools[eKey]'s linked element would not be done here.
- // entryRecord[4] is not required to be updated here.
- }
- }
- } catch (e) { }
- return this.attached9512();
- }
- const detachedDefine = function () {
-
- Promise.resolve().then(timeCheck);
- try {
- const hostElement = this?.hostElement;
- if (hostElement instanceof HTMLElement) {
- const entryRecord = entryRecords.get(hostElement);
- if (entryRecord && entryRecord[0].deref() === hostElement && hostElement.isConnected === false && this?.isAttached === false) {
- noTimeCheck= true;
- const ct = Date.now();
- entryRecord[2] = ct;
- entryRecord[1] = -1;
- entryRecord[3] = ct;
- operations.delete(entryRecord);
- operations.add(entryRecord);
- noTimeCheck= false;
- // note: because of performance prespective, deletion for availablePools[eKey]'s linked element would not be done here.
- // entryRecord[4] is not required to be updated here.
- }
- }
- } catch (e) { }
-
- return this.detached9512();
- }
-
-
- // function cpy(x) {
- // if (!x) return x;
- // try {
- // if (typeof x === 'object' && typeof x.length ==='number' && typeof x.slice === 'function') {
- // x = x.slice(0)
- // } else if (typeof x === 'object' && !x.length) {
- // x = JSON.parse(JSON.stringify(x));
- // } else {
- // return Object.assign({}, x);
- // }
- // } catch (e) { }
- // return x;
- // }
-
- async function digestMessage(message) {
- const msgUint8 = new TextEncoder().encode(message); // (utf-8 の) Uint8Array にエンコードする
- const hashBuffer = await crypto.subtle.digest("SHA-256", msgUint8); // メッセージをハッシュする
- const hashArray = Array.from(new Uint8Array(hashBuffer)); // バッファーをバイト列に変換する
- const hashHex = hashArray
- .map((b) => b.toString(16).padStart(2, "0"))
- .join(""); // バイト列を 16 進文字列に変換する
- return hashHex.toUpperCase();
- }
-
-
- let onPageContainer = null;
-
- const createComponentDefine_ = function (a, b, c) {
-
- Promise.resolve().then(timeCheck);
-
-
- const creatorTag = this?.is || this?.nodeName?.toLowerCase() || '';
-
- const componentTag = typeof a === 'string' ? a : ((a || 0).component || '');
-
-
-
- const eKey = creatorTag && componentTag ? `${creatorTag}.${componentTag}` : '*'; // '*' for play-safe
- const availablePool = availablePools.get(eKey);
-
- try {
-
- if (availablePool instanceof LinkedArray) {
- noTimeCheck = true;
-
- let node = availablePool.tail; // oldest
-
- while (node instanceof LinkedArray.Node) {
- const entryRecord = node.value;
- const prevNode = node.prev;
-
- let ok = false;
- let elm = null;
- if (entryRecord[1] < 0 && entryRecord[2] > 0 && entryRecord[4]) {
- elm = entryRecord[0].deref();
- // elm && console.log(3882, (elm.__shady_native_textContent || elm.textContent))
- if (elm && elm instanceof HTMLElement && elm.isConnected === false && insp(elm).isAttached === false && elm.parentNode === null) {
- ok = true;
- }
- }
-
- if (ok) {
-
- // useEntryRecord = entryRecord;
- entryRecord[4] = false;
- // console.log('nodeDeleted', 1, entryRecord[0].deref().nodeName)
- availablePool.deleteNode(node);
- // break;
-
- if (!onPageContainer) {
- let p = document.createElement('noscript');
- document.body.prepend(p);
- onPageContainer = p;
- }
-
- onPageContainer.appendChild(elm); // to fix some issues for the rendered elements
-
- const cnt = insp(elm);
-
-
- cnt.__dataInvalid = false;
- // cnt._initializeProtoProperties(cnt.data)
-
- // window.meaa = cnt.$.container;
- if (typeof (cnt.__data || 0) === 'object') {
- cnt.__data = Object.assign({}, cnt.__data);
- }
- cnt.__dataPending = {};
- cnt.__dataOld = {};
-
- try {
- cnt.markDirty();
- } catch (e) { }
- try {
- cnt.markDirtyVisibilityObserver();
- } catch (e) { }
-
- try{
- cnt.wasPrescan = cnt.wasVisible = !1
- }catch(e){}
-
-
- // try{
- // cnt._setPendingProperty('data', Object.assign({}, cntData), !0);
- // }catch(e){}
- // try {
- // cnt._flushProperties();
- // } catch (e) { }
-
- if (DEBUG_OPT && DEBUG_dataChangeReflection) {
-
- let jC1 = null;
- let jC2 = null;
- const jKey = `${Math.floor(Math.random() * 314159265359 + 314159265359).toString(36)}`;
- try {
- jC1 = (cnt.hostElement.__shady_native_textContent || cnt.hostElement.textContent);
- // console.log(83802, jKey, (cnt.hostElement.__shady_native_textContent || cnt.hostElement.textContent))
- } catch (e) {
- console.warn(e);
- }
-
- setTimeout(() => {
- try {
- jC2 = (cnt.hostElement.__shady_native_textContent || cnt.hostElement.textContent);
- // console.log(83804, jKey, (cnt.hostElement.__shady_native_textContent || cnt.hostElement.textContent))
- } catch (e) {
- console.warn(e);
- }
-
- (async () => {
-
-
-
- jC1 = await digestMessage(jC1);
- jC2 = await digestMessage(jC2);
-
- console.log(83804, jKey, jC1.substring(0, 7), jC2.substring(0, 7))
-
- })()
-
-
- }, 1000);
- }
-
- // // try{
-
- // // console.log(83801, JSON.stringify(cntData))
- // // }catch(e){
- // // console.warn(e);
- // // }
-
- // const jKey = `${Math.floor(Math.random() * 314159265359 + 314159265359).toString(36)}`;
- // try{
-
- // console.log(83802, jKey, (cnt.hostElement.__shady_native_textContent || cnt.hostElement.textContent))
- // }catch(e){
- // console.warn(e);
- // }
-
- // setTimeout(()=>{
- // // try{
-
- // // console.log(83803, JSON.stringify(cntData))
- // // }catch(e){
- // // console.warn(e);
- // // }
- // try{
-
- // console.log(83804, jKey, (cnt.hostElement.__shady_native_textContent || cnt.hostElement.textContent))
- // }catch(e){
- // console.warn(e);
- // }
- // }, 1000);
-
-
- // reference
- // https://www.youtube.com/s/desktop/c01ea7e3/jsbin/live_chat_polymer.vflset/live_chat_polymer.js
- // a.prototype._initializeProtoProperties = function(c) {
- // this.__data = Object.create(c);
- // this.__dataPending = Object.create(c);
- // this.__dataOld = {}
- // }
-
- // ------- (NO USE) ------
- //
- // a.prototype._initializeProperties = function() {
- // this.__dataProto && (this._initializeProtoProperties(this.__dataProto),
- // this.__dataProto = null);
- // b.prototype._initializeProperties.call(this)
- // }
- // ;
- // a.prototype._initializeProtoProperties = function(c) {
- // for (var d in c)
- // this._setProperty(d, c[d])
- // }
- //
- // ------- (NO USE) ------
-
-
- // // cnt.__dataReady = false;
- // cnt.__dataInvalid = true;
- // cnt.__dataEnabled = false; // tbc
- // // if('__dataEnabled' in cnt) cnt.__dataEnabled = false;
- // // if ('__dataReady' in cnt && typeof cnt.__dataReady === 'boolean') cnt.__dataReady = false;
- // // if ('__dataInvalid' in cnt && typeof cnt.__dataInvalid === 'boolean') cnt.__dataInvalid = true;
-
- // // try {
- // // if ('data' in cnt) cnt.data = null;
- // // if ('__data' in cnt) cnt.__data = null;
- // // } catch (e) {
- // // console.warn(e)
- // // }
-
- // // try {
- // // if ('data' in cnt) cnt.data = {};
- // // if ('__data' in cnt) cnt.__data = {};
- // // } catch (e) {
- // // console.warn(e)
- // // }
-
-
-
-
-
-
-
-
-
-
-
- // // const noValue = noValues.get(eKey);
- // // if(noValue){
- // // if(!noValue.data) cnt.data = noValue.data;
- // // if(!noValue.__data) cnt.data = noValue.__data;
- // // }
-
- // // const defaultValue = defaultValues.get(eKey);
- // // if (defaultValue) {
-
- // // try {
- // // if ('data' in defaultValue) cnt.data = cpy(cnt.data);
- // // if ('__data' in defaultValue) cnt.__data = cpy(cnt.__data);
- // // } catch (e) {
- // // console.warn(e)
- // // }
- // // }
-
- // // const flg001 = elm.__rm3Flg001__;
- // // if (cnt.__dataEnabled !== flg001) cnt.__dataEnabled = flg001;
-
-
-
-
-
-
-
- // // const flg001 = elm.__rm3Flg001__;
- // // if (cnt.__dataEnabled !== flg001) cnt.__dataEnabled = flg001;
-
-
- // if (cnt.__dataPending && typeof cnt.__dataPending === 'object') cnt.__dataPending = null;
- // if (cnt.__dataOld && typeof cnt.__dataOld === 'object') cnt.__dataOld = null;
-
- // // cnt.__dataInstanceProps = null;
- // if (cnt.__dataCounter && typeof cnt.__dataCounter === 'number') cnt.__dataCounter = 0;
- // // cnt.__serializing = !1;
-
-
-
- // if ('__dataClientsInitialized' in cnt || '__dataClientsReady' in cnt) {
-
- // if ('__dataClientsInitialized' in cnt !== '__dataClientsReady' in cnt) {
-
- // console.log('[rm3-warning] __dataClientsInitialized and __dataClientsReady should exist in the controller');
-
- // }
-
- // cnt.__dataClientsReady = !1;
- // cnt.__dataLinkedPaths = cnt.__dataToNotify = cnt.__dataPendingClients = null;
- // cnt.__dataHasPaths = !1;
- // cnt.__dataCompoundStorage = null; // cnt.__dataCompoundStorage = cnt.__dataCompoundStorage || null;
- // cnt.__dataHost = null; // cnt.__dataHost = cnt.__dataHost || null;
- // if (!cnt.__dataTemp) cnt.__dataTemp = {}; // cnt.__dataTemp = {};
- // cnt.__dataClientsInitialized = !1;
-
- // }
-
- if (entryRecord[5] < 1e9) entryRecord[5] += 1;
- DEBUG_OPT && Promise.resolve().then(() => console.log(`${eKey} reuse`, entryRecord)); // give some time for attach process
- DEBUG_OPT && reuseRecord_.add([Date.now(), cnt.is, entryRecord]);
- DEBUG_OPT && reuseCount_.set(cnt.is, (reuseCount_.get(cnt.is) || 0) + 1)
- if (rm3.reuseCount < 1e9) rm3.reuseCount++;
-
- return elm;
-
-
- }
-
- // console.log('condi88', entryRecord[1] < 0 , entryRecord[2] > 0 , !!entryRecord[4], !!entryRecord[0].deref())
-
- entryRecord[4] = false;
-
- // console.log(entryRecord);
- // console.log('nodeDeleted',2, entryRecord[0]?.deref()?.nodeName)
- availablePool.deleteNode(node);
- node = prevNode;
-
- }
- // for(const ) availablePool
- // noTimeCheck = false;
- }
-
- } catch (e) {
- console.warn(e)
- }
- noTimeCheck = false;
-
-
- // console.log('createComponentDefine_', a, b, c)
-
- // if (!reusePool.has(componentTag)) reusePool.set(componentTag, new LinkedArray()); // xx858
-
- // const pool = reusePool.get(componentTag); // xx858
- // if (!(pool instanceof LinkedArray)) throw new Error(); // xx858
-
-
- const newElement = this.createComponent9512_(a, b, c);
- // if(componentTag.indexOf( 'ticker')>=0)console.log(1883, a,newElement)
-
- try {
-
- const cntE = insp(newElement);
- if (!cntE.attached9512 && cntE.attached) {
-
- const cProtoE = getProto(newElement);
-
-
- if (cProtoE.attached === cntE.attached) {
-
- if (!cProtoE.attached9512 && typeof cProtoE.attached === 'function' && cProtoE.attached.length === 0) {
-
- cProtoE.attached9512 = cProtoE.attached;
-
- cProtoE.attached = attachedDefine;
- // hookTos.add(a);
- }
- } else {
-
- if (typeof cntE.attached === 'function' && cntE.attached.length === 3) {
- cntE.attached9512 = cntE.attached;
-
- cntE.attached = attachedDefine;
- // hookTos.add(a);
- }
- }
-
-
- }
-
- if (!cntE.detached9512 && cntE.detached) {
-
- const cProtoE = getProto(newElement);
-
-
- if (cProtoE.detached === cntE.detached) {
-
- if (!cProtoE.detached9512 && typeof cProtoE.detached === 'function' && cProtoE.detached.length === 0) {
-
- cProtoE.detached9512 = cProtoE.detached;
-
- cProtoE.detached = detachedDefine;
- // hookTos.add(a);
- }
- } else {
-
- if (typeof cntE.detached === 'function' && cntE.detached.length === 3) {
- cntE.detached9512 = cntE.detached;
-
- cntE.detached = detachedDefine;
- // hookTos.add(a);
- }
- }
-
-
- }
-
-
- const acceptance = true;
- // const acceptance = !cntE.__dataReady && cntE.__dataInvalid !== false; // we might need to change the acceptance condition along with YouTube Coding updates.
- if (acceptance) {
-
- // [[ weak ElementNode, attached time, detached time, time of change, inside availablePool, reuse count ]]
- const entryRecord = [new WeakRef(newElement), -1, -1, -1, false, 0];
-
- newElement.__rm3Tag003__ = eKey;
- // pool.push(entryRecord);
- entryRecords.set(newElement, entryRecord);
- // newElement.__rm3Tag001__ = creatorTag;
- // newElement.__rm3Tag002__ = componentTag;
-
- // newElement.__rm3Flg001__ = cntE.__dataEnabled;
- // // console.log(5928, cntE.data, cntE.__data)
- // if (!defaultValues.has(eKey)){
-
- // const o = {};
-
- // if('data' in cntE) o.data = cpy(cntE.data);
- // if('__data' in cntE) o.__data = cpy(cntE.__data);
- // defaultValues.set(eKey, o);
-
- // }
-
- // if(!noValues.has(eKey)){
- // const o = {};
- // o.data = true;
- // try {
-
- // if (!cntE.data) o.data = cntE.data;
- // } catch (e) { }
-
- // o.__data = true;
- // try {
-
- // if (!cntE.__data) o.__data = cntE.__data;
- // } catch (e) { }
- // noValues.set(eKey, o)
- // }
-
- } else {
- // console.log(5920, cntE.__dataReady, cntE.__dataInvalid)
- }
-
-
- } catch (e) {
- console.warn(e);
- }
- return newElement;
-
-
- }
-
- document.createElement9512 = document.createElement;
- document.createElement = function (a) {
- const r = document.createElement9512(a);
- try {
- const cnt = insp(r);
- if (cnt.createComponent_ && !cnt.createComponent9512_) {
- const cProto = getProto(r);
- if (cProto.createComponent_ === cnt.createComponent_) {
-
- if (!cProto.createComponent9512_ && typeof cProto.createComponent_ === 'function' && cProto.createComponent_.length === 3) {
-
- cProto.createComponent9512_ = cProto.createComponent_;
-
- cProto.createComponent_ = createComponentDefine_;
- DEBUG_OPT && hookTos.add(a);
- }
- } else {
-
- if (typeof cnt.createComponent_ === 'function' && cnt.createComponent_.length === 3) {
- cnt.createComponent9512_ = cnt.createComponent_;
-
- cnt.createComponent_ = createComponentDefine_;
- DEBUG_OPT && hookTos.add(a);
- }
- }
-
- }
-
- } catch (e) {
- console.warn(e)
- }
-
-
- return r;
- }
-
- rm3.checkWhetherUnderParent = () => {
- const r = [];
- for (const operation of operations) {
- const elm = operation[0].deref();
- if (operation[2] > 0) {
-
- r.push([!!elm, elm?.nodeName.toLowerCase(), elm?.parentNode === null]);
- }
- }
- return r;
- }
-
- rm3.hookTags = () => {
-
- const r = new Set();
- for (const operation of operations) {
- const elm = operation[0].deref();
- if (elm && elm.is) {
-
- r.add(elm.is)
- }
- }
- return [...r];
- }
-
-
- DEBUG_OPT && (rm3.reuseRecord = () => {
- return [...reuseRecord_]; // [[debug]]
- });
-
- DEBUG_OPT && (rm3.reuseCount_ = reuseCount_);
-
- }
-
- (rm3.reuseCount = 0); // window.rm3 will be zero initially if this script has no runtime complier error in the initialization phase.
-
- })();