diff options
Diffstat (limited to 'data/extensions/uBlock0@raymondhill.net/js/resources/run-at.js')
-rw-r--r-- | data/extensions/uBlock0@raymondhill.net/js/resources/run-at.js | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/data/extensions/uBlock0@raymondhill.net/js/resources/run-at.js b/data/extensions/uBlock0@raymondhill.net/js/resources/run-at.js new file mode 100644 index 0000000..35036d2 --- /dev/null +++ b/data/extensions/uBlock0@raymondhill.net/js/resources/run-at.js @@ -0,0 +1,96 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2019-present Raymond Hill + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see {http://www.gnu.org/licenses/}. + + Home: https://github.com/gorhill/uBlock + +*/ + +import { registerScriptlet } from './base.js'; +import { safeSelf } from './safe-self.js'; + +/* eslint no-prototype-builtins: 0 */ + +/** + * @helperScriptlet run-at.fn + * + * @description + * Execute a function at a specific page-load milestone. + * + * @param fn + * The function to call. + * + * @param when + * An identifier which tells when the function should be executed. + * See <https://developer.mozilla.org/en-US/docs/Web/API/Document/readyState>. + * + * @example + * `runAt(( ) => { start(); }, 'interactive')` + * + * */ + +export function runAt(fn, when) { + const intFromReadyState = state => { + const targets = { + 'loading': 1, 'asap': 1, + 'interactive': 2, 'end': 2, '2': 2, + 'complete': 3, 'idle': 3, '3': 3, + }; + const tokens = Array.isArray(state) ? state : [ state ]; + for ( const token of tokens ) { + const prop = `${token}`; + if ( Object.hasOwn(targets, prop) === false ) { continue; } + return targets[prop]; + } + return 0; + }; + const runAt = intFromReadyState(when); + if ( intFromReadyState(document.readyState) >= runAt ) { + fn(); return; + } + const onStateChange = ( ) => { + if ( intFromReadyState(document.readyState) < runAt ) { return; } + fn(); + safe.removeEventListener.apply(document, args); + }; + const safe = safeSelf(); + const args = [ 'readystatechange', onStateChange, { capture: true } ]; + safe.addEventListener.apply(document, args); +} +registerScriptlet(runAt, { + name: 'run-at.fn', + dependencies: [ + safeSelf, + ], +}); + +/******************************************************************************/ + +export function runAtHtmlElementFn(fn) { + if ( document.documentElement ) { + fn(); + return; + } + const observer = new MutationObserver(( ) => { + observer.disconnect(); + fn(); + }); + observer.observe(document, { childList: true }); +} +registerScriptlet(runAtHtmlElementFn, { + name: 'run-at-html-element.fn', +}); |