From 9a81cad2ab6c520f975c4ae0a7da8f3db5e8deeb Mon Sep 17 00:00:00 2001 From: Rintim Date: Sun, 7 Jan 2024 21:25:53 +0800 Subject: [PATCH] feat: onload mutex wait. --- noname/init/onload.js | 7 ++++-- noname/util/index.js | 1 + noname/util/mutex.js | 58 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 noname/util/mutex.js diff --git a/noname/init/onload.js b/noname/init/onload.js index 9396a9307..b359a6d06 100644 --- a/noname/init/onload.js +++ b/noname/init/onload.js @@ -9,6 +9,7 @@ import { UI as ui } from '../ui/index.js'; import { userAgent } from '../util/index.js'; import * as config from '../util/config.js'; import { gnc } from '../gnc/index.js'; +import { Mutex } from '../util/index.js'; export async function onload(resetGameTimeout) { const libOnload = lib.onload; @@ -821,15 +822,17 @@ function createTouchDraggedFilter() { /** * @async - * @param {(() => void | GeneratorFunction)[]} contents + * @param {((function(Mutex): void) | GeneratorFunction)[]} contents */ function runCustomContents(contents) { if (!Array.isArray(contents)) return + const mutex = new Mutex(); + const tasks = contents .filter((fn) => typeof fn === "function") .map((fn) => gnc.is.generatorFunc(fn) ? gnc.of(fn) : fn) // 将生成器函数转换成genCoroutin - .map((fn) => fn()) + .map((fn) => fn(mutex)) return Promise diff --git a/noname/util/index.js b/noname/util/index.js index b8a168fb1..aca4c9da2 100644 --- a/noname/util/index.js +++ b/noname/util/index.js @@ -3,6 +3,7 @@ export const assetURL = typeof nonameInitialized != 'string' || nonameInitialize export const GeneratorFunction = (function* () { }).constructor; export const AsyncFunction = (async function () { }).constructor; export const userAgent = navigator.userAgent.toLowerCase(); +export { Mutex } from './mutex.js'; // 我靠循环引用问题在这? // export * as config from './config.js' diff --git a/noname/util/mutex.js b/noname/util/mutex.js new file mode 100644 index 000000000..47b034d74 --- /dev/null +++ b/noname/util/mutex.js @@ -0,0 +1,58 @@ +/** + * + */ +export class Mutex { + /** + * @type {'locked' | 'unlocked'} + */ + #status; + + /** + * @type {null | Promise} + */ + #promise; + + /** + * @type {null | function(): void} + */ + #resolve; + + constructor() { + this.#status = 'unlocked'; + this.#promise = null; + this.#resolve = null; + } + + async lock() { + switch (this.#status) { + case 'locked': + await this.#promise; + + case 'unlocked': + this.#status = 'locked'; + // @ts-ignore + ({ promise: this.#promise, resolve: this.#resolve } = Promise.withResolvers()) + break; + } + } + + unlock() { + if (this.#status === 'unlocked') throw new Error('This Mutex is not locked.'); + + this.#status = 'unlocked'; + if (this.#resolve) this.#resolve(); + } + + /** + * + * @param {function(): void | Promise} content + */ + async scoped(content) { + try { + await this.lock(); + await content(); + } finally { + this.unlock(); + } + } +}