diff --git a/Build/build-chn-cidr.ts b/Build/build-chn-cidr.ts index e14bdf6f..476ee1bf 100644 --- a/Build/build-chn-cidr.ts +++ b/Build/build-chn-cidr.ts @@ -2,7 +2,6 @@ import { fetchRemoteTextByLine } from './lib/fetch-text-by-line'; import { resolve as pathResolve } from 'path'; import { compareAndWriteFile, withBannerArray } from './lib/create-file'; import { processLineFromReadline } from './lib/process-line'; -import { traceSync } from './lib/trace-runner'; import { task } from './trace'; import { exclude } from 'fast-cidr-tools'; @@ -21,11 +20,7 @@ const INCLUDE_CIDRS = [ export const getChnCidrPromise = createMemoizedPromise(async () => { const cidr = await processLineFromReadline(await fetchRemoteTextByLine('https://raw.githubusercontent.com/misakaio/chnroutes2/master/chnroutes.txt')); - return traceSync( - picocolors.gray('processing chnroutes2'), - () => exclude([...cidr, ...INCLUDE_CIDRS], EXCLUDE_CIDRS, true), - picocolors.gray - ); + return exclude([...cidr, ...INCLUDE_CIDRS], EXCLUDE_CIDRS, true); }); export const buildChnCidr = task(import.meta.path, async (span) => { diff --git a/Build/build-microsoft-cdn.ts b/Build/build-microsoft-cdn.ts index dff4023f..033aeb83 100644 --- a/Build/build-microsoft-cdn.ts +++ b/Build/build-microsoft-cdn.ts @@ -1,5 +1,4 @@ import path from 'path'; -import { traceAsync } from './lib/trace-runner'; import { task } from './trace'; import { createRuleset } from './lib/create-file'; import { fetchRemoteTextByLine } from './lib/fetch-text-by-line'; diff --git a/Build/download-publicsuffixlist.ts b/Build/download-publicsuffixlist.ts index 272760b6..72fbd9b2 100644 --- a/Build/download-publicsuffixlist.ts +++ b/Build/download-publicsuffixlist.ts @@ -1,18 +1,14 @@ import { TTL, fsFetchCache } from './lib/cache-filesystem'; import { defaultRequestInit, fetchWithRetry } from './lib/fetch-retry'; import { createMemoizedPromise } from './lib/memo-promise'; -import { traceAsync } from './lib/trace-runner'; -export const getPublicSuffixListTextPromise = createMemoizedPromise(() => traceAsync( - 'obtain public_suffix_list', - () => fsFetchCache.apply( - 'https://publicsuffix.org/list/public_suffix_list.dat', - () => fetchWithRetry('https://publicsuffix.org/list/public_suffix_list.dat', defaultRequestInit).then(r => r.text()), - { - // https://github.com/publicsuffix/list/blob/master/.github/workflows/tld-update.yml - // Though the action runs every 24 hours, the IANA list is updated every 7 days. - // So a 3 day TTL should be enough. - ttl: TTL.THREE_DAYS() - } - ) +export const getPublicSuffixListTextPromise = createMemoizedPromise(() => fsFetchCache.apply( + 'https://publicsuffix.org/list/public_suffix_list.dat', + () => fetchWithRetry('https://publicsuffix.org/list/public_suffix_list.dat', defaultRequestInit).then(r => r.text()), + { + // https://github.com/publicsuffix/list/blob/master/.github/workflows/tld-update.yml + // Though the action runs every 24 hours, the IANA list is updated every 7 days. + // So a 3 day TTL should be enough. + ttl: TTL.THREE_DAYS() + } )); diff --git a/Build/lib/cache-filesystem.ts b/Build/lib/cache-filesystem.ts index 8f1d566d..dcf616a6 100644 --- a/Build/lib/cache-filesystem.ts +++ b/Build/lib/cache-filesystem.ts @@ -4,7 +4,6 @@ import os from 'os'; import path from 'path'; import { mkdirSync } from 'fs'; import picocolors from 'picocolors'; -import { traceSync } from './trace-runner'; const identity = (x: any) => x; @@ -72,7 +71,13 @@ export class Cache { type: S extends string ? 'string' : 'buffer'; constructor({ - cachePath = path.join(os.tmpdir() || '/tmp', 'hdc'), tbd, tableName = 'cache', type }: CacheOptions = {}) { + cachePath = path.join(os.tmpdir() || '/tmp', 'hdc'), + tbd, + tableName = 'cache', + type + }: CacheOptions = {}) { + const start = Bun.nanoseconds(); + this.cachePath = cachePath; mkdirSync(this.cachePath, { recursive: true }); if (tbd != null) this.tbd = tbd; @@ -111,6 +116,9 @@ export class Cache { this.set('__LAST_VACUUM', dateString, 10 * 365 * 60 * 60 * 24 * 1000); this.db.exec('VACUUM;'); } + + const end = Bun.nanoseconds(); + console.log(`${picocolors.gray(`[${((end - start) / 1e6).toFixed(3)}ms]`)} cache initialized from ${this.cachePath}`); } set(key: string, value: string, ttl = 60 * 1000): void { @@ -195,7 +203,7 @@ export class Cache { } } -export const fsFetchCache = traceSync('initializing filesystem cache for fetch', () => new Cache({ cachePath: path.resolve(import.meta.dir, '../../.cache') })); +export const fsFetchCache = new Cache({ cachePath: path.resolve(import.meta.dir, '../../.cache') }); // process.on('exit', () => { // fsFetchCache.destroy(); // }); diff --git a/Build/lib/cached-tld-parse.ts b/Build/lib/cached-tld-parse.ts index 8acbf3d3..a09fa809 100644 --- a/Build/lib/cached-tld-parse.ts +++ b/Build/lib/cached-tld-parse.ts @@ -1,11 +1,9 @@ import { createCache } from './cache-apply'; import type { PublicSuffixList } from '@gorhill/publicsuffixlist'; -let gothillGetDomainCache: ReturnType | null = null; +let gorhillGetDomainCache: ReturnType | null = null; export const createCachedGorhillGetDomain = (gorhill: PublicSuffixList) => { - gothillGetDomainCache ??= createCache('cached-gorhill-get-domain', true); - return (domain: string) => { - // we do know gothillGetDomainCache exists here - return gothillGetDomainCache!.sync(domain, () => gorhill.getDomain(domain[0] === '.' ? domain.slice(1) : domain)); - }; + gorhillGetDomainCache ??= createCache('cached-gorhill-get-domain', true); + return (domain: string) => gorhillGetDomainCache! // we do know gothillGetDomainCache exists here + .sync(domain, () => gorhill.getDomain(domain[0] === '.' ? domain.slice(1) : domain)); }; diff --git a/Build/lib/clash.ts b/Build/lib/clash.ts index 3dade26d..819ecd17 100644 --- a/Build/lib/clash.ts +++ b/Build/lib/clash.ts @@ -24,15 +24,9 @@ const REQUIRE_REWRITE = { export const surgeRulesetToClashClassicalTextRuleset = (rules: string[] | Set) => { const trie = Trie.from(rules); - return CLASH_SUPPORTED_RULE_TYPE.flatMap( - type => trie.find(`${type},`) - ).concat( - Object.keys(REQUIRE_REWRITE).flatMap( - (type) => { - const found = trie.find(`${type},`); - return found.map(line => `${REQUIRE_REWRITE[type as keyof typeof REQUIRE_REWRITE]}${line.slice(type.length)}`); - } - ) + return CLASH_SUPPORTED_RULE_TYPE.flatMap(type => trie.find(`${type},`)).concat( + Object.keys(REQUIRE_REWRITE).flatMap((type) => trie.find(`${type},`) + .map(line => `${REQUIRE_REWRITE[type as keyof typeof REQUIRE_REWRITE]}${line.slice(type.length)}`)) ); }; diff --git a/Build/lib/fetch-assets.ts b/Build/lib/fetch-assets.ts index 09600c29..f1ef4aa7 100644 --- a/Build/lib/fetch-assets.ts +++ b/Build/lib/fetch-assets.ts @@ -12,20 +12,10 @@ const sleepWithAbort = (ms: number, signal: AbortSignal) => new Promise((r return; } - signal.addEventListener('abort', stop); - Bun.sleep(ms).then(done).catch(doReject); + function stop(this: AbortSignal) { reject(this.reason); } - function done() { - signal.removeEventListener('abort', stop); - resolve(); - } - function stop(this: AbortSignal) { - reject(this.reason); - } - function doReject(reason: unknown) { - signal.removeEventListener('abort', stop); - reject(reason); - } + signal.addEventListener('abort', stop, { once: true }); + Bun.sleep(ms).then(resolve).catch(reject).finally(() => signal.removeEventListener('abort', stop)); }); export async function fetchAssets(url: string, fallbackUrls: string[] | readonly string[]) { diff --git a/Build/lib/get-gorhill-publicsuffix.ts b/Build/lib/get-gorhill-publicsuffix.ts index 20f0b763..6092f652 100644 --- a/Build/lib/get-gorhill-publicsuffix.ts +++ b/Build/lib/get-gorhill-publicsuffix.ts @@ -1,11 +1,10 @@ import { toASCII } from 'punycode'; -import { traceAsync } from './trace-runner'; import { createMemoizedPromise } from './memo-promise'; import { getPublicSuffixListTextPromise } from '../download-publicsuffixlist'; const customFetch = (url: string | URL): Promise => Promise.resolve(Bun.file(url)); -export const getGorhillPublicSuffixPromise = createMemoizedPromise(() => traceAsync('create gorhill public suffix instance', async () => { +export const getGorhillPublicSuffixPromise = createMemoizedPromise(async () => { const [publicSuffixListDat, { default: gorhill }] = await Promise.all([ getPublicSuffixListTextPromise(), import('@gorhill/publicsuffixlist') @@ -15,4 +14,4 @@ export const getGorhillPublicSuffixPromise = createMemoizedPromise(() => traceAs await gorhill.enableWASM({ customFetch }); return gorhill; -})); +}); diff --git a/Build/lib/memo-promise.ts b/Build/lib/memo-promise.ts index 0c701113..5e26332a 100644 --- a/Build/lib/memo-promise.ts +++ b/Build/lib/memo-promise.ts @@ -1,9 +1,5 @@ export const createMemoizedPromise = (fn: () => Promise, preload = true): () => Promise => { - let promise: Promise | null = null; - - if (preload) { - promise = fn(); - } + let promise: Promise | null = preload ? fn() : null; return () => { promise ??= fn(); diff --git a/Build/lib/trace-runner.ts b/Build/lib/trace-runner.ts deleted file mode 100644 index d1eed852..00000000 --- a/Build/lib/trace-runner.ts +++ /dev/null @@ -1,20 +0,0 @@ -import picocolors from 'picocolors'; - -type Formatter = (result: string) => string; - -export function traceSync(prefix: string, fn: () => T, timeFormatter: Formatter = picocolors.blue): T { - const start = Bun.nanoseconds(); - const result = fn(); - const end = Bun.nanoseconds(); - console.log(`${timeFormatter(`[${((end - start) / 1e6).toFixed(3)}ms]`)} ${prefix}`); - return result; -} -// traceSync.skip = (_prefix: string, fn: () => T): T => fn(); - -export const traceAsync = async (prefix: string, fn: () => Promise, timeFormatter: Formatter = picocolors.blue): Promise => { - const start = Bun.nanoseconds(); - const result = await fn(); - const end = Bun.nanoseconds(); - console.log(`${timeFormatter(`[${((end - start) / 1e6).toFixed(3)}ms]`)} ${prefix}`); - return result; -}; diff --git a/Build/lib/trie.ts b/Build/lib/trie.ts index bec6a61f..cc669067 100644 --- a/Build/lib/trie.ts +++ b/Build/lib/trie.ts @@ -211,11 +211,11 @@ export const createTrie = (from?: string[] | Set | null) => { for (let i = suffix.length - 1; i >= 0; i--) { const token = suffix[i]; - if (node.has(token)) { - node = node.get(token)!; - } else { + if (!node.has(token)) { return false; } + + node = node.get(token)!; } return node[SENTINEL];