Fix: guard pending promise

This commit is contained in:
SukkaW 2024-10-25 02:23:51 +08:00
parent ec0ce55487
commit c24fae555a

View File

@ -35,7 +35,7 @@ export abstract class RuleOutput<TPreprocessed = unknown> {
protected otherRules: string[] = []; protected otherRules: string[] = [];
protected abstract type: 'domainset' | 'non_ip' | 'ip'; protected abstract type: 'domainset' | 'non_ip' | 'ip';
protected pendingPromise = Promise.resolve(); private pendingPromise: Promise<void> | null = null;
static readonly jsonToLines = (json: unknown): string[] => stringify(json).split('\n'); static readonly jsonToLines = (json: unknown): string[] => stringify(json).split('\n');
@ -125,7 +125,7 @@ export abstract class RuleOutput<TPreprocessed = unknown> {
} }
addFromDomainset(source: AsyncIterable<string> | Iterable<string> | string[]) { addFromDomainset(source: AsyncIterable<string> | Iterable<string> | string[]) {
this.pendingPromise = this.pendingPromise.then(() => this.addFromDomainsetPromise(source)); this.pendingPromise = (this.pendingPromise ||= Promise.resolve()).then(() => this.addFromDomainsetPromise(source));
return this; return this;
} }
@ -193,7 +193,7 @@ export abstract class RuleOutput<TPreprocessed = unknown> {
} }
addFromRuleset(source: AsyncIterable<string> | Iterable<string>) { addFromRuleset(source: AsyncIterable<string> | Iterable<string>) {
this.pendingPromise = this.pendingPromise.then(() => this.addFromRulesetPromise(source)); this.pendingPromise = (this.pendingPromise ||= Promise.resolve()).then(() => this.addFromRulesetPromise(source));
return this; return this;
} }
@ -235,13 +235,26 @@ export abstract class RuleOutput<TPreprocessed = unknown> {
protected abstract preprocess(): NonNullable<TPreprocessed>; protected abstract preprocess(): NonNullable<TPreprocessed>;
done() { async done() {
return this.pendingPromise; 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; private $$preprocessed: TPreprocessed | null = null;
get $preprocessed() { get $preprocessed() {
if (this.$$preprocessed === null) { if (this.$$preprocessed === null) {
this.guardPendingPromise();
this.$$preprocessed = this.span.traceChildSync('RuleOutput#preprocess: ' + this.id, () => this.preprocess()); this.$$preprocessed = this.span.traceChildSync('RuleOutput#preprocess: ' + this.id, () => this.preprocess());
} }
return this.$$preprocessed; return this.$$preprocessed;