mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-22 05:11:20 -08:00
refactor(site): [SITE-CONSOLE-01] restore typed console and lifecycle ownership
This commit is contained in:
1 parent
6cd2d0ffbe
commit
3dba82a453
29 files changed
+1884
-36
No files matched your search
@@ -0,0 +1,107 @@
|
||||
import type { Clock, ConsoleTarget, Log, NativeMethod, Parser } from './types.ts'
|
||||
import { errorArgument } from './errors.ts'
|
||||
|
||||
interface Listener { callback?: (log: Log) => void }
|
||||
interface SavedMethod { name: string, descriptor?: PropertyDescriptor, wrapper: NativeMethod }
|
||||
interface Owner {
|
||||
listeners: Set<Listener>
|
||||
pending: Set<number>
|
||||
saved: SavedMethod[]
|
||||
feed: { pointers: Record<string, unknown>, src: { npm: string, github: string } }
|
||||
previousFeed?: PropertyDescriptor
|
||||
}
|
||||
|
||||
export function createSubscriptions(target: ConsoleTarget, methods: string[], parse: Parser, clock: Clock) {
|
||||
let owner: Owner | undefined
|
||||
|
||||
function restore(current: Owner) {
|
||||
for (const timer of current.pending)
|
||||
clock.clearTimeout(timer)
|
||||
current.pending.clear()
|
||||
for (const saved of current.saved) {
|
||||
if (target[saved.name] !== saved.wrapper)
|
||||
continue
|
||||
if (saved.descriptor)
|
||||
Object.defineProperty(target, saved.name, saved.descriptor)
|
||||
else
|
||||
delete target[saved.name]
|
||||
}
|
||||
if (target.feed === current.feed) {
|
||||
if (current.previousFeed)
|
||||
Object.defineProperty(target, 'feed', current.previousFeed)
|
||||
else
|
||||
delete target.feed
|
||||
}
|
||||
}
|
||||
|
||||
return (callback: (log: Log) => void) => {
|
||||
if (!owner) {
|
||||
const current: Owner = {
|
||||
listeners: new Set(),
|
||||
pending: new Set(),
|
||||
saved: [],
|
||||
previousFeed: Object.getOwnPropertyDescriptor(target, 'feed'),
|
||||
feed: { pointers: {}, src: { npm: 'https://npmjs.com/package/console-feed', github: 'https://github.com/samdenty99/console-feed' } },
|
||||
}
|
||||
owner = current
|
||||
try {
|
||||
for (const name of methods) {
|
||||
const original = target[name] as NativeMethod
|
||||
const wrapper: NativeMethod = function (...args) {
|
||||
Reflect.apply(original, this, args)
|
||||
const listeners = [...current.listeners]
|
||||
if (!listeners.length)
|
||||
return
|
||||
const timer = clock.setTimeout(() => {
|
||||
current.pending.delete(timer)
|
||||
const log = parse(name, name === 'error' ? args.map(errorArgument) : args)
|
||||
if (log) {
|
||||
let failed = false
|
||||
let failure: unknown
|
||||
for (const listener of listeners) {
|
||||
try {
|
||||
listener.callback?.(log)
|
||||
}
|
||||
catch (error) {
|
||||
if (!failed) {
|
||||
failed = true
|
||||
failure = error
|
||||
}
|
||||
else {
|
||||
clock.setTimeout(() => {
|
||||
throw error
|
||||
}, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (failed)
|
||||
throw failure
|
||||
}
|
||||
}, 0)
|
||||
current.pending.add(timer)
|
||||
}
|
||||
current.feed.pointers[name] = original
|
||||
current.saved.push({ name, descriptor: Object.getOwnPropertyDescriptor(target, name), wrapper })
|
||||
target[name] = wrapper
|
||||
}
|
||||
target.feed = current.feed
|
||||
}
|
||||
catch (error) {
|
||||
restore(current)
|
||||
owner = undefined
|
||||
throw error
|
||||
}
|
||||
}
|
||||
const current = owner
|
||||
const listener: Listener = { callback }
|
||||
current.listeners.add(listener)
|
||||
return () => {
|
||||
listener.callback = undefined
|
||||
current.listeners.delete(listener)
|
||||
if (!current.listeners.size && owner === current) {
|
||||
owner = undefined
|
||||
restore(current)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user