From c24fae555a721054f51c83a73c78791d1ae9e9e1 Mon Sep 17 00:00:00 2001 From: SukkaW Date: Fri, 25 Oct 2024 02:23:51 +0800 Subject: [PATCH] Fix: guard pending promise --- Build/lib/rules/base.ts | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/Build/lib/rules/base.ts b/Build/lib/rules/base.ts index 5e1a02d8..a8052777 100644 --- a/Build/lib/rules/base.ts +++ b/Build/lib/rules/base.ts @@ -35,7 +35,7 @@ export abstract class RuleOutput { protected otherRules: string[] = []; protected abstract type: 'domainset' | 'non_ip' | 'ip'; - protected pendingPromise = Promise.resolve(); + private pendingPromise: Promise | null = null; static readonly jsonToLines = (json: unknown): string[] => stringify(json).split('\n'); @@ -125,7 +125,7 @@ export abstract class RuleOutput { } addFromDomainset(source: AsyncIterable | Iterable | string[]) { - this.pendingPromise = this.pendingPromise.then(() => this.addFromDomainsetPromise(source)); + this.pendingPromise = (this.pendingPromise ||= Promise.resolve()).then(() => this.addFromDomainsetPromise(source)); return this; } @@ -193,7 +193,7 @@ export abstract class RuleOutput { } addFromRuleset(source: AsyncIterable | Iterable) { - this.pendingPromise = this.pendingPromise.then(() => this.addFromRulesetPromise(source)); + this.pendingPromise = (this.pendingPromise ||= Promise.resolve()).then(() => this.addFromRulesetPromise(source)); return this; } @@ -235,13 +235,26 @@ export abstract class RuleOutput { protected abstract preprocess(): NonNullable; - done() { - return this.pendingPromise; + async done() { + await this.pendingPromise; + this.pendingPromise = null; + } + + private guardPendingPromise() { + console.log('Pending promise:', this.pendingPromise); + + // reverse invariant + if (this.pendingPromise !== null) { + console.trace('Pending promise:', this.pendingPromise); + throw new Error('You should call done() before calling this method'); + } } private $$preprocessed: TPreprocessed | null = null; get $preprocessed() { if (this.$$preprocessed === null) { + this.guardPendingPromise(); + this.$$preprocessed = this.span.traceChildSync('RuleOutput#preprocess: ' + this.id, () => this.preprocess()); } return this.$$preprocessed;