chore: refactor mutex (#10816)

This commit is contained in:
jrandolf 2023-08-30 15:06:19 +02:00 committed by GitHub
parent 65188dd2e2
commit 8233f61a45
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 42 additions and 28 deletions

View File

@ -30,6 +30,7 @@ import {CDPJSHandle} from './JSHandle.js';
import {LifecycleWatcher, PuppeteerLifeCycleEvent} from './LifecycleWatcher.js'; import {LifecycleWatcher, PuppeteerLifeCycleEvent} from './LifecycleWatcher.js';
import {BindingPayload, EvaluateFunc, HandleFor} from './types.js'; import {BindingPayload, EvaluateFunc, HandleFor} from './types.js';
import { import {
Mutex,
addPageBinding, addPageBinding,
createJSHandle, createJSHandle,
debugError, debugError,
@ -222,7 +223,8 @@ export class IsolatedWorld extends Realm {
return; return;
} }
await this.#mutex.acquire(); // eslint-disable-next-line @typescript-eslint/no-unused-vars
using _ = await this.#mutex.acquire();
try { try {
await context._client.send( await context._client.send(
'Runtime.addBinding', 'Runtime.addBinding',
@ -256,8 +258,6 @@ export class IsolatedWorld extends Realm {
} }
debugError(error); debugError(error);
} finally {
this.#mutex.release();
} }
} }
@ -344,28 +344,3 @@ export class IsolatedWorld extends Realm {
this.#client.off('Runtime.bindingCalled', this.#onBindingCalled); this.#client.off('Runtime.bindingCalled', this.#onBindingCalled);
} }
} }
class Mutex {
#locked = false;
#acquirers: Array<() => void> = [];
// This is FIFO.
acquire(): Promise<void> {
if (!this.#locked) {
this.#locked = true;
return Promise.resolve();
}
const deferred = Deferred.create<void>();
this.#acquirers.push(deferred.resolve.bind(deferred));
return deferred.valueOrThrow();
}
release(): void {
const resolve = this.#acquirers.shift();
if (!resolve) {
this.#locked = false;
return;
}
resolve();
}
}

View File

@ -669,3 +669,42 @@ export function validateDialogType(
assert(dialogType, `Unknown javascript dialog type: ${type}`); assert(dialogType, `Unknown javascript dialog type: ${type}`);
return dialogType as 'alert' | 'confirm' | 'prompt' | 'beforeunload'; return dialogType as 'alert' | 'confirm' | 'prompt' | 'beforeunload';
} }
/**
* @internal
*/
export class Mutex {
static Guard = class Guard {
#mutex: Mutex;
constructor(mutex: Mutex) {
this.#mutex = mutex;
}
[Symbol.dispose](): void {
return this.#mutex.release();
}
};
#locked = false;
#acquirers: Array<() => void> = [];
// This is FIFO.
async acquire(): Promise<InstanceType<typeof Mutex.Guard>> {
if (!this.#locked) {
this.#locked = true;
return new Mutex.Guard(this);
}
const deferred = Deferred.create<void>();
this.#acquirers.push(deferred.resolve.bind(deferred));
await deferred.valueOrThrow();
return new Mutex.Guard(this);
}
release(): void {
const resolve = this.#acquirers.shift();
if (!resolve) {
this.#locked = false;
return;
}
resolve();
}
}