diff options
Diffstat (limited to 'raveos-theme/gnome/theme-data/extensions/installed/ShutdownTimer@deminder/modules/injection.js')
| -rw-r--r-- | raveos-theme/gnome/theme-data/extensions/installed/ShutdownTimer@deminder/modules/injection.js | 192 |
1 files changed, 0 insertions, 192 deletions
diff --git a/raveos-theme/gnome/theme-data/extensions/installed/ShutdownTimer@deminder/modules/injection.js b/raveos-theme/gnome/theme-data/extensions/installed/ShutdownTimer@deminder/modules/injection.js deleted file mode 100644 index 7d5bdd1..0000000 --- a/raveos-theme/gnome/theme-data/extensions/installed/ShutdownTimer@deminder/modules/injection.js +++ /dev/null @@ -1,192 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Deminder <tremminder@gmail.com> -// SPDX-License-Identifier: GPL-3.0-or-later -import { logDebug } from './util.js'; - -/** - * The InjectionTracker helps revert object property injections 'out of order' - * by keeping track of the injection history. - * This is useful when overriding the same method from mulitple extensions, - * for instance, `Main.panel.statusArea.quickSettings._addItems`. - * - * The InjectionManager does not work when multiple extensions override the same method. - * Its `restoreMethod` only restores correctly if it is called in reverse order to `overrideMethod`. - * - */ -export class InjectionTracker { - localInjections = []; - - /** - * Inject a property into an object. - * - * To revert the injection call `injection.clear()`. - * - * @param {object} obj the target object - * @param {string} prop the property name - * @param {any} value the new property value - * @param {boolean} isPropertyDescriptor whether the value is a property descriptor - * - * @returns {object} an injection object - * provding `injection.original` and `injection.previous` property values - */ - injectProperty(obj, prop, value, isPropertyDescriptor) { - let propertyDescriptor = Object.getOwnPropertyDescriptor(obj, prop); - if (!propertyDescriptor) { - if (prop in obj) { - propertyDescriptor = { - value: obj[prop], - writable: true, - configurable: true, - }; - } else { - throw new Error( - `Injection target object does not have a '${prop}' property!` - ); - } - } - // Keep history; mutated by each injection - const histories = obj.__injectionHistories ?? {}; - const history = histories[prop] ?? []; - // Push old property descriptor to history - history.push(propertyDescriptor); - histories[prop] = history; - obj.__injectionHistories = histories; - - const injectionId = history.length; - logDebug('[new] injectionid', injectionId); - - // Override value - Object.defineProperty( - obj, - prop, - isPropertyDescriptor - ? value - : { value, writable: false, configurable: true } - ); - - const localInjectionId = this.localInjections.length; - const injection = createInjection(obj, prop, history, injectionId, () => { - // Remove from local injections - this.localInjections[localInjectionId] = undefined; - const pruneIndex = - this.localInjections.length - - 1 - - [...this.localInjections].reverse().findIndex(inj => inj !== undefined); - if (pruneIndex === this.localInjections.length) { - logDebug('[local-cleanclear]'); - this.localInjections = []; - } else { - logDebug('[local-nocleanclear]'); - this.localInjections = this.localInjections.slice(0, pruneIndex); - } - }); - this.localInjections.push(injection); - return injection; - } - - /** - * Clear all injections made by this instance. - */ - clearAll() { - this.localInjections - .filter(inj => inj !== undefined) - .forEach(inj => inj.clear()); - } -} - -function createInjection(obj, prop, history, injectionId, clearHook) { - let reverted = false; - const readDescriptorValue = descriptor => - 'get' in descriptor ? descriptor.get.call(obj) : descriptor.value; - return { - /** - * Read the original property value before any injections. - */ - get original() { - // Using h instead history to remain valid after `clear()` - const h = obj.__injectionHistories?.[prop]; - return readDescriptorValue( - h?.length ? h[0] : Object.getOwnPropertyDescriptor(obj, prop) - ); - }, - - /** - * Read the previous property value from the injection history. - * - * Valid after `clear()` as long as no new injection occurs. - */ - get previous() { - return history.length - ? readDescriptorValue( - injectionId > history.length - ? Object.getOwnPropertyDescriptor(obj, prop) - : popPropertyDescriptorFromHistory( - // previous history - history.slice(0, injectionId) - ) - ) - : this.original; - }, - - /** - * Clear the injection from the injection history. - */ - clear() { - if (!reverted) { - reverted = true; - clearHook(); - - // Remove from global injections - if (injectionId >= history.length) { - logDebug( - '[remclear] injectionID', - injectionId, - 'historylen', - history.length - ); - // Restore property of obj - Object.defineProperty( - obj, - prop, - popPropertyDescriptorFromHistory(history) - ); - // Cleanup empty history - if (history.length === 0) { - logDebug('[cleanclear]'); - delete obj.__injectionHistories[prop]; - - // Cleanup empty history store - if (Object.keys(obj.__injectionHistories).length === 0) { - delete obj.__injectionHistories; - } - } else { - logDebug('[nocleanclear] history.length', history.length); - } - } else { - logDebug( - '[setclear] injectionID', - injectionId, - 'historylen', - history.length - ); - // Clear injection from history - history[injectionId] = undefined; - } - } - }, - - /** - * Count of previous injections. Is 1 if there is only this injection. - */ - get count() { - return history.slice(0, injectionId).filter(i => i !== undefined).length; - }, - }; -} - -function popPropertyDescriptorFromHistory(history) { - let propertyDescriptor; - do { - propertyDescriptor = history.pop(); - } while (history.length && propertyDescriptor === undefined); - return propertyDescriptor; -} |