Skip to content

Commit

Permalink
fix ThrottleWrapper (former AsyncWrapper)
Browse files Browse the repository at this point in the history
Squashed commit of the following:

commit 05270fb58665ae9c7fbd03b9effd227f4c566d92
Author: Slava Leleka <[email protected]>
Date:   Tue Oct 11 16:08:40 2022 +0300

    fix comment for throttleDelayMs

commit 8fb1a295313083aa5ffc0d740bf723aa3f77996e
Merge: 5bb1b4d b2359c3
Author: Slava Leleka <[email protected]>
Date:   Tue Oct 11 16:03:18 2022 +0300

    Merge branch 'epic/AG-3532' into fix/AG-16841

commit 5bb1b4da9ad17fd7761fc6bd373ba83847ddae99
Merge: 2cd4f82 4bd79b2
Author: Slava Leleka <[email protected]>
Date:   Tue Oct 11 15:33:13 2022 +0300

    Merge branch 'epic/AG-3532' into fix/AG-16841

commit 2cd4f82e59a0989a140ceb775be9ed16ae11e4fa
Merge: c084e6e e8286b1
Author: Slava Leleka <[email protected]>
Date:   Tue Oct 11 12:14:00 2022 +0300

    Merge branch 'epic/AG-3532' into fix/AG-16841

commit c084e6eeb33a78fad3a087b1f2c09f9292ffb495
Author: Slava Leleka <[email protected]>
Date:   Mon Oct 10 19:07:53 2022 +0300

    rename file

commit 7ecfb7657d4848b77f3e3438f31ea04d64facb2a
Author: Slava Leleka <[email protected]>
Date:   Fri Oct 7 13:09:53 2022 +0300

    add comment for ThrottleWrapper's private wrappedCallback

commit abd4874a42376e51e9e9a30b26c34e4071fb43b8
Author: Slava Leleka <[email protected]>
Date:   Thu Oct 6 19:31:30 2022 +0300

    fix WrappedCallback types

commit fc79a7e7947a9bec9757ee006dfaddaa8b1d5dff
Author: Slava Leleka <[email protected]>
Date:   Thu Oct 6 19:10:33 2022 +0300

    clear ThrottleWrapper timeouts better

commit 5f531e48dd0c47138265c612fe15a70601fe8b87
Author: Slava Leleka <[email protected]>
Date:   Thu Oct 6 16:02:58 2022 +0300

    rename AsyncWrapper -> ThrottleWrapper

commit d31ed8f6de95a723e97d2a4ff0375fedfa03002d
Author: Slava Leleka <[email protected]>
Date:   Thu Oct 6 15:47:22 2022 +0300

    fix comment for throttleDelayMs

commit e70dca281dd00596cfe47469997856cacd93a87d
Author: Slava Leleka <[email protected]>
Date:   Thu Oct 6 15:43:46 2022 +0300

    fix comment for throttleDelayMs

commit 4998b8ce15acd95cb50a76aa553e2145ec0f6939
Author: Slava Leleka <[email protected]>
Date:   Thu Oct 6 15:34:45 2022 +0300

    rename timeout and timeoutId
  • Loading branch information
slavaleleka committed Oct 12, 2022
1 parent b2359c3 commit 4d9e119
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 21 deletions.
14 changes: 7 additions & 7 deletions src/extended-css/extended-css.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ExtCssDocument } from '../selector';
import { parse as parseStylesheet } from '../stylesheet';

import { AsyncWrapper } from './helpers/async-wrapper';
import { ThrottleWrapper } from './helpers/throttle-wrapper';
import { applyRules } from './helpers/rules-applier';
import { revertStyle } from './helpers/style-setter';
import { mainDisconnect } from './helpers/document-observer';
Expand All @@ -17,7 +17,7 @@ import { logger } from '../common/utils/logger';
import { DEBUG_PSEUDO_PROPERTY_GLOBAL_VALUE } from '../common/constants';

/**
* Throttle timeout for AsyncWrapper to execute applyRules()
* Throttle timeout for ThrottleWrapper to execute applyRules()
*/
const APPLY_RULES_DELAY = 150;

Expand Down Expand Up @@ -78,7 +78,7 @@ export interface ExtCssConfiguration {
* Parses css stylesheet with any selectors (passed to its argument as styleSheet),
* and guarantee its applying as mutation observer is used to prevent the restyling of needed elements by other scripts.
* This style protection is limited to 50 times to avoid infinite loop (MAX_STYLE_PROTECTION_COUNT).
* Our own AsyncWrapper is used for styles applying to avoid too often lib reactions on page mutations.
* Our own ThrottleWrapper is used for styles applying to avoid too often lib reactions on page mutations.
*
* Constructor creates the instance of class which should be run be `apply()` method to apply the rules,
* and the applying can be stopped by `dispose()`.
Expand All @@ -89,7 +89,7 @@ export interface ExtCssConfiguration {
export class ExtendedCss {
private context: Context;

private applyRulesScheduler: AsyncWrapper;
private applyRulesScheduler: ThrottleWrapper;

private applyRulesCallbackListener: () => void;

Expand Down Expand Up @@ -123,7 +123,7 @@ export class ExtendedCss {
return ruleData.debug === DEBUG_PSEUDO_PROPERTY_GLOBAL_VALUE;
});

this.applyRulesScheduler = new AsyncWrapper(this.context, applyRules, APPLY_RULES_DELAY);
this.applyRulesScheduler = new ThrottleWrapper(this.context, applyRules, APPLY_RULES_DELAY);

this.context.mainCallback = this.applyRulesScheduler.run.bind(this.applyRulesScheduler);

Expand Down Expand Up @@ -186,13 +186,13 @@ export class ExtendedCss {
throw new Error('Selector should be defined as a string.');
}

const start = AsyncWrapper.now();
const start = ThrottleWrapper.now();

try {
const extCssDoc = new ExtCssDocument();
return extCssDoc.querySelectorAll(selector);
} finally {
const end = AsyncWrapper.now();
const end = ThrottleWrapper.now();
if (!noTiming) {
logger.info(`[ExtendedCss] Elapsed: ${Math.round((end - start) * 1000)} μs.`);
}
Expand Down
6 changes: 3 additions & 3 deletions src/extended-css/helpers/rules-applier.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AsyncWrapper } from './async-wrapper';
import { ThrottleWrapper } from './throttle-wrapper';
import { mainDisconnect, mainObserve } from './document-observer';
import { applyStyle, revertStyle } from './style-setter';
import { protectStyleAttribute } from './style-protector';
Expand Down Expand Up @@ -33,7 +33,7 @@ const applyRule = (context: Context, ruleData: ExtCssRuleData): HTMLElement[] =>
const isDebuggingMode = !!ruleData.debug || context.debug;
let startTime: number | undefined;
if (isDebuggingMode) {
startTime = AsyncWrapper.now();
startTime = ThrottleWrapper.now();
}

const { ast } = ruleData;
Expand All @@ -60,7 +60,7 @@ const applyRule = (context: Context, ruleData: ExtCssRuleData): HTMLElement[] =>
});

if (isDebuggingMode && startTime) {
const elapsedTimeMs = AsyncWrapper.now() - startTime;
const elapsedTimeMs = ThrottleWrapper.now() - startTime;
if (!ruleData.timingStats) {
ruleData.timingStats = new TimingStats();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,41 @@ import { isNumber } from '../../common/utils/numbers';
import { Context } from './types';

const isSupported = (typeof window.requestAnimationFrame !== 'undefined');
const rAF = isSupported ? requestAnimationFrame : window.setTimeout;
const timeout = isSupported ? requestAnimationFrame : window.setTimeout;
const deleteTimeout = isSupported ? cancelAnimationFrame : clearTimeout;
const perf = isSupported ? performance : Date;

const DEFAULT_THROTTLE_DELAY_MS = 150;

type WrappedCallback = (timestamp: number) => void;
type WrappedCallback = (timestamp?: number) => void;

/**
* Method for filtering rules applying
*/
type ApplyRulesCallback = (context: Context) => void;

/**
* The purpose of AsyncWrapper is to debounce calls of the function
* The purpose of ThrottleWrapper is to throttle calls of the function
* that applies ExtendedCss rules. The reasoning here is that the function calls
* are triggered by MutationObserver and there may be many mutations in a short period of time.
* We do not want to apply rules on every mutation so we use this helper to make sure
* that there is only one call in the given amount of time.
*/
export class AsyncWrapper {
export class ThrottleWrapper {
private context: Context;

private callback?: ApplyRulesCallback;

// number, the provided callback should be executed twice in this time frame
/**
* the provided callback should be executed twice in this time frame:
* very first time and not more often than throttleDelayMs for further executions.
* @see {@link ThrottleWrapper.run}
*/
private throttleDelayMs: number;

private wrappedCb: WrappedCallback;

private rAFid?: number;
private timeoutId?: number;

private timerId?: number;

Expand All @@ -44,11 +49,22 @@ export class AsyncWrapper {
this.wrappedCb = this.wrappedCallback.bind(this);
}

/**
* Wraps the callback (which supposed to be `applyRules`),
* needed to update `lastRunTime` and clean previous timeouts for proper execution of the callback
* @param timestamp
*/
private wrappedCallback(timestamp?: number): void {
this.lastRunTime = isNumber(timestamp)
? timestamp
: perf.now();
delete this.rAFid;
// `timeoutId` can be requestAnimationFrame-related
// so cancelAnimationFrame() as deleteTimeout() needs the arg to be defined
if (this.timeoutId) {
deleteTimeout(this.timeoutId);
delete this.timeoutId;
}
clearTimeout(this.timerId);
delete this.timerId;
if (this.callback) {
this.callback(this.context);
Expand All @@ -59,13 +75,13 @@ export class AsyncWrapper {
* Indicates whether there is a scheduled callback.
*/
private hasPendingCallback(): boolean {
return isNumber(this.rAFid) || isNumber(this.timerId);
return isNumber(this.timeoutId) || isNumber(this.timerId);
}

/**
* Schedules the function which applies ExtendedCss rules before the next animation frame.
*
* Wraps function execution into requestAnimationFrame or setTimeout.
* Wraps function execution into `timeout` — requestAnimationFrame or setTimeout.
* For the first time runs the function without any condition.
* As it may be triggered by any mutation which may occur too ofter, we limit the function execution:
* 1. If `elapsedTime` since last function execution is less then set `throttleDelayMs`,
Expand All @@ -84,7 +100,7 @@ export class AsyncWrapper {
return;
}
}
this.rAFid = rAF(this.wrappedCb);
this.timeoutId = timeout(this.wrappedCb);
}

public static now(): number {
Expand Down
2 changes: 1 addition & 1 deletion src/extended-css/helpers/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export interface Context {
domMutationObserver?: MutationObserver;

/**
* Actually the main callback — applyRules() scheduled by AsyncWrapper
* Actually the main callback — applyRules() scheduled by ThrottleWrapper
*/
mainCallback: MainCallback;

Expand Down

0 comments on commit 4d9e119

Please sign in to comment.