Skip to content

Commit 3c12173

Browse files
committed
Add ability to execute aeld scriptlet at a later time
As per discussion with filter list maintainers. THis requires to use JSON notation for parameter passing: - "runAt": "end" = execute scriptlet at `DOMContentLoaded` event - "runAt": "idle" = execute scriptlet at `load` event
1 parent 7cba521 commit 3c12173

File tree

1 file changed

+73
-37
lines changed

1 file changed

+73
-37
lines changed

assets/resources/scriptlets.js

Lines changed: 73 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,35 @@ function shouldLog(details) {
117117
return scriptletGlobals.has('canDebug') && details.log;
118118
}
119119

120+
/******************************************************************************/
121+
122+
builtinScriptlets.push({
123+
name: 'run-at.fn',
124+
fn: runAt,
125+
});
126+
function runAt(fn, when) {
127+
const intFromReadyState = state => {
128+
return ({
129+
loading: 1,
130+
interactive: 2,
131+
end: 2,
132+
complete: 3,
133+
idle: 3,
134+
})[`${state}`] || 0;
135+
};
136+
const runAt = intFromReadyState(when);
137+
if ( intFromReadyState(document.readyState) >= runAt ) {
138+
fn(); return;
139+
}
140+
const options = { capture: true };
141+
const onStateChange = ( ) => {
142+
if ( intFromReadyState(document.readyState) < runAt ) { return; }
143+
fn();
144+
document.removeEventListener('readystatechange', onStateChange, options);
145+
};
146+
document.addEventListener('readystatechange', onStateChange, options);
147+
}
148+
120149
/*******************************************************************************
121150
122151
Injectable scriptlets
@@ -432,6 +461,7 @@ builtinScriptlets.push({
432461
fn: addEventListenerDefuser,
433462
dependencies: [
434463
'pattern-to-regex.fn',
464+
'run-at.fn',
435465
'safe-self.fn',
436466
'should-debug.fn',
437467
'should-log.fn',
@@ -453,29 +483,45 @@ function addEventListenerDefuser(
453483
const rePattern = patternToRegex(pattern);
454484
const log = shouldLog(details);
455485
const debug = shouldDebug(details);
456-
const proto = self.EventTarget.prototype;
457-
proto.addEventListener = new Proxy(proto.addEventListener, {
458-
apply: function(target, thisArg, args) {
459-
let type, handler;
460-
try {
461-
type = String(args[0]);
462-
handler = String(args[1]);
463-
} catch(ex) {
464-
}
465-
const matchesType = safe.RegExp_test.call(reType, type);
466-
const matchesHandler = safe.RegExp_test.call(rePattern, handler);
467-
const matchesEither = matchesType || matchesHandler;
468-
const matchesBoth = matchesType && matchesHandler;
469-
if ( log === 1 && matchesBoth || log === 2 && matchesEither || log === 3 ) {
470-
safe.uboLog(`addEventListener('${type}', ${handler})`);
471-
}
472-
if ( debug === 1 && matchesBoth || debug === 2 && matchesEither ) {
473-
debugger; // jshint ignore:line
486+
const trapEddEventListeners = ( ) => {
487+
const eventListenerHandler = {
488+
apply: function(target, thisArg, args) {
489+
let type, handler;
490+
try {
491+
type = String(args[0]);
492+
handler = String(args[1]);
493+
} catch(ex) {
494+
}
495+
const matchesType = safe.RegExp_test.call(reType, type);
496+
const matchesHandler = safe.RegExp_test.call(rePattern, handler);
497+
const matchesEither = matchesType || matchesHandler;
498+
const matchesBoth = matchesType && matchesHandler;
499+
if ( log === 1 && matchesBoth || log === 2 && matchesEither || log === 3 ) {
500+
safe.uboLog(`addEventListener('${type}', ${handler})`);
501+
}
502+
if ( debug === 1 && matchesBoth || debug === 2 && matchesEither ) {
503+
debugger; // jshint ignore:line
504+
}
505+
if ( matchesBoth ) { return; }
506+
return Reflect.apply(target, thisArg, args);
474507
}
475-
if ( matchesBoth ) { return; }
476-
return Reflect.apply(target, thisArg, args);
477-
}
478-
});
508+
};
509+
self.EventTarget.prototype.addEventListener = new Proxy(
510+
self.EventTarget.prototype.addEventListener,
511+
eventListenerHandler
512+
);
513+
self.document.addEventListener = new Proxy(
514+
self.document.addEventListener,
515+
eventListenerHandler
516+
);
517+
self.addEventListener = new Proxy(
518+
self.addEventListener,
519+
eventListenerHandler
520+
);
521+
};
522+
runAt(( ) => {
523+
trapEddEventListeners();
524+
}, details.runAt);
479525
}
480526

481527
/******************************************************************************/
@@ -979,6 +1025,9 @@ builtinScriptlets.push({
9791025
name: 'set-constant.js',
9801026
aliases: [ 'set.js' ],
9811027
fn: setConstant,
1028+
dependencies: [
1029+
'run-at.fn',
1030+
],
9821031
});
9831032
function setConstant(
9841033
arg1 = '',
@@ -1144,22 +1193,9 @@ function setConstant(
11441193
};
11451194
trapChain(window, chain);
11461195
}
1147-
const runAt = details.runAt;
1148-
if ( runAt === 0 ) {
1149-
setConstant(chain, cValue); return;
1150-
}
1151-
const docReadyState = ( ) => {
1152-
return ({ loading: 1, interactive: 2, complete: 3, })[document.readyState] || 0;
1153-
};
1154-
if ( docReadyState() >= runAt ) {
1155-
setConstant(chain, cValue); return;
1156-
}
1157-
const onReadyStateChange = ( ) => {
1158-
if ( docReadyState() < runAt ) { return; }
1196+
runAt(( ) => {
11591197
setConstant(chain, cValue);
1160-
document.removeEventListener('readystatechange', onReadyStateChange);
1161-
};
1162-
document.addEventListener('readystatechange', onReadyStateChange);
1198+
}, details.runAt);
11631199
}
11641200

11651201
/******************************************************************************/

0 commit comments

Comments
 (0)