@pravosleva/reactive-engine 2.3.13-alpha → 2.3.15-alpha

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../src/core/core.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../src/core/core.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"core.method.computed.d.ts","sourceRoot":"","sources":["../../src/core/core.method.computed.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAa,MAAM,SAAS,CAAA;AAE7C,wBAAgB,cAAc,CAAC,CAAC,EAC9B,MAAM,EAAE,GAAG,EACX,EAAE,EAAE,MAAM,CAAC,EACX,UAAU,CAAC,EAAE,MAAM,GAClB,QAAQ,CAAC,CAAC,CAAC,CAwSb"}
1
+ {"version":3,"file":"core.method.computed.d.ts","sourceRoot":"","sources":["../../src/core/core.method.computed.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAa,MAAM,SAAS,CAAA;AAE7C,wBAAgB,cAAc,CAAC,CAAC,EAC9B,MAAM,EAAE,GAAG,EACX,EAAE,EAAE,MAAM,CAAC,EACX,UAAU,CAAC,EAAE,MAAM,GAClB,QAAQ,CAAC,CAAC,CAAC,CA2Tb"}
@@ -1 +1 @@
1
- {"version":3,"file":"core.method.signal.d.ts","sourceRoot":"","sources":["../../src/core/core.method.signal.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAE/C,wBAAgB,YAAY,CAAC,CAAC,EAC5B,MAAM,EAAE,GAAG,EACX,YAAY,EAAE,CAAC,EACf,aAAa,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,MAAM,GACxC,MAAM,CAAC,CAAC,CAAC,CA2HX"}
1
+ {"version":3,"file":"core.method.signal.d.ts","sourceRoot":"","sources":["../../src/core/core.method.signal.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAE/C,wBAAgB,YAAY,CAAC,CAAC,EAC5B,MAAM,EAAE,GAAG,EACX,YAAY,EAAE,CAAC,EACf,aAAa,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,MAAM,GACxC,MAAM,CAAC,CAAC,CAAC,CAiIX"}
package/dist/core.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"core.cjs","names":[],"sources":["../src/core/core.ts"],"sourcesContent":["import { getExtractedValues } from '../utils/getExtractedValues'\nimport { Signal, Computed, IEffect, EngineLoggerOptions, LogEventType, CleanupFn, TransactionContext, LogRecord, SignalOptions, ResourceOptions, ResourceState, Resource } from './types'\nimport { createComputed } from './core.method.computed'\nimport { createSignal } from './core.method.signal'\n// import { executeBatch } from './core.method.batch'\nimport { executeUntrack } from './core.method.untrack'\nimport { createReactive } from './core.method.reactive'\nimport { createEffect } from './core.method.effect'\nimport { ReactiveDebounceLogger } from './core.logger'\n\n// Тип для конструктора класса\ntype Constructor<T> = new (...args: any[]) => T\n// Тип для фабричной функции зависимостей\ntype Factory<T> = (engine: any) => T\n// Универсальный тип токена DI\ntype InjectionToken<T> = Constructor<T> | Factory<T> | symbol | string\n\nconst badgeColors: Record<LogEventType, string> = {\n signal: 'background: #007acc; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;',\n computed: 'background: #42b883; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;',\n effect: 'background: #e01e5a; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;',\n batch: 'background: #7952b3; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;',\n resource: 'background: #d97706; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;',\n reactive: 'background: #007acc; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;'\n}\nlet currentTransaction: TransactionContext | null = null\nfunction safeValueToString(value: unknown): string {\n if (value === null) return 'null'\n if (value === undefined) return 'undefined'\n if (typeof value === 'object') {\n try {\n return JSON.stringify(value)\n } catch (e) {\n return '[Cyclic Object or Layer]'\n }\n }\n return String(value)\n}\nexport function queueLog(type: LogEventType, label: string, details?: { from?: unknown; to?: unknown; payload?: unknown }): void {\n if (!currentTransaction) {\n currentTransaction = { id: Math.random().toString(36).substring(2, 9), pendingLogQueue: [], isFlushing: false }\n queueMicrotask(() => flushLogs())\n }\n currentTransaction.pendingLogQueue.push({ type, label, from: details?.from, to: details?.to, payload: details?.payload, timestamp: Date.now() })\n}\nexport function flushLogs(): void {\n if (!currentTransaction || currentTransaction.isFlushing) return\n currentTransaction.isFlushing = true\n const queue = currentTransaction.pendingLogQueue\n if (queue.length === 0) {\n currentTransaction = null\n return\n }\n console.groupCollapsed(`%cREACTIVE TRANSACTION%c [id: ${currentTransaction.id}] (${queue.length} operations)`, 'background: #7952b3; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;', 'color: #888; font-weight: normal;')\n for (const record of queue) {\n const colorStyle = badgeColors[record.type]\n const hasTransition = record.from !== undefined || record.to !== undefined\n let logMessage = `%c${record.type.toUpperCase()}%c ${record.label}`\n\n if (hasTransition) {\n if (!!record.from)\n logMessage += ` ${safeValueToString(record.from)} → ${safeValueToString(record.to)}`\n else logMessage += ` (${safeValueToString(record.to)})`\n }\n\n if (record.payload !== undefined) {\n console.groupCollapsed(logMessage, colorStyle, 'color: inherit;')\n console.log('Payload:', record.payload)\n console.groupEnd()\n } else {\n console.log(logMessage, colorStyle, 'color: inherit;')\n }\n }\n console.groupEnd()\n currentTransaction = null\n}\nexport class ReactiveEngineCore {\n protected frameworkPrefix = 'core'\n private logger: EngineLoggerOptions\n public epoch = 0\n public activeConsumer: any = null\n public batchDepth = 0\n public subscriberId = 0\n public pendingEffects: Array<Set<any> | undefined> = []\n public maxPendingDepth = 0\n public computedCache = new WeakMap<Function, any>()\n private diRegistry = new Map<unknown, unknown>()\n private diCache = new Map<unknown, unknown>()\n private proxyCache = new WeakMap<object, any>()\n private proxyTargets = new WeakSet<object>()\n private reactiveSignals = new WeakMap<object, Map<string | symbol, any>>()\n private cycleDetectionStack = new Set<unknown>()\n public batchedSignals = new Set<any>()\n public activeOwner: any = null\n // Системная очередь для отложенного батчинга деструкторов\n public pendingCleanups = new Set<() => void>()\n\n // Метод для регистрации отложенной очистки\n public queueCleanup(cleanup: () => void): void {\n this.pendingCleanups.add(cleanup)\n }\n\n constructor(options?: { logger?: EngineLoggerOptions }) {\n this.logger = options?.logger || { isEnabled: false }\n }\n\n public scheduleEffect(effect: any): void {\n const depth = effect.depth || 0\n if (!this.pendingEffects[depth]) {\n this.pendingEffects[depth] = new Set()\n }\n this.pendingEffects[depth]!.add(effect)\n if (depth > this.maxPendingDepth) {\n this.maxPendingDepth = depth\n }\n }\n\n public queueLog(type: LogEventType, label: string, details?: { from?: unknown; to?: unknown; payload?: unknown }): void {\n queueLog(type, label, details)\n }\n\n public batch<T>(fn: () => T): T {\n this.batchDepth++\n try {\n return fn()\n } finally {\n this.batchDepth--\n if (this.batchDepth === 0) {\n // ⚡ СВЕРХБЫСТРЫЙ ZERO-ALLOCATION FLUSH (O(1) Hot Path):\n // Если батч был пустым (как это часто бывает в dynamic),\n // мы мгновенно выходим, избегая создания массивов и итераторов.\n if (this.batchedSignals.size > 0) {\n // Итерируемся прямо по Set через нативный for...of,\n // убирая аллокацию временного массива Array.from()\n for (const sig of this.batchedSignals) {\n if (sig._flushBatch) sig._flushBatch()\n }\n this.batchedSignals.clear()\n }\n\n this.flushEffects()\n }\n }\n }\n\n public flushEffects(): void {\n // Если мы еще внутри батча — откладываем выполнение\n if (this.batchDepth > 0) return\n\n const prevConsumer = this.activeConsumer\n\n try {\n // Итерируемся по уровням глубины от 0 до maxPendingDepth\n for (let depth = 0; depth <= this.maxPendingDepth; depth++) {\n const bucket = this.pendingEffects[depth]\n\n // Если на текущей глубине нет запланированных эффектов, идем дальше\n if (!bucket || bucket.size === 0) continue\n\n // Извлекаем эффекты текущего уровня и сразу очищаем корзину\n const effects = Array.from(bucket)\n bucket.clear()\n\n for (const effect of effects) {\n if (effect.isDisposed) continue\n\n // Pull-валидация версий родителей перед запуском эффекта\n if (effect.dependencies && effect.dependencies.size > 0) {\n let parentChanged = false\n for (const dep of effect.dependencies) {\n const rawNode = dep._node || dep\n if (rawNode.type === 'computed' && rawNode.state > 0) {\n if (rawNode.update) rawNode.update()\n }\n if (effect.depVersions && effect.depVersions.get(dep) !== rawNode.version) {\n parentChanged = true\n }\n }\n if (!parentChanged && effect.dependencies.size > 0) {\n effect.isDirty = false\n continue\n }\n }\n\n if (!effect.isDirty) continue\n\n try {\n effect.run()\n } catch (err) {\n throw err\n }\n }\n\n // Если в процессе выполнения текущего уровня были добавлены новые эффекты\n // на этот же или более верхний уровень, сбрасываем указатель цикла,\n // чтобы гарантировать топологическую строгость.\n if (depth > 0) {\n let hasEarlierEffects = false\n for (let i = 0; i < depth; i++) {\n if (this.pendingEffects[i] && this.pendingEffects[i]!.size > 0) {\n hasEarlierEffects = true\n break\n }\n }\n if (hasEarlierEffects) {\n depth = -1 // Перезапустит цикл с 0 (учитывая depth++ в конце итерации)\n }\n }\n }\n\n // Полностью сбрасываем трекер максимальной глубины после завершения всех эффектов\n this.maxPendingDepth = 0\n\n } finally {\n this.activeConsumer = prevConsumer\n }\n }\n\n // public batch<T>(fn: () => T): T {\n // return executeBatch<T>(this, fn)\n // }\n\n private log (params: any) {\n if (!this.logger || !this.logger.isEnabled) return\n\n ReactiveDebounceLogger.processLog(this.logger, queueLog, params)\n }\n\n public signal<T>(initialValue: T, optionsOrName?: string | SignalOptions<T>): Signal<T> {\n return createSignal<T>(this, initialValue, optionsOrName)\n }\n\n public computed<T>(fn: () => T, signalName?: string): Computed<T> {\n // Просто делегируем вызов строго изолированной чистой функции\n return createComputed<T>(this, fn, signalName)\n }\n\n public effect(fn: () => void | CleanupFn, effectName?: string): () => void {\n return createEffect(this, fn, effectName)\n }\n\n public untrack<T>(fn: () => T): T {\n return executeUntrack<T>(this, fn)\n }\n\n public reactive<T extends object>(target: T, name?: string): T {\n return createReactive<T>(this, target, name)\n }\n\n public provide<T>(token: InjectionToken<T>, valueOrFactory: T | Factory<T>): void {\n this.diRegistry.set(token, valueOrFactory)\n this.diCache.delete(token)\n }\n\n public inject<T>(token: InjectionToken<T>): T {\n if (token === undefined || token === null) throw new Error('[DI Error] Token is empty')\n if (this.diCache.has(token)) return this.diCache.get(token) as T\n if (this.cycleDetectionStack.has(token)) throw new Error('[DI Error] Cyclic dependency detected')\n this.cycleDetectionStack.add(token)\n try {\n if (this.diRegistry.has(token)) {\n const entry = this.diRegistry.get(token)\n if (typeof entry === 'function') {\n if ((entry as any)._isMockFunction) {\n const mockRes = (entry as Function)(this)\n if (mockRes !== undefined) {\n this.diCache.set(token, mockRes)\n return mockRes as T\n }\n return entry as unknown as T\n }\n const str = entry.toString()\n const isClass = str.startsWith('class ') || str.startsWith('class{') || (entry.prototype && entry.prototype.constructor === entry && !str.startsWith('function') && !str.includes('=>'))\n if (!isClass) {\n const resolved = (entry as Factory<T>)(this)\n this.diCache.set(token, resolved)\n return resolved\n }\n return entry as unknown as T\n }\n return entry as T\n }\n if (typeof token === 'function') {\n const resolved = new (token as Constructor<T>)(this)\n this.diCache.set(token, resolved)\n return resolved\n }\n throw new Error('[DI Error] Token not found')\n } finally {\n this.cycleDetectionStack.delete(token)\n }\n }\n\n private delay(ms: number, signal: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal.aborted) {\n return reject(new DOMException('Aborted', 'AbortError'))\n }\n\n const timeoutId = setTimeout(() => {\n signal.removeEventListener('abort', onAbort)\n resolve()\n }, ms)\n\n const onAbort = () => {\n clearTimeout(timeoutId)\n reject(new DOMException('Aborted', 'AbortError'))\n }\n\n signal.addEventListener('abort', onAbort, { once: true })\n })\n }\n\n public resource<T, S = void>(\n fetcher: (source: S, signal: AbortSignal) => Promise<T>,\n source?: { value: S },\n optionsOrName?: string | ResourceOptions<T, S>,\n ): Resource<T> {\n const isOptionsObject = optionsOrName && typeof optionsOrName === 'object'\n const resourceSignalName = isOptionsObject\n ? ((optionsOrName as ResourceOptions<T, S>).name || 'unnamed_resource')\n : (optionsOrName as string) || 'unnamed_resource'\n\n const options: Partial<ResourceOptions<T, S>> = isOptionsObject\n ? (optionsOrName as ResourceOptions<T, S>)\n : {}\n\n const resetDataOnSourceChange = options.resetDataOnSourceChange ?? true\n const responseValidate = options.responseValidate\n const validateBeforeFetch = options.validateBeforeFetch\n const retryCount = 0\n const baseDelay = 1000\n const useExponential = true\n const maxRetryDelay = 1000 * 60 * 5\n const timeoutMs = 1000\n const state = this.signal<ResourceState<T>>(\n { data: null, loading: true, error: null, isRetrying: false },\n `[CORE_INTERNAL_SIGNAL=1]:resource:state:${resourceSignalName}`\n )\n\n const updateResourceState = (nextState: ResourceState<T>) => {\n this.log({ type: 'resource', label: resourceSignalName, details: { to: nextState, from: state.value } })\n state.value = nextState\n }\n\n const load = async (sValue: S, effectSignal: AbortSignal, isSourceChange = false) => {\n if (effectSignal.aborted) return\n const isValid = options.validateBeforeFetch ? options.validateBeforeFetch(sValue) : true\n\n /**\n * 🧐 WIP_CORE: Есть два пути, ни один не будет ошибкой, если разкомментировать код ниже. Чуть бозже добавлю опци для более тонкой отладки ядра.\n *\n * - АКТИВНО: Разделяем мирную блокировку (false) и боевую ошибку (string): работать будет идеально, но без логов, связанных с пре-валидацией\n * - НЕАКТИВНО: Более очевидное логирование процессов пре-валидации (выставление ошибок и мониторинг разработчиком)\n */\n // --\n // if (isValid === false) {\n // // Если валидатор вернул строго false — мы тихо блокируем старт фетчера,\n // // переводя ресурс в состояние ПОКОЯ (loading: false, error: null).\n // // Это полностью ликвидирует генерацию ложных ошибок при монтировании!\n // state.value = {\n // loading: false,\n // data: null,\n // error: null, // Ошибки нет! Стейт стабилен.\n // isRetrying: false\n // }\n // return\n // }\n // if (typeof isValid === 'string') {\n // // Если валидатор вернул строку — это боевая декларативная ошибка валидации формы.\n // // Здесь мы честно переводим ресурс в стейт ошибки, как и требовалось ранее.\n // state.value = {\n // loading: false,\n // data: null,\n // error: 'Core internal stopper',\n // isRetrying: false\n // }\n // return\n // }\n // --\n if (validateBeforeFetch) {\n const preValidationResult = validateBeforeFetch(sValue)\n if (preValidationResult === false || typeof preValidationResult === 'string') {\n if (effectSignal.aborted) return\n const errorMsg = typeof preValidationResult === 'string'\n ? preValidationResult\n : 'Pre-fetch validation failed for resource'\n\n const currentData = isSourceChange ? null : this.untrack(() => state.value.data)\n updateResourceState({ data: currentData, loading: false, error: errorMsg, isRetrying: false })\n return\n }\n }\n const shouldClear = isSourceChange && resetDataOnSourceChange\n const currentData = shouldClear ? null : this.untrack(() => state.value.data)\n updateResourceState({ data: currentData, loading: true, error: null, isRetrying: false })\n for (let attempt = 0; attempt <= retryCount; attempt++) {\n if (effectSignal.aborted) return\n let combinedSignal = effectSignal\n try {\n const data = await fetcher(sValue, combinedSignal)\n if (effectSignal.aborted) return\n if (combinedSignal.aborted) {\n throw new DOMException('The operation timed out.', 'TimeoutError')\n }\n if (responseValidate) {\n const validationResult = responseValidate(data)\n if (validationResult === false || typeof validationResult === 'string') {\n if (effectSignal.aborted) return\n const errorMsg = typeof validationResult === 'string' ? validationResult : 'Validation failed'\n updateResourceState({ data: null, loading: false, error: errorMsg, isRetrying: false })\n return\n }\n }\n if (effectSignal.aborted) return\n updateResourceState({ data, loading: false, error: null, isRetrying: false })\n return\n } catch (e: unknown) {\n if (effectSignal.aborted || ((e as Error).name === 'AbortError' && effectSignal.aborted)) return\n const isTimeout = (e as Error).name === 'TimeoutError' || (e as Error).name === 'AbortError' || (e as Error).message?.includes('timeout')\n const isCustomValidationError = getExtractedValues({\n tested: [(e as Error).message], expectedKey: 'THROW_CUSTOM_VALIDATION_ERROR_NO_RETRY', valueType: 'number',\n })?.[0] === '1' || false\n const __defaultCustomValidationErrorMessage = 'Custom validation error'\n let customValidationErrorMessage: string = isCustomValidationError\n ? (getExtractedValues({\n tested: [(e as Error).message], expectedKey: 'MESSAGE', valueType: 'string',\n })?.[0] || __defaultCustomValidationErrorMessage)\n : __defaultCustomValidationErrorMessage\n const isFetchBodyValidationError = isCustomValidationError || (e as Error).name === 'ValidationError'\n if (attempt === retryCount || isFetchBodyValidationError) {\n if (effectSignal.aborted) return\n const finalError = isTimeout\n ? new Error(`Request timed out after ${timeoutMs}ms`, { cause: e })\n : isCustomValidationError\n ? new Error(customValidationErrorMessage, { cause: e })\n : e\n\n updateResourceState({\n data: null, loading: false,\n error: finalError instanceof Error ? finalError.message : typeof finalError === 'string' ? finalError : `typeof finalError is ${typeof finalError}`,\n isRetrying: false,\n })\n return\n } else {\n if (effectSignal.aborted) return\n let currentDelay = useExponential ? baseDelay * Math.pow(2, attempt) : baseDelay\n currentDelay = Math.min(currentDelay, maxRetryDelay)\n const jitter = Math.random() * 200\n currentDelay = currentDelay + jitter\n updateResourceState({ data: state.value.data, loading: true, error: null, isRetrying: true })\n const logReason = isTimeout ? 'таймауту' : 'ошибке сети'\n console.warn(`[Resource Retry] \"${resourceSignalName}\" сбой по ${logReason}. Попытка ${attempt + 1}/${retryCount > 0 ? retryCount + 1 : attempt + 1}...`)\n\n try {\n await this.delay(currentDelay, effectSignal)\n if (effectSignal.aborted) return\n } catch (delayError) {\n return\n }\n }\n }\n }\n }\n\n let activeEffectController: AbortController | null = null\n\n this.effect(() => {\n const sValue = source ? source.value : undefined as S\n const effectController = new AbortController()\n activeEffectController = effectController\n\n this.untrack(() => {\n load(sValue as S, effectController.signal, true)\n })\n\n return () => effectController.abort()\n }, '[CORE_INTERNAL_SIGNAL=1]:effect')\n\n return {\n get data() { return state.value.data },\n get loading() { return state.value.loading },\n get error() { return state.value.error },\n get isRetrying() { return state.value.isRetrying },\n get value() { return state.value },\n refetch: () => {\n activeEffectController?.abort()\n activeEffectController = new AbortController()\n load(source ? source.value : undefined as S, activeEffectController.signal, false)\n },\n subscribe: (cb: (val: ResourceState<T>) => void) => state.subscribe(cb)\n }\n }\n}\n\nexport { ReactiveEngineCore as ReactiveEngine, ReactiveEngineCore as ReactiveEngineAutomatic }\n"],"mappings":"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"}
1
+ {"version":3,"file":"core.cjs","names":[],"sources":["../src/core/core.ts"],"sourcesContent":["import { getExtractedValues } from '../utils/getExtractedValues'\nimport { Signal, Computed, IEffect, EngineLoggerOptions, LogEventType, CleanupFn, TransactionContext, LogRecord, SignalOptions, ResourceOptions, ResourceState, Resource } from './types'\nimport { createComputed } from './core.method.computed'\nimport { createSignal } from './core.method.signal'\n// import { executeBatch } from './core.method.batch'\nimport { executeUntrack } from './core.method.untrack'\nimport { createReactive } from './core.method.reactive'\nimport { createEffect } from './core.method.effect'\nimport { ReactiveDebounceLogger } from './core.logger'\n\n// Тип для конструктора класса\ntype Constructor<T> = new (...args: any[]) => T\n// Тип для фабричной функции зависимостей\ntype Factory<T> = (engine: any) => T\n// Универсальный тип токена DI\ntype InjectionToken<T> = Constructor<T> | Factory<T> | symbol | string\n\nconst badgeColors: Record<LogEventType, string> = {\n signal: 'background: #007acc; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;',\n computed: 'background: #42b883; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;',\n effect: 'background: #e01e5a; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;',\n batch: 'background: #7952b3; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;',\n resource: 'background: #d97706; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;',\n reactive: 'background: #007acc; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;'\n}\nlet currentTransaction: TransactionContext | null = null\nfunction safeValueToString(value: unknown): string {\n if (value === null) return 'null'\n if (value === undefined) return 'undefined'\n if (typeof value === 'object') {\n try {\n return JSON.stringify(value)\n } catch (e) {\n return '[Cyclic Object or Layer]'\n }\n }\n return String(value)\n}\nexport function queueLog(type: LogEventType, label: string, details?: { from?: unknown; to?: unknown; payload?: unknown }): void {\n if (!currentTransaction) {\n currentTransaction = { id: Math.random().toString(36).substring(2, 9), pendingLogQueue: [], isFlushing: false }\n queueMicrotask(() => flushLogs())\n }\n currentTransaction.pendingLogQueue.push({ type, label, from: details?.from, to: details?.to, payload: details?.payload, timestamp: Date.now() })\n}\nexport function flushLogs(): void {\n if (!currentTransaction || currentTransaction.isFlushing) return\n currentTransaction.isFlushing = true\n const queue = currentTransaction.pendingLogQueue\n if (queue.length === 0) {\n currentTransaction = null\n return\n }\n console.groupCollapsed(`%cREACTIVE TRANSACTION%c [id: ${currentTransaction.id}] (${queue.length} operations)`, 'background: #7952b3; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;', 'color: #888; font-weight: normal;')\n for (const record of queue) {\n const colorStyle = badgeColors[record.type]\n const hasTransition = record.from !== undefined || record.to !== undefined\n let logMessage = `%c${record.type.toUpperCase()}%c ${record.label}`\n\n if (hasTransition) {\n if (!!record.from)\n logMessage += ` ${safeValueToString(record.from)} → ${safeValueToString(record.to)}`\n else logMessage += ` (${safeValueToString(record.to)})`\n }\n\n if (record.payload !== undefined) {\n console.groupCollapsed(logMessage, colorStyle, 'color: inherit;')\n console.log('Payload:', record.payload)\n console.groupEnd()\n } else {\n console.log(logMessage, colorStyle, 'color: inherit;')\n }\n }\n console.groupEnd()\n currentTransaction = null\n}\nexport class ReactiveEngineCore {\n protected frameworkPrefix = 'core'\n private logger: EngineLoggerOptions\n public epoch = 0\n public activeConsumer: any = null\n public batchDepth = 0\n public subscriberId = 0\n public pendingEffects: Array<Set<any> | undefined> = []\n public maxPendingDepth = 0\n public computedCache = new WeakMap<Function, any>()\n private diRegistry = new Map<unknown, unknown>()\n private diCache = new Map<unknown, unknown>()\n private proxyCache = new WeakMap<object, any>()\n private proxyTargets = new WeakSet<object>()\n private reactiveSignals = new WeakMap<object, Map<string | symbol, any>>()\n private cycleDetectionStack = new Set<unknown>()\n public batchedSignals = new Set<any>()\n public activeOwner: any = null\n // Системная очередь для отложенного батчинга деструкторов\n public pendingCleanups = new Set<() => void>()\n\n // Метод для регистрации отложенной очистки\n public queueCleanup(cleanup: () => void): void {\n this.pendingCleanups.add(cleanup)\n }\n\n constructor(options?: { logger?: EngineLoggerOptions }) {\n this.logger = options?.logger || { isEnabled: false }\n }\n\n public scheduleEffect(effect: any): void {\n const depth = effect.depth || 0\n if (!this.pendingEffects[depth]) {\n this.pendingEffects[depth] = new Set()\n }\n this.pendingEffects[depth]!.add(effect)\n if (depth > this.maxPendingDepth) {\n this.maxPendingDepth = depth\n }\n }\n\n public queueLog(type: LogEventType, label: string, details?: { from?: unknown; to?: unknown; payload?: unknown }): void {\n queueLog(type, label, details)\n }\n\n public batch<T>(fn: () => T): T {\n this.batchDepth++\n try {\n return fn()\n } finally {\n this.batchDepth--\n if (this.batchDepth === 0) {\n // ⚡ СВЕРХБЫСТРЫЙ ZERO-ALLOCATION FLUSH (O(1) Hot Path):\n // Если батч был пустым (как это часто бывает в dynamic),\n // мы мгновенно выходим, избегая создания массивов и итераторов.\n if (this.batchedSignals.size > 0) {\n // Итерируемся прямо по Set через нативный for...of,\n // убирая аллокацию временного массива Array.from()\n for (const sig of this.batchedSignals) {\n if (sig._flushBatch) sig._flushBatch()\n }\n this.batchedSignals.clear()\n }\n\n this.flushEffects()\n }\n }\n }\n\n public flushEffects(): void {\n // Если мы еще внутри батча — откладываем выполнение\n if (this.batchDepth > 0) return\n\n const prevConsumer = this.activeConsumer\n\n try {\n // Итерируемся по уровням глубины от 0 до maxPendingDepth\n for (let depth = 0; depth <= this.maxPendingDepth; depth++) {\n const bucket = this.pendingEffects[depth]\n\n // Если на текущей глубине нет запланированных эффектов, идем дальше\n if (!bucket || bucket.size === 0) continue\n\n // Извлекаем эффекты текущего уровня и сразу очищаем корзину\n const effects = Array.from(bucket)\n bucket.clear()\n\n for (const effect of effects) {\n if (effect.isDisposed) continue\n\n // Pull-валидация версий родителей перед запуском эффекта\n if (effect.dependencies && effect.dependencies.size > 0) {\n let parentChanged = false\n\n for (const dep of effect.dependencies) {\n const rawNode = dep._node || dep\n\n // ⚡ ВОЗВРАЩАЕМ ПРОВЕРКУ РОДИТЕЛЕЙ (С математической точностью):\n // Если родитель является computed-свойством и он \"загрязнен\" (state > 0),\n // форсируем его апдейт. Благодаря маркеруverifiedInEpoch, этот вызов\n // отработает за мгновенное O(1), если узел уже актуализировался в этой эпохе.\n if (rawNode.type === 'computed' && rawNode.state > 0) {\n if (rawNode.update) rawNode.update()\n }\n\n if (effect.depVersions && effect.depVersions.get(dep) !== rawNode.version) {\n parentChanged = true\n }\n }\n\n if (!parentChanged && effect.dependencies.size > 0) {\n effect.isDirty = false\n continue\n }\n }\n\n if (!effect.isDirty) continue\n\n try {\n effect.run()\n } catch (err) {\n throw err\n }\n }\n\n // Если в процессе выполнения текущего уровня были добавлены новые эффекты\n // на этот же или более верхний уровень, сбрасываем указатель цикла.\n if (depth > 0) {\n let hasEarlierEffects = false\n for (let i = 0; i < depth; i++) {\n if (this.pendingEffects[i] && this.pendingEffects[i]!.size > 0) {\n hasEarlierEffects = true\n break\n }\n }\n if (hasEarlierEffects) {\n depth = -1 // Перезапустит цикл с 0\n }\n }\n }\n\n // Полностью сбрасываем трекер максимальной глубины после завершения всех эффектов\n this.maxPendingDepth = 0\n\n } finally {\n this.activeConsumer = prevConsumer\n }\n }\n\n // public batch<T>(fn: () => T): T {\n // return executeBatch<T>(this, fn)\n // }\n\n private log (params: any) {\n if (!this.logger || !this.logger.isEnabled) return\n\n ReactiveDebounceLogger.processLog(this.logger, queueLog, params)\n }\n\n public signal<T>(initialValue: T, optionsOrName?: string | SignalOptions<T>): Signal<T> {\n return createSignal<T>(this, initialValue, optionsOrName)\n }\n\n public computed<T>(fn: () => T, signalName?: string): Computed<T> {\n // Просто делегируем вызов строго изолированной чистой функции\n return createComputed<T>(this, fn, signalName)\n }\n\n public effect(fn: () => void | CleanupFn, effectName?: string): () => void {\n return createEffect(this, fn, effectName)\n }\n\n public untrack<T>(fn: () => T): T {\n return executeUntrack<T>(this, fn)\n }\n\n public reactive<T extends object>(target: T, name?: string): T {\n return createReactive<T>(this, target, name)\n }\n\n public provide<T>(token: InjectionToken<T>, valueOrFactory: T | Factory<T>): void {\n this.diRegistry.set(token, valueOrFactory)\n this.diCache.delete(token)\n }\n\n public inject<T>(token: InjectionToken<T>): T {\n if (token === undefined || token === null) throw new Error('[DI Error] Token is empty')\n if (this.diCache.has(token)) return this.diCache.get(token) as T\n if (this.cycleDetectionStack.has(token)) throw new Error('[DI Error] Cyclic dependency detected')\n this.cycleDetectionStack.add(token)\n try {\n if (this.diRegistry.has(token)) {\n const entry = this.diRegistry.get(token)\n if (typeof entry === 'function') {\n if ((entry as any)._isMockFunction) {\n const mockRes = (entry as Function)(this)\n if (mockRes !== undefined) {\n this.diCache.set(token, mockRes)\n return mockRes as T\n }\n return entry as unknown as T\n }\n const str = entry.toString()\n const isClass = str.startsWith('class ') || str.startsWith('class{') || (entry.prototype && entry.prototype.constructor === entry && !str.startsWith('function') && !str.includes('=>'))\n if (!isClass) {\n const resolved = (entry as Factory<T>)(this)\n this.diCache.set(token, resolved)\n return resolved\n }\n return entry as unknown as T\n }\n return entry as T\n }\n if (typeof token === 'function') {\n const resolved = new (token as Constructor<T>)(this)\n this.diCache.set(token, resolved)\n return resolved\n }\n throw new Error('[DI Error] Token not found')\n } finally {\n this.cycleDetectionStack.delete(token)\n }\n }\n\n private delay(ms: number, signal: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal.aborted) {\n return reject(new DOMException('Aborted', 'AbortError'))\n }\n\n const timeoutId = setTimeout(() => {\n signal.removeEventListener('abort', onAbort)\n resolve()\n }, ms)\n\n const onAbort = () => {\n clearTimeout(timeoutId)\n reject(new DOMException('Aborted', 'AbortError'))\n }\n\n signal.addEventListener('abort', onAbort, { once: true })\n })\n }\n\n public resource<T, S = void>(\n fetcher: (source: S, signal: AbortSignal) => Promise<T>,\n source?: { value: S },\n optionsOrName?: string | ResourceOptions<T, S>,\n ): Resource<T> {\n const isOptionsObject = optionsOrName && typeof optionsOrName === 'object'\n const resourceSignalName = isOptionsObject\n ? ((optionsOrName as ResourceOptions<T, S>).name || 'unnamed_resource')\n : (optionsOrName as string) || 'unnamed_resource'\n\n const options: Partial<ResourceOptions<T, S>> = isOptionsObject\n ? (optionsOrName as ResourceOptions<T, S>)\n : {}\n\n const resetDataOnSourceChange = options.resetDataOnSourceChange ?? true\n const responseValidate = options.responseValidate\n const validateBeforeFetch = options.validateBeforeFetch\n const retryCount = 0\n const baseDelay = 1000\n const useExponential = true\n const maxRetryDelay = 1000 * 60 * 5\n const timeoutMs = 1000\n const state = this.signal<ResourceState<T>>(\n { data: null, loading: true, error: null, isRetrying: false },\n `[CORE_INTERNAL_SIGNAL=1]:resource:state:${resourceSignalName}`\n )\n\n const updateResourceState = (nextState: ResourceState<T>) => {\n this.log({ type: 'resource', label: resourceSignalName, details: { to: nextState, from: state.value } })\n state.value = nextState\n }\n\n const load = async (sValue: S, effectSignal: AbortSignal, isSourceChange = false) => {\n if (effectSignal.aborted) return\n const isValid = options.validateBeforeFetch ? options.validateBeforeFetch(sValue) : true\n\n /**\n * 🧐 WIP_CORE: Есть два пути, ни один не будет ошибкой, если разкомментировать код ниже. Чуть бозже добавлю опци для более тонкой отладки ядра.\n *\n * - АКТИВНО: Разделяем мирную блокировку (false) и боевую ошибку (string): работать будет идеально, но без логов, связанных с пре-валидацией\n * - НЕАКТИВНО: Более очевидное логирование процессов пре-валидации (выставление ошибок и мониторинг разработчиком)\n */\n // --\n // if (isValid === false) {\n // // Если валидатор вернул строго false — мы тихо блокируем старт фетчера,\n // // переводя ресурс в состояние ПОКОЯ (loading: false, error: null).\n // // Это полностью ликвидирует генерацию ложных ошибок при монтировании!\n // state.value = {\n // loading: false,\n // data: null,\n // error: null, // Ошибки нет! Стейт стабилен.\n // isRetrying: false\n // }\n // return\n // }\n // if (typeof isValid === 'string') {\n // // Если валидатор вернул строку — это боевая декларативная ошибка валидации формы.\n // // Здесь мы честно переводим ресурс в стейт ошибки, как и требовалось ранее.\n // state.value = {\n // loading: false,\n // data: null,\n // error: 'Core internal stopper',\n // isRetrying: false\n // }\n // return\n // }\n // --\n if (validateBeforeFetch) {\n const preValidationResult = validateBeforeFetch(sValue)\n if (preValidationResult === false || typeof preValidationResult === 'string') {\n if (effectSignal.aborted) return\n const errorMsg = typeof preValidationResult === 'string'\n ? preValidationResult\n : 'Pre-fetch validation failed for resource'\n\n const currentData = isSourceChange ? null : this.untrack(() => state.value.data)\n updateResourceState({ data: currentData, loading: false, error: errorMsg, isRetrying: false })\n return\n }\n }\n const shouldClear = isSourceChange && resetDataOnSourceChange\n const currentData = shouldClear ? null : this.untrack(() => state.value.data)\n updateResourceState({ data: currentData, loading: true, error: null, isRetrying: false })\n for (let attempt = 0; attempt <= retryCount; attempt++) {\n if (effectSignal.aborted) return\n let combinedSignal = effectSignal\n try {\n const data = await fetcher(sValue, combinedSignal)\n if (effectSignal.aborted) return\n if (combinedSignal.aborted) {\n throw new DOMException('The operation timed out.', 'TimeoutError')\n }\n if (responseValidate) {\n const validationResult = responseValidate(data)\n if (validationResult === false || typeof validationResult === 'string') {\n if (effectSignal.aborted) return\n const errorMsg = typeof validationResult === 'string' ? validationResult : 'Validation failed'\n updateResourceState({ data: null, loading: false, error: errorMsg, isRetrying: false })\n return\n }\n }\n if (effectSignal.aborted) return\n updateResourceState({ data, loading: false, error: null, isRetrying: false })\n return\n } catch (e: unknown) {\n if (effectSignal.aborted || ((e as Error).name === 'AbortError' && effectSignal.aborted)) return\n const isTimeout = (e as Error).name === 'TimeoutError' || (e as Error).name === 'AbortError' || (e as Error).message?.includes('timeout')\n const isCustomValidationError = getExtractedValues({\n tested: [(e as Error).message], expectedKey: 'THROW_CUSTOM_VALIDATION_ERROR_NO_RETRY', valueType: 'number',\n })?.[0] === '1' || false\n const __defaultCustomValidationErrorMessage = 'Custom validation error'\n let customValidationErrorMessage: string = isCustomValidationError\n ? (getExtractedValues({\n tested: [(e as Error).message], expectedKey: 'MESSAGE', valueType: 'string',\n })?.[0] || __defaultCustomValidationErrorMessage)\n : __defaultCustomValidationErrorMessage\n const isFetchBodyValidationError = isCustomValidationError || (e as Error).name === 'ValidationError'\n if (attempt === retryCount || isFetchBodyValidationError) {\n if (effectSignal.aborted) return\n const finalError = isTimeout\n ? new Error(`Request timed out after ${timeoutMs}ms`, { cause: e })\n : isCustomValidationError\n ? new Error(customValidationErrorMessage, { cause: e })\n : e\n\n updateResourceState({\n data: null, loading: false,\n error: finalError instanceof Error ? finalError.message : typeof finalError === 'string' ? finalError : `typeof finalError is ${typeof finalError}`,\n isRetrying: false,\n })\n return\n } else {\n if (effectSignal.aborted) return\n let currentDelay = useExponential ? baseDelay * Math.pow(2, attempt) : baseDelay\n currentDelay = Math.min(currentDelay, maxRetryDelay)\n const jitter = Math.random() * 200\n currentDelay = currentDelay + jitter\n updateResourceState({ data: state.value.data, loading: true, error: null, isRetrying: true })\n const logReason = isTimeout ? 'таймауту' : 'ошибке сети'\n console.warn(`[Resource Retry] \"${resourceSignalName}\" сбой по ${logReason}. Попытка ${attempt + 1}/${retryCount > 0 ? retryCount + 1 : attempt + 1}...`)\n\n try {\n await this.delay(currentDelay, effectSignal)\n if (effectSignal.aborted) return\n } catch (delayError) {\n return\n }\n }\n }\n }\n }\n\n let activeEffectController: AbortController | null = null\n\n this.effect(() => {\n const sValue = source ? source.value : undefined as S\n const effectController = new AbortController()\n activeEffectController = effectController\n\n this.untrack(() => {\n load(sValue as S, effectController.signal, true)\n })\n\n return () => effectController.abort()\n }, '[CORE_INTERNAL_SIGNAL=1]:effect')\n\n return {\n get data() { return state.value.data },\n get loading() { return state.value.loading },\n get error() { return state.value.error },\n get isRetrying() { return state.value.isRetrying },\n get value() { return state.value },\n refetch: () => {\n activeEffectController?.abort()\n activeEffectController = new AbortController()\n load(source ? source.value : undefined as S, activeEffectController.signal, false)\n },\n subscribe: (cb: (val: ResourceState<T>) => void) => state.subscribe(cb)\n }\n }\n}\n\nexport { ReactiveEngineCore as ReactiveEngine, ReactiveEngineCore as ReactiveEngineAutomatic }\n"],"mappings":"oRAiBA,IAAM,EAA4C,CAChD,OAAQ,6FACR,SAAU,6FACV,OAAQ,6FACR,MAAO,6FACP,SAAU,6FACV,SAAU,4FACZ,EACI,EAAgD,KACpD,SAAS,EAAkB,EAAwB,CACjD,GAAI,IAAU,KAAM,MAAO,OAC3B,GAAI,IAAU,IAAA,GAAW,MAAO,YAChC,GAAI,OAAO,GAAU,SACnB,GAAI,CACF,OAAO,KAAK,UAAU,CAAK,CAC7B,MAAY,CACV,MAAO,0BACT,CAEF,OAAO,OAAO,CAAK,CACrB,CACA,SAAgB,EAAS,EAAoB,EAAe,EAAqE,CAC1H,IACH,EAAqB,CAAE,GAAI,KAAK,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,UAAU,EAAG,CAAC,EAAG,gBAAiB,CAAC,EAAG,WAAY,EAAM,EAC9G,mBAAqB,EAAU,CAAC,GAElC,EAAmB,gBAAgB,KAAK,CAAE,OAAM,QAAO,KAAM,GAAS,KAAM,GAAI,GAAS,GAAI,QAAS,GAAS,QAAS,UAAW,KAAK,IAAI,CAAE,CAAC,CACjJ,CACA,SAAgB,GAAkB,CAChC,GAAI,CAAC,GAAsB,EAAmB,WAAY,OAC1D,EAAmB,WAAa,GAChC,IAAM,EAAQ,EAAmB,gBACjC,GAAI,EAAM,SAAW,EAAG,CACtB,EAAqB,KACrB,MACF,CACA,QAAQ,eAAe,iCAAiC,EAAmB,GAAG,KAAK,EAAM,OAAO,cAAe,6FAA8F,mCAAmC,EAChP,IAAK,IAAM,KAAU,EAAO,CAC1B,IAAM,EAAa,EAAY,EAAO,MAChC,EAAgB,EAAO,OAAS,IAAA,IAAa,EAAO,KAAO,IAAA,GAC7D,EAAa,KAAK,EAAO,KAAK,YAAY,EAAE,KAAK,EAAO,QAExD,IACI,EAAO,KACX,GAAc,IAAI,EAAkB,EAAO,IAAI,EAAE,KAAK,EAAkB,EAAO,EAAE,IAC9E,GAAc,KAAK,EAAkB,EAAO,EAAE,EAAE,IAGnD,EAAO,UAAY,IAAA,GAKrB,QAAQ,IAAI,EAAY,EAAY,iBAAiB,GAJrD,QAAQ,eAAe,EAAY,EAAY,iBAAiB,EAChE,QAAQ,IAAI,WAAY,EAAO,OAAO,EACtC,QAAQ,SAAS,EAIrB,CACA,QAAQ,SAAS,EACjB,EAAqB,IACvB,CACA,IAAa,EAAb,KAAgC,CAC9B,gBAA4B,OAC5B,OACA,MAAe,EACf,eAA6B,KAC7B,WAAoB,EACpB,aAAsB,EACtB,eAAqD,CAAC,EACtD,gBAAyB,EACzB,cAAuB,IAAI,QAC3B,WAAqB,IAAI,IACzB,QAAkB,IAAI,IACtB,WAAqB,IAAI,QACzB,aAAuB,IAAI,QAC3B,gBAA0B,IAAI,QAC9B,oBAA8B,IAAI,IAClC,eAAwB,IAAI,IAC5B,YAA0B,KAE1B,gBAAyB,IAAI,IAG7B,aAAoB,EAA2B,CAC7C,KAAK,gBAAgB,IAAI,CAAO,CAClC,CAEA,YAAY,EAA4C,CACtD,KAAK,OAAS,GAAS,QAAU,CAAE,UAAW,EAAM,CACtD,CAEA,eAAsB,EAAmB,CACvC,IAAM,EAAQ,EAAO,OAAS,EACzB,KAAK,eAAe,KACvB,KAAK,eAAe,GAAS,IAAI,KAEnC,KAAK,eAAe,EAAM,CAAE,IAAI,CAAM,EAClC,EAAQ,KAAK,kBACf,KAAK,gBAAkB,EAE3B,CAEA,SAAgB,EAAoB,EAAe,EAAqE,CACtH,EAAS,EAAM,EAAO,CAAO,CAC/B,CAEA,MAAgB,EAAgB,CAC9B,KAAK,aACL,GAAI,CACF,OAAO,EAAG,CACZ,QAAU,CAER,GADA,KAAK,aACD,KAAK,aAAe,EAAG,CAIzB,GAAI,KAAK,eAAe,KAAO,EAAG,CAGhC,IAAK,IAAM,KAAO,KAAK,eACjB,EAAI,aAAa,EAAI,YAAY,EAEvC,KAAK,eAAe,MAAM,CAC5B,CAEA,KAAK,aAAa,CACpB,CACF,CACF,CAEA,cAA4B,CAE1B,GAAI,KAAK,WAAa,EAAG,OAEzB,IAAM,EAAe,KAAK,eAE1B,GAAI,CAEF,IAAK,IAAI,EAAQ,EAAG,GAAS,KAAK,gBAAiB,IAAS,CAC1D,IAAM,EAAS,KAAK,eAAe,GAGnC,GAAI,CAAC,GAAU,EAAO,OAAS,EAAG,SAGlC,IAAM,EAAU,MAAM,KAAK,CAAM,EACjC,EAAO,MAAM,EAEb,IAAK,IAAM,KAAU,EACf,MAAO,WAGX,IAAI,EAAO,cAAgB,EAAO,aAAa,KAAO,EAAG,CACvD,IAAI,EAAgB,GAEpB,IAAK,IAAM,KAAO,EAAO,aAAc,CACrC,IAAM,EAAU,EAAI,OAAS,EAMzB,EAAQ,OAAS,YAAc,EAAQ,MAAQ,GAC7C,EAAQ,QAAQ,EAAQ,OAAO,EAGjC,EAAO,aAAe,EAAO,YAAY,IAAI,CAAG,IAAM,EAAQ,UAChE,EAAgB,GAEpB,CAEA,GAAI,CAAC,GAAiB,EAAO,aAAa,KAAO,EAAG,CAClD,EAAO,QAAU,GACjB,QACF,CACF,CAEK,KAAO,QAEZ,GAAI,CACF,EAAO,IAAI,CACb,OAAS,EAAK,CACZ,MAAM,CACR,CARA,CAaF,GAAI,EAAQ,EAAG,CACb,IAAI,EAAoB,GACxB,IAAK,IAAI,EAAI,EAAG,EAAI,EAAO,IACzB,GAAI,KAAK,eAAe,IAAM,KAAK,eAAe,EAAE,CAAE,KAAO,EAAG,CAC9D,EAAoB,GACpB,KACF,CAEE,IACF,EAAQ,GAEZ,CACF,CAGA,KAAK,gBAAkB,CAEzB,QAAU,CACR,KAAK,eAAiB,CACxB,CACF,CAMA,IAAa,EAAa,CACpB,CAAC,KAAK,QAAU,CAAC,KAAK,OAAO,WAEjC,EAAA,uBAAuB,WAAW,KAAK,OAAQ,EAAU,CAAM,CACjE,CAEA,OAAiB,EAAiB,EAAsD,CACtF,OAAO,EAAA,aAAgB,KAAM,EAAc,CAAa,CAC1D,CAEA,SAAmB,EAAa,EAAkC,CAEhE,OAAO,EAAA,eAAkB,KAAM,EAAI,CAAU,CAC/C,CAEA,OAAc,EAA4B,EAAiC,CACzE,OAAO,EAAA,aAAa,KAAM,EAAI,CAAU,CAC1C,CAEA,QAAkB,EAAgB,CAChC,OAAO,EAAA,eAAkB,KAAM,CAAE,CACnC,CAEA,SAAkC,EAAW,EAAkB,CAC7D,OAAO,EAAA,eAAkB,KAAM,EAAQ,CAAI,CAC7C,CAEA,QAAkB,EAA0B,EAAsC,CAChF,KAAK,WAAW,IAAI,EAAO,CAAc,EACzC,KAAK,QAAQ,OAAO,CAAK,CAC3B,CAEA,OAAiB,EAA6B,CAC5C,GAAI,GAAiC,KAAM,MAAU,MAAM,2BAA2B,EACtF,GAAI,KAAK,QAAQ,IAAI,CAAK,EAAG,OAAO,KAAK,QAAQ,IAAI,CAAK,EAC1D,GAAI,KAAK,oBAAoB,IAAI,CAAK,EAAG,MAAU,MAAM,uCAAuC,EAChG,KAAK,oBAAoB,IAAI,CAAK,EAClC,GAAI,CACF,GAAI,KAAK,WAAW,IAAI,CAAK,EAAG,CAC9B,IAAM,EAAQ,KAAK,WAAW,IAAI,CAAK,EACvC,GAAI,OAAO,GAAU,WAAY,CAC/B,GAAK,EAAc,gBAAiB,CAClC,IAAM,EAAW,EAAmB,IAAI,EAKxC,OAJI,IAAY,IAAA,GAIT,GAHL,KAAK,QAAQ,IAAI,EAAO,CAAO,EACxB,EAGX,CACA,IAAM,EAAM,EAAM,SAAS,EAE3B,GAAI,EADY,EAAI,WAAW,QAAQ,GAAK,EAAI,WAAW,QAAQ,GAAM,EAAM,WAAa,EAAM,UAAU,cAAgB,GAAS,CAAC,EAAI,WAAW,UAAU,GAAK,CAAC,EAAI,SAAS,IAAI,GACxK,CACZ,IAAM,EAAY,EAAqB,IAAI,EAE3C,OADA,KAAK,QAAQ,IAAI,EAAO,CAAQ,EACzB,CACT,CACA,OAAO,CACT,CACA,OAAO,CACT,CACA,GAAI,OAAO,GAAU,WAAY,CAC/B,IAAM,EAAW,IAAK,EAAyB,IAAI,EAEnD,OADA,KAAK,QAAQ,IAAI,EAAO,CAAQ,EACzB,CACT,CACA,MAAU,MAAM,4BAA4B,CAC9C,QAAU,CACR,KAAK,oBAAoB,OAAO,CAAK,CACvC,CACF,CAEA,MAAc,EAAY,EAAoC,CAC5D,OAAO,IAAI,SAAS,EAAS,IAAW,CACtC,GAAI,EAAO,QACT,OAAO,EAAO,IAAI,aAAa,UAAW,YAAY,CAAC,EAGzD,IAAM,EAAY,eAAiB,CACjC,EAAO,oBAAoB,QAAS,CAAO,EAC3C,EAAQ,CACV,EAAG,CAAE,EAEC,MAAgB,CACpB,aAAa,CAAS,EACtB,EAAO,IAAI,aAAa,UAAW,YAAY,CAAC,CAClD,EAEA,EAAO,iBAAiB,QAAS,EAAS,CAAE,KAAM,EAAK,CAAC,CAC1D,CAAC,CACH,CAEA,SACE,EACA,EACA,EACa,CACb,IAAM,EAAkB,GAAiB,OAAO,GAAkB,SAC5D,EAAqB,EACrB,EAAwC,MAAQ,mBACjD,GAA4B,mBAE3B,EAA0C,EAC3C,EACD,CAAC,EAEC,EAA0B,EAAQ,yBAA2B,GAC7D,EAAmB,EAAQ,iBAC3B,EAAsB,EAAQ,oBAM9B,EAAQ,KAAK,OACjB,CAAE,KAAM,KAAM,QAAS,GAAM,MAAO,KAAM,WAAY,EAAM,EAC5D,2CAA2C,GAC7C,EAEM,EAAuB,GAAgC,CAC3D,KAAK,IAAI,CAAE,KAAM,WAAY,MAAO,EAAoB,QAAS,CAAE,GAAI,EAAW,KAAM,EAAM,KAAM,CAAE,CAAC,EACvG,EAAM,MAAQ,CAChB,EAEM,EAAO,MAAO,EAAW,EAA2B,EAAiB,KAAU,CACnF,GAAI,EAAa,QAAS,OAkC1B,GAjCgB,EAAQ,qBAAsB,EAAQ,oBAAoB,CAAM,EAiC5E,EAAqB,CACvB,IAAM,EAAsB,EAAoB,CAAM,EACtD,GAAI,IAAwB,IAAS,OAAO,GAAwB,SAAU,CAC5E,GAAI,EAAa,QAAS,OAC1B,IAAM,EAAW,OAAO,GAAwB,SAC5C,EACA,2CAEE,EAAc,EAAiB,KAAO,KAAK,YAAc,EAAM,MAAM,IAAI,EAC/E,EAAoB,CAAE,KAAM,EAAa,QAAS,GAAO,MAAO,EAAU,WAAY,EAAM,CAAC,EAC7F,MACF,CACF,CAEA,IAAM,EADc,GAAkB,EACJ,KAAO,KAAK,YAAc,EAAM,MAAM,IAAI,EAC5E,EAAoB,CAAE,KAAM,EAAa,QAAS,GAAM,MAAO,KAAM,WAAY,EAAM,CAAC,EACxF,IAAK,IAAI,EAAU,EAAG,GAAW,EAAY,IAAW,CACtD,GAAI,EAAa,QAAS,OAC1B,IAAI,EAAiB,EACrB,GAAI,CACF,IAAM,EAAO,MAAM,EAAQ,EAAQ,CAAc,EACjD,GAAI,EAAa,QAAS,OAC1B,GAAI,EAAe,QACjB,MAAM,IAAI,aAAa,2BAA4B,cAAc,EAEnE,GAAI,EAAkB,CACpB,IAAM,EAAmB,EAAiB,CAAI,EAC9C,GAAI,IAAqB,IAAS,OAAO,GAAqB,SAAU,CACtE,GAAI,EAAa,QAAS,OAE1B,EAAoB,CAAE,KAAM,KAAM,QAAS,GAAO,MADjC,OAAO,GAAqB,SAAW,EAAmB,oBACR,WAAY,EAAM,CAAC,EACtF,MACF,CACF,CACA,GAAI,EAAa,QAAS,OAC1B,EAAoB,CAAE,OAAM,QAAS,GAAO,MAAO,KAAM,WAAY,EAAM,CAAC,EAC5E,MACF,OAAS,EAAY,CACnB,GAAI,EAAa,SAAa,EAAY,OAAS,cAAgB,EAAa,QAAU,OAC1F,IAAM,EAAa,EAAY,OAAS,gBAAmB,EAAY,OAAS,cAAiB,EAAY,SAAS,SAAS,SAAS,EAClI,EAA0B,EAAA,mBAAmB,CACjD,OAAQ,CAAE,EAAY,OAAO,EAAG,YAAa,yCAA0C,UAAW,QACpG,CAAC,CAAC,GAAG,KAAO,KAAO,GAEf,EAAuC,GACtC,EAAA,mBAAmB,CACpB,OAAQ,CAAE,EAAY,OAAO,EAAG,YAAa,UAAW,UAAW,QACrE,CAAC,CAAC,GAAG,IACH,0BACE,EAA6B,GAA4B,EAAY,OAAS,kBACpF,GAAI,IAAY,GAAc,EAA4B,CACxD,GAAI,EAAa,QAAS,OAC1B,IAAM,EAAa,EACX,MAAM,iCAA0C,CAAE,MAAO,CAAE,CAAC,EAChE,EACM,MAAM,EAA8B,CAAE,MAAO,CAAE,CAAC,EACpD,EAEN,EAAoB,CAClB,KAAM,KAAM,QAAS,GACrB,MAAO,aAAsB,MAAQ,EAAW,QAAU,OAAO,GAAe,SAAW,EAAa,wBAAwB,OAAO,IACvI,WAAY,EACd,CAAC,EACD,MACF,KAAO,CACL,GAAI,EAAa,QAAS,OAC1B,IAAI,EAAgC,IAAqB,GAAG,EAC5D,EAAe,KAAK,IAAI,EAAc,GAAa,EACnD,IAAM,EAAS,KAAK,OAAO,EAAI,IAC/B,GAA8B,EAC9B,EAAoB,CAAE,KAAM,EAAM,MAAM,KAAM,QAAS,GAAM,MAAO,KAAM,WAAY,EAAK,CAAC,EAE5F,QAAQ,KAAK,qBAAqB,EAAmB,YADnC,EAAY,WAAa,cACgC,YAAY,EAAU,EAAE,GAAqC,EAAU,EAAE,IAAI,EAExJ,GAAI,CAEF,GADA,MAAM,KAAK,MAAM,EAAc,CAAY,EACvC,EAAa,QAAS,MAC5B,MAAqB,CACnB,MACF,CACF,CACF,CACF,CACF,EAEI,EAAiD,KAcrD,OAZA,KAAK,WAAa,CAChB,IAAM,EAAS,EAAS,EAAO,MAAQ,IAAA,GACjC,EAAmB,IAAI,gBAO7B,MANA,GAAyB,EAEzB,KAAK,YAAc,CACjB,EAAK,EAAa,EAAiB,OAAQ,EAAI,CACjD,CAAC,MAEY,EAAiB,MAAM,CACtC,EAAG,iCAAiC,EAE7B,CACL,IAAI,MAAO,CAAE,OAAO,EAAM,MAAM,IAAK,EACrC,IAAI,SAAU,CAAE,OAAO,EAAM,MAAM,OAAQ,EAC3C,IAAI,OAAQ,CAAE,OAAO,EAAM,MAAM,KAAM,EACvC,IAAI,YAAa,CAAE,OAAO,EAAM,MAAM,UAAW,EACjD,IAAI,OAAQ,CAAE,OAAO,EAAM,KAAM,EACjC,YAAe,CACb,GAAwB,MAAM,EAC9B,EAAyB,IAAI,gBAC7B,EAAK,EAAS,EAAO,MAAQ,IAAA,GAAgB,EAAuB,OAAQ,EAAK,CACnF,EACA,UAAY,GAAwC,EAAM,UAAU,CAAE,CACxE,CACF,CACF"}
@@ -1,2 +1,2 @@
1
- function e(e,t,n){let r=e.computedCache.get(t);if(r)return r;let i,a=!0,o=0,s=!1,c=-1,l=2,u=new Set,d=new Map,f=new Set,p=e=>{if(!e)return;let t=e._node||e;if(t.dependencies&&t.dependencies.size>0){for(let n of t.dependencies){let r=n,i=r._node||r;i.subscribers&&(i.subscribers.delete(t),i.subscribers.delete(e),i.subscribers.delete(_),i.type===`computed`&&i.subscribers.size===0&&p(i))}t.dependencies.clear(),t.depVersions&&t.depVersions.clear()}},m=new Set,h=-1,g=t=>{if(!s||t.state===2)return t.run();if(h===e.epoch)return!1;if(t.state===1){let n=!1;if(t.dependencies&&t.dependencies.size>0)for(let e of t.dependencies){let r=e,i=r._node||r;n||(i.type===`computed`&&i.state>0&&g(i),t.depVersions.get(r)!==i.version&&(n=!0))}return h=e.epoch,t.state=0,n||a?t.run():!1}return h=e.epoch,!1},_={id:e.subscriberId++,dependencies:u,subscribers:m,ownedEffects:f,depth:1,type:`computed`,fn:t,get version(){return o},get state(){return l},set state(e){l=e},get depVersions(){return d},update:()=>g(_),run:()=>{if(c===e.epoch&&s)return!1;if(c=e.epoch,h=e.epoch,_.isEvaluating)throw Error(`[Graph Error] Cyclic dependency detected`);_.isEvaluating=!0;let r=e.activeConsumer,p=e.activeOwner;e.activeConsumer=_,e.activeOwner=_;let g=u.size>0?Array.from(u):null;u.clear();try{if(f.size>0){for(let e of f)e&&typeof e.dispose==`function`&&e.dispose();f.clear()}let r=t();if(g!==null)for(let e of g){let t=e;if(!u.has(t)){let e=t._node||t;e.subscribers&&e.subscribers.delete(_),d.delete(t)}}let c=a||!Object.is(i,r);if(c){let t=a?void 0:typeof i==`object`&&i?JSON.parse(JSON.stringify(i)):i;i=r,o++,e.log&&n&&e.log({type:`computed`,label:n,details:{from:t,to:r}});for(let t of m){let n=t._node||t;n.type===`effect`?(n.state=2,n.isDirty=!0,e.scheduleEffect(t)):n.markDirty&&n.markDirty(1)}}a=!1,l=0,s=!0;let p=0;for(let e of u){let t=e,n=t._node||t;d.set(t,n.version),n.subscribers&&n.subscribers.add(_),n.depth!==void 0&&n.depth>p&&(p=n.depth)}for(let t of m){let n=t._node||t;n.type===`effect`?(n.state=2,n.isDirty=!0,e.scheduleEffect(t)):n.markDirty&&n.markDirty(1)}return _.depth=p+1,c}finally{e.activeConsumer=r,e.activeOwner=p,_.isEvaluating=!1}},markDirty:t=>{if(!(l>=t)){l=t;for(let t of m){let n=t._node||t;n.type===`effect`?(n.isDirty=!0,e.scheduleEffect(t)):n.markDirty&&n.markDirty(1)}}}},v={get value(){return e.activeConsumer&&e.activeConsumer!==_&&(_.subscribers.add(e.activeConsumer),e.activeConsumer.dependencies.add(_)),g(_),e.activeConsumer&&e.activeConsumer.depVersions&&e.activeConsumer.depVersions.set(v,o),i},get valueWithoutTracking(){return i},get version(){return o},subscribe(t){let n={id:e.subscriberId++,isDirty:!0,depth:9999,dependencies:new Set,type:`effect`,run:()=>{if(!n.isDisposed)try{t(v.value)}catch(e){console.error(e)}}};return _.subscribers.add(n),t(v.value),()=>{n.isDisposed=!0,_.subscribers.delete(n)}},subscribeState(e){return v.subscribe(e)},destroy:()=>{_.subscribers.clear(),p(_),e.computedCache.delete(t),a=!0,l=2,s=!1},__subscribe(t){let n={id:e.subscriberId++,type:`effect`,run:t,isDirty:!1};return _.subscribers.add(n),()=>{m.delete(n)}}};return v._node=_,v.subscribers=m,v.dependencies=u,v._isDirty=()=>l>0,v.type=`computed`,v.run=()=>_.run(),e.computedCache.set(t,v),v}exports.createComputed=e;
1
+ function e(e,t,n){let r=e.computedCache.get(t);if(r)return r;let i,a=!0,o=0,s=!1,c=-1,l=2,u=new Set,d=new Map,f=new Set,p=e=>{if(!e)return;let t=e._node||e;if(t.dependencies&&t.dependencies.size>0){for(let n of t.dependencies){let r=n,i=r._node||r;i.subscribers&&(i.subscribers.delete(t),i.subscribers.delete(e),i.subscribers.delete(v),i.type===`computed`&&i.subscribers.size===0&&p(i))}t.dependencies.clear(),t.depVersions&&t.depVersions.clear()}},m=new Set,h=-1,g=t=>{if(!s||t.state===2)return t.run();if(h===e.epoch)return!1;if(t.state===1){let n=!1;if(t.dependencies&&t.dependencies.size>0)for(let e of t.dependencies){let r=e,i=r._node||r;n||(i.type===`computed`&&i.state>0&&g(i),t.depVersions.get(r)!==i.version&&(n=!0))}return h=e.epoch,t.state=0,n||a?t.run():!1}return h=e.epoch,!1},_=0,v={id:e.subscriberId++,dependencies:u,subscribers:m,ownedEffects:f,depth:1,type:`computed`,fn:t,get version(){return o},get state(){return l},set state(e){l=e},get depVersions(){return d},update:()=>g(v),run:()=>{if(c===e.epoch&&s)return!1;if(c=e.epoch,h=e.epoch,e.cycleDetectionStack.has(v))throw Error(`[Graph Error] Cyclic dependency detected`);e.cycleDetectionStack.add(v);let r=e.activeConsumer,p=e.activeOwner;e.activeConsumer=v,e.activeOwner=v,_++,v.activeRunId=_;try{if(f.size>0){for(let e of f)e&&typeof e.dispose==`function`&&e.dispose();f.clear()}let r=t();if(s&&u.size>0)for(let e of u){let t=e;if(t._lastSeenInRunId!==_){u.delete(t);let e=t._node||t;e.subscribers&&e.subscribers.delete(v),d.delete(t)}}let c=a||!Object.is(i,r);if(c){let t=a?void 0:typeof i==`object`&&i?JSON.parse(JSON.stringify(i)):i;i=r,o++,e.log&&n&&e.log({type:`computed`,label:n,details:{from:t,to:r}});for(let t of m){let n=t._node||t;n.type===`effect`?(n.state=2,n.isDirty=!0,e.scheduleEffect(t)):n.markDirty&&n.markDirty(1)}}a=!1,l=0,s=!0;let p=0;for(let e of u){let t=e,n=t._node||t;d.set(t,n.version),n.subscribers&&n.subscribers.add(v),n.depth!==void 0&&n.depth>p&&(p=n.depth)}for(let t of m){let n=t._node||t;n.type===`effect`?(n.state=2,n.isDirty=!0,e.scheduleEffect(t)):n.markDirty&&n.markDirty(1)}return v.depth=p+1,c}finally{e.activeConsumer=r,e.activeOwner=p,e.cycleDetectionStack.delete(v)}},markDirty:t=>{if(!(l>=t)){l=t;for(let t of m){let n=t._node||t;n.type===`effect`?(n.isDirty=!0,e.scheduleEffect(t)):n.markDirty&&n.markDirty(1)}}}},y={get value(){let t=e.activeConsumer;return t&&t!==v&&(v.subscribers.add(t),t.dependencies.add(v),t.activeRunId!==void 0&&(v._lastSeenInRunId=t.activeRunId)),g(v),t&&t.depVersions&&t.depVersions.set(y,o),i},get valueWithoutTracking(){return i},get version(){return o},subscribe(t){let n={id:e.subscriberId++,isDirty:!0,depth:9999,dependencies:new Set,type:`effect`,run:()=>{if(!n.isDisposed)try{t(y.value)}catch(e){console.error(e)}}};return v.subscribers.add(n),t(y.value),()=>{n.isDisposed=!0,v.subscribers.delete(n)}},subscribeState(e){return y.subscribe(e)},destroy:()=>{v.subscribers.clear(),p(v),e.computedCache.delete(t),a=!0,l=2,s=!1},__subscribe(t){let n={id:e.subscriberId++,type:`effect`,run:t,isDirty:!1};return v.subscribers.add(n),()=>{m.delete(n)}}};return y._node=v,y.subscribers=m,y.dependencies=u,y._isDirty=()=>l>0,y.type=`computed`,y.run=()=>v.run(),e.computedCache.set(t,y),y}exports.createComputed=e;
2
2
  //# sourceMappingURL=core.method.computed.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"core.method.computed.cjs","names":[],"sources":["../src/core/core.method.computed.ts"],"sourcesContent":["import { Computed, CleanupFn } from './types'\n\nexport function createComputed<T>(\n engine: any,\n fn: () => T,\n signalName?: string\n): Computed<T> {\n const existing = engine.computedCache.get(fn)\n if (existing) return existing as Computed<T>\n\n let value: T\n let isDirty = true\n let version = 0\n let isInitialized = false\n let evaluatedInEpoch = -1\n let state = 2\n\n const dependencies = new Set<any>()\n const depVersions = new Map<any, number>()\n const ownedEffects = new Set<any>()\n\n const releaseNode = (node: any): void => {\n if (!node) return\n const actNode = node._node || node\n\n if (actNode.dependencies && actNode.dependencies.size > 0) {\n // ⚡ ОПТИМИЗАЦИЯ: Полностью убираем Array.from()! Итерируемся прямо по Set.\n // Чтобы безопасно удалять элементы во время итерации (избегая бесконечных циклов в JS),\n // мы очищаем родительские подписки, а сам actNode.dependencies.clear() вызовем строго ПОСЛЕ цикла.\n for (const unknownDep of actNode.dependencies) {\n const dep = unknownDep as any\n const rawDepNode = dep._node || dep\n\n if (rawDepNode.subscribers) {\n // Выполняем точечное удаление. Если узел есть — удаляем, не дергая Set вхолостую\n rawDepNode.subscribers.delete(actNode)\n rawDepNode.subscribers.delete(node)\n rawDepNode.subscribers.delete(computedNode)\n\n // Рекурсивный спуск делаем только для живых computed-сирот,\n // у которых реально не осталось активных потребителей\n if (rawDepNode.type === 'computed' && rawDepNode.subscribers.size === 0) {\n releaseNode(rawDepNode)\n }\n }\n }\n\n // Атомарно очищаем зависимости узла за один такт O(1) после завершения обхода\n actNode.dependencies.clear()\n if (actNode.depVersions) actNode.depVersions.clear()\n }\n }\n\n const subscribers = new Set<any>()\n let verifiedInEpoch = -1\n\n const updateIfNecessary = (node: any): boolean => {\n if (!isInitialized) return node.run()\n if (node.state === 2) return node.run()\n\n if (verifiedInEpoch === engine.epoch) {\n return false\n }\n\n if (node.state === 1) {\n let hasChangedParent = false\n\n if (node.dependencies && node.dependencies.size > 0) {\n for (const unknownDep of node.dependencies) {\n const dep = unknownDep as any\n const rawDep = dep._node || dep\n\n if (!hasChangedParent) {\n if (rawDep.type === 'computed' && rawDep.state > 0) {\n updateIfNecessary(rawDep)\n }\n\n if (node.depVersions.get(dep) !== rawDep.version) {\n hasChangedParent = true\n }\n }\n }\n }\n\n verifiedInEpoch = engine.epoch\n node.state = 0\n\n if (hasChangedParent || isDirty) {\n return node.run()\n }\n return false\n }\n\n verifiedInEpoch = engine.epoch\n return false\n }\n\n const computedNode: any = {\n id: engine.subscriberId++,\n dependencies,\n subscribers,\n ownedEffects,\n depth: 1,\n type: 'computed',\n fn,\n get version() { return version },\n get state() { return state },\n set state(val: number) { state = val },\n get depVersions() { return depVersions },\n update: () => updateIfNecessary(computedNode),\n run: () => {\n if (evaluatedInEpoch === engine.epoch && isInitialized) {\n return false\n }\n evaluatedInEpoch = engine.epoch\n verifiedInEpoch = engine.epoch\n\n // ⚡ СВЕРХБЫСТРАЯ ЗАЩИТА ОТ ЦИКЛОВ (O(1) Inline Flag Bypass):\n // Вместо тяжелых runtime-мутаций глобальной коллекции Set, используем плоский флаг на узле.\n if (computedNode.isEvaluating) {\n throw new Error('[Graph Error] Cyclic dependency detected')\n }\n computedNode.isEvaluating = true // Блокируем узел перед вычислением\n\n const prevConsumer = engine.activeConsumer\n const prevOwner = engine.activeOwner\n\n engine.activeConsumer = computedNode\n engine.activeOwner = computedNode\n\n const oldDeps = dependencies.size > 0 ? Array.from(dependencies) : null\n dependencies.clear()\n\n try {\n if (ownedEffects.size > 0) {\n for (const child of ownedEffects) {\n if (child && typeof child.dispose === 'function') {\n child.dispose()\n }\n }\n ownedEffects.clear()\n }\n\n const newValue = fn()\n\n if (oldDeps !== null) {\n for (const unknownDep of oldDeps) {\n const dep = unknownDep as any\n if (!dependencies.has(dep)) {\n const rawDepNode = dep._node || dep\n if (rawDepNode.subscribers) rawDepNode.subscribers.delete(computedNode)\n depVersions.delete(dep)\n }\n }\n }\n\n const changed = isDirty || !Object.is(value, newValue)\n\n if (changed) {\n const previousValueSnapshot = isDirty ? undefined : (typeof value === 'object' && value !== null ? JSON.parse(JSON.stringify(value)) : value)\n value = newValue\n version++\n\n if (engine.log && signalName) {\n engine.log({\n type: 'computed',\n label: signalName,\n details: { from: previousValueSnapshot, to: newValue }\n })\n }\n\n for (const sub of subscribers) {\n const rawSub = sub._node || sub\n if (rawSub.type === 'effect') {\n rawSub.state = 2\n rawSub.isDirty = true\n engine.scheduleEffect(sub)\n } else if (rawSub.markDirty) {\n rawSub.markDirty(1)\n }\n }\n }\n\n isDirty = false\n state = 0\n isInitialized = true\n\n let maxDepDepth = 0\n for (const unknownDep of dependencies) {\n const dep = unknownDep as any\n const rawNode = dep._node || dep\n depVersions.set(dep, rawNode.version)\n if (rawNode.subscribers) rawNode.subscribers.add(computedNode)\n if (rawNode.depth !== undefined && rawNode.depth > maxDepDepth) {\n maxDepDepth = rawNode.depth\n }\n }\n\n for (const sub of subscribers) {\n const rawSub = sub._node || sub\n if (rawSub.type === 'effect') {\n rawSub.state = 2\n rawSub.isDirty = true\n engine.scheduleEffect(sub)\n } else if (rawSub.markDirty) {\n rawSub.markDirty(1)\n }\n }\n\n computedNode.depth = maxDepDepth + 1\n return changed\n } finally {\n engine.activeConsumer = prevConsumer\n engine.activeOwner = prevOwner\n computedNode.isEvaluating = false // ⚡ Снимаем блокировку строго в finally\n }\n },\n markDirty: (parentState: number) => {\n if (state >= parentState) return\n state = parentState\n\n for (const sub of subscribers) {\n const rawSub = sub._node || sub\n if (rawSub.type === 'effect') {\n rawSub.isDirty = true\n engine.scheduleEffect(sub)\n } else if (rawSub.markDirty) {\n rawSub.markDirty(1)\n }\n }\n }\n }\n\n const computedInstance: Computed<T> = {\n get value() {\n if (engine.activeConsumer && engine.activeConsumer !== computedNode) {\n computedNode.subscribers.add(engine.activeConsumer)\n engine.activeConsumer.dependencies.add(computedNode)\n }\n\n updateIfNecessary(computedNode)\n\n if (engine.activeConsumer && engine.activeConsumer.depVersions) {\n engine.activeConsumer.depVersions.set(computedInstance, version)\n }\n return value\n },\n get valueWithoutTracking() { return value },\n get version() { return version },\n subscribe(cb: (val: T) => void): CleanupFn {\n const fakeEffect: any = {\n id: engine.subscriberId++,\n isDirty: true,\n depth: 9999,\n dependencies: new Set(),\n type: 'effect',\n run: () => {\n if (fakeEffect.isDisposed) return\n try { cb(computedInstance.value) } catch (err) { console.error(err) }\n }\n }\n computedNode.subscribers.add(fakeEffect)\n cb(computedInstance.value)\n return () => {\n fakeEffect.isDisposed = true\n computedNode.subscribers.delete(fakeEffect)\n }\n },\n subscribeState(cb: () => void): CleanupFn {\n return (computedInstance as any).subscribe(cb)\n },\n destroy: () => {\n computedNode.subscribers.clear()\n releaseNode(computedNode)\n engine.computedCache.delete(fn)\n isDirty = true\n state = 2\n isInitialized = false\n },\n __subscribe(cb: () => void): CleanupFn {\n const hookEffect: any = {\n id: engine.subscriberId++,\n type: 'effect',\n run: cb,\n isDirty: false\n }\n computedNode.subscribers.add(hookEffect)\n return () => {\n subscribers.delete(hookEffect)\n }\n }\n } as any\n\n ;(computedInstance as any)._node = computedNode\n ;(computedInstance as any).subscribers = subscribers\n ;(computedInstance as any).dependencies = dependencies\n computedInstance._isDirty = () => state > 0\n computedInstance.type = 'computed'\n computedInstance.run = () => computedNode.run()\n\n engine.computedCache.set(fn, computedInstance)\n return computedInstance\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"core.method.computed.cjs","names":[],"sources":["../src/core/core.method.computed.ts"],"sourcesContent":["import { Computed, CleanupFn } from './types'\n\nexport function createComputed<T>(\n engine: any,\n fn: () => T,\n signalName?: string\n): Computed<T> {\n const existing = engine.computedCache.get(fn)\n if (existing) return existing as Computed<T>\n\n let value: T\n let isDirty = true\n let version = 0\n let isInitialized = false\n let evaluatedInEpoch = -1\n let state = 2\n\n const dependencies = new Set<any>()\n const depVersions = new Map<any, number>()\n const ownedEffects = new Set<any>()\n\n const releaseNode = (node: any): void => {\n if (!node) return\n const actNode = node._node || node\n\n if (actNode.dependencies && actNode.dependencies.size > 0) {\n // ⚡ ОПТИМИЗАЦИЯ: Полностью убираем Array.from()! Итерируемся прямо по Set.\n // Чтобы безопасно удалять элементы во время итерации (избегая бесконечных циклов в JS),\n // мы очищаем родительские подписки, а сам actNode.dependencies.clear() вызовем строго ПОСЛЕ цикла.\n for (const unknownDep of actNode.dependencies) {\n const dep = unknownDep as any\n const rawDepNode = dep._node || dep\n\n if (rawDepNode.subscribers) {\n // Выполняем точечное удаление. Если узел есть — удаляем, не дергая Set вхолостую\n rawDepNode.subscribers.delete(actNode)\n rawDepNode.subscribers.delete(node)\n rawDepNode.subscribers.delete(computedNode)\n\n // Рекурсивный спуск делаем только для живых computed-сирот,\n // у которых реально не осталось активных потребителей\n if (rawDepNode.type === 'computed' && rawDepNode.subscribers.size === 0) {\n releaseNode(rawDepNode)\n }\n }\n }\n\n // Атомарно очищаем зависимости узла за один такт O(1) после завершения обхода\n actNode.dependencies.clear()\n if (actNode.depVersions) actNode.depVersions.clear()\n }\n }\n\n const subscribers = new Set<any>()\n let verifiedInEpoch = -1\n\n const updateIfNecessary = (node: any): boolean => {\n if (!isInitialized) return node.run()\n if (node.state === 2) return node.run()\n\n if (verifiedInEpoch === engine.epoch) {\n return false\n }\n\n if (node.state === 1) {\n let hasChangedParent = false\n\n if (node.dependencies && node.dependencies.size > 0) {\n for (const unknownDep of node.dependencies) {\n const dep = unknownDep as any\n const rawDep = dep._node || dep\n\n if (!hasChangedParent) {\n if (rawDep.type === 'computed' && rawDep.state > 0) {\n updateIfNecessary(rawDep)\n }\n\n if (node.depVersions.get(dep) !== rawDep.version) {\n hasChangedParent = true\n }\n }\n }\n }\n\n verifiedInEpoch = engine.epoch\n node.state = 0\n\n if (hasChangedParent || isDirty) {\n return node.run()\n }\n return false\n }\n\n verifiedInEpoch = engine.epoch\n return false\n }\n\n // Счечтик итераций: Мы внедрим маркерную эпоху вычисления прямо на связь.\n // Для этого мы будем инкрементировать системный счетчик запусков узла (computedNode.runId), а при чтении геттеров родители будут запоминать этот runId.\n let currentRunId = 0\n\n const computedNode: any = {\n id: engine.subscriberId++,\n dependencies,\n subscribers,\n ownedEffects,\n depth: 1,\n type: 'computed',\n fn,\n get version() { return version },\n get state() { return state },\n set state(val: number) { state = val },\n get depVersions() { return depVersions },\n update: () => updateIfNecessary(computedNode),\n run: () => {\n if (evaluatedInEpoch === engine.epoch && isInitialized) {\n return false\n }\n evaluatedInEpoch = engine.epoch\n verifiedInEpoch = engine.epoch\n\n if (engine.cycleDetectionStack.has(computedNode)) {\n throw new Error('[Graph Error] Cyclic dependency detected')\n }\n engine.cycleDetectionStack.add(computedNode)\n\n const prevConsumer = engine.activeConsumer\n const prevOwner = engine.activeOwner\n\n engine.activeConsumer = computedNode\n engine.activeOwner = computedNode\n\n // Инкрементируем уникальный ID текущего расчета\n currentRunId++\n computedNode.activeRunId = currentRunId\n\n try {\n if (ownedEffects.size > 0) {\n for (const child of ownedEffects) {\n if (child && typeof child.dispose === 'function') {\n child.dispose()\n }\n }\n ownedEffects.clear()\n }\n\n // Вычисляем пользовательскую функцию.\n // В процессе выполнения геттеры сигналов запишут dep._lastSeenInRunId = currentRunId\n const newValue = fn()\n\n // ⚡ СВЕРХБЫСТРЫЙ МАРКЕРНЫЙ ДИФФ (Zero-Allocation Hot Path):\n // Вместо полной очистки коллекции dependencies и создания временных массивов,\n // мы в один плоский проход удаляем только те ребра, которые не были прочитаны в этом цикле!\n if (isInitialized && dependencies.size > 0) {\n // Чтобы безопасно удалять элементы Set во время итерации for...of, V8 не требует копирования,\n // если мы удаляем элементы точечно.\n for (const unknownDep of dependencies) {\n const dep = unknownDep as any\n if (dep._lastSeenInRunId !== currentRunId) {\n // Это ребро графа умерло в текущем кадре (условное ветвление)\n dependencies.delete(dep)\n const rawDepNode = dep._node || dep\n if (rawDepNode.subscribers) rawDepNode.subscribers.delete(computedNode)\n depVersions.delete(dep)\n }\n }\n }\n\n const changed = isDirty || !Object.is(value, newValue)\n\n if (changed) {\n const previousValueSnapshot = isDirty ? undefined : (typeof value === 'object' && value !== null ? JSON.parse(JSON.stringify(value)) : value)\n value = newValue\n version++\n\n if (engine.log && signalName) {\n engine.log({\n type: 'computed',\n label: signalName,\n details: { from: previousValueSnapshot, to: newValue }\n })\n }\n\n for (const sub of subscribers) {\n const rawSub = sub._node || sub\n if (rawSub.type === 'effect') {\n rawSub.state = 2\n rawSub.isDirty = true\n engine.scheduleEffect(sub)\n } else if (rawSub.markDirty) {\n rawSub.markDirty(1)\n }\n }\n }\n\n isDirty = false\n state = 0\n isInitialized = true\n\n let maxDepDepth = 0\n for (const unknownDep of dependencies) {\n const dep = unknownDep as any\n const rawNode = dep._node || dep\n depVersions.set(dep, rawNode.version)\n if (rawNode.subscribers) rawNode.subscribers.add(computedNode)\n if (rawNode.depth !== undefined && rawNode.depth > maxDepDepth) {\n maxDepDepth = rawNode.depth\n }\n }\n\n for (const sub of subscribers) {\n const rawSub = sub._node || sub\n if (rawSub.type === 'effect') {\n rawSub.state = 2\n rawSub.isDirty = true\n engine.scheduleEffect(sub)\n } else if (rawSub.markDirty) {\n rawSub.markDirty(1)\n }\n }\n\n computedNode.depth = maxDepDepth + 1\n return changed\n } finally {\n engine.activeConsumer = prevConsumer\n engine.activeOwner = prevOwner\n engine.cycleDetectionStack.delete(computedNode)\n }\n },\n markDirty: (parentState: number) => {\n if (state >= parentState) return\n state = parentState\n\n for (const sub of subscribers) {\n const rawSub = sub._node || sub\n if (rawSub.type === 'effect') {\n rawSub.isDirty = true\n engine.scheduleEffect(sub)\n } else if (rawSub.markDirty) {\n rawSub.markDirty(1)\n }\n }\n }\n }\n\n const computedInstance: Computed<T> = {\n get value() {\n const consumer = engine.activeConsumer\n if (consumer && consumer !== computedNode) {\n computedNode.subscribers.add(consumer)\n consumer.dependencies.add(computedNode)\n\n // ⚡ Маркерная эпоха (Zero-Allocation Track)\n if (consumer.activeRunId !== undefined) {\n computedNode._lastSeenInRunId = consumer.activeRunId\n }\n }\n\n updateIfNecessary(computedNode)\n\n // Оптимизация: используем локальную ссылку consumer вместо повторного обращения к engine\n if (consumer && consumer.depVersions) {\n consumer.depVersions.set(computedInstance, version)\n }\n return value\n },\n get valueWithoutTracking() { return value },\n get version() { return version },\n subscribe(cb: (val: T) => void): CleanupFn {\n const fakeEffect: any = {\n id: engine.subscriberId++,\n isDirty: true,\n depth: 9999,\n dependencies: new Set(),\n type: 'effect',\n run: () => {\n if (fakeEffect.isDisposed) return\n try { cb(computedInstance.value) } catch (err) { console.error(err) }\n }\n }\n computedNode.subscribers.add(fakeEffect)\n cb(computedInstance.value)\n return () => {\n fakeEffect.isDisposed = true\n computedNode.subscribers.delete(fakeEffect)\n }\n },\n subscribeState(cb: () => void): CleanupFn {\n return (computedInstance as any).subscribe(cb)\n },\n destroy: () => {\n computedNode.subscribers.clear()\n releaseNode(computedNode)\n engine.computedCache.delete(fn)\n isDirty = true\n state = 2\n isInitialized = false\n },\n __subscribe(cb: () => void): CleanupFn {\n const hookEffect: any = {\n id: engine.subscriberId++,\n type: 'effect',\n run: cb,\n isDirty: false\n }\n computedNode.subscribers.add(hookEffect)\n return () => {\n subscribers.delete(hookEffect)\n }\n }\n } as any\n\n ;(computedInstance as any)._node = computedNode\n ;(computedInstance as any).subscribers = subscribers\n ;(computedInstance as any).dependencies = dependencies\n computedInstance._isDirty = () => state > 0\n computedInstance.type = 'computed'\n computedInstance.run = () => computedNode.run()\n\n engine.computedCache.set(fn, computedInstance)\n return computedInstance\n}\n"],"mappings":"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"}
@@ -8,7 +8,7 @@ function e(e, t, n) {
8
8
  if (t.dependencies && t.dependencies.size > 0) {
9
9
  for (let n of t.dependencies) {
10
10
  let r = n, i = r._node || r;
11
- i.subscribers && (i.subscribers.delete(t), i.subscribers.delete(e), i.subscribers.delete(_), i.type === "computed" && i.subscribers.size === 0 && p(i));
11
+ i.subscribers && (i.subscribers.delete(t), i.subscribers.delete(e), i.subscribers.delete(v), i.type === "computed" && i.subscribers.size === 0 && p(i));
12
12
  }
13
13
  t.dependencies.clear(), t.depVersions && t.depVersions.clear();
14
14
  }
@@ -24,7 +24,7 @@ function e(e, t, n) {
24
24
  return h = e.epoch, t.state = 0, n || a ? t.run() : !1;
25
25
  }
26
26
  return h = e.epoch, !1;
27
- }, _ = {
27
+ }, _ = 0, v = {
28
28
  id: e.subscriberId++,
29
29
  dependencies: u,
30
30
  subscribers: m,
@@ -44,26 +44,25 @@ function e(e, t, n) {
44
44
  get depVersions() {
45
45
  return d;
46
46
  },
47
- update: () => g(_),
47
+ update: () => g(v),
48
48
  run: () => {
49
49
  if (c === e.epoch && s) return !1;
50
- if (c = e.epoch, h = e.epoch, _.isEvaluating) throw Error("[Graph Error] Cyclic dependency detected");
51
- _.isEvaluating = !0;
50
+ if (c = e.epoch, h = e.epoch, e.cycleDetectionStack.has(v)) throw Error("[Graph Error] Cyclic dependency detected");
51
+ e.cycleDetectionStack.add(v);
52
52
  let r = e.activeConsumer, p = e.activeOwner;
53
- e.activeConsumer = _, e.activeOwner = _;
54
- let g = u.size > 0 ? Array.from(u) : null;
55
- u.clear();
53
+ e.activeConsumer = v, e.activeOwner = v, _++, v.activeRunId = _;
56
54
  try {
57
55
  if (f.size > 0) {
58
56
  for (let e of f) e && typeof e.dispose == "function" && e.dispose();
59
57
  f.clear();
60
58
  }
61
59
  let r = t();
62
- if (g !== null) for (let e of g) {
60
+ if (s && u.size > 0) for (let e of u) {
63
61
  let t = e;
64
- if (!u.has(t)) {
62
+ if (t._lastSeenInRunId !== _) {
63
+ u.delete(t);
65
64
  let e = t._node || t;
66
- e.subscribers && e.subscribers.delete(_), d.delete(t);
65
+ e.subscribers && e.subscribers.delete(v), d.delete(t);
67
66
  }
68
67
  }
69
68
  let c = a || !Object.is(i, r);
@@ -86,15 +85,15 @@ function e(e, t, n) {
86
85
  let p = 0;
87
86
  for (let e of u) {
88
87
  let t = e, n = t._node || t;
89
- d.set(t, n.version), n.subscribers && n.subscribers.add(_), n.depth !== void 0 && n.depth > p && (p = n.depth);
88
+ d.set(t, n.version), n.subscribers && n.subscribers.add(v), n.depth !== void 0 && n.depth > p && (p = n.depth);
90
89
  }
91
90
  for (let t of m) {
92
91
  let n = t._node || t;
93
92
  n.type === "effect" ? (n.state = 2, n.isDirty = !0, e.scheduleEffect(t)) : n.markDirty && n.markDirty(1);
94
93
  }
95
- return _.depth = p + 1, c;
94
+ return v.depth = p + 1, c;
96
95
  } finally {
97
- e.activeConsumer = r, e.activeOwner = p, _.isEvaluating = !1;
96
+ e.activeConsumer = r, e.activeOwner = p, e.cycleDetectionStack.delete(v);
98
97
  }
99
98
  },
100
99
  markDirty: (t) => {
@@ -106,9 +105,10 @@ function e(e, t, n) {
106
105
  }
107
106
  }
108
107
  }
109
- }, v = {
108
+ }, y = {
110
109
  get value() {
111
- return e.activeConsumer && e.activeConsumer !== _ && (_.subscribers.add(e.activeConsumer), e.activeConsumer.dependencies.add(_)), g(_), e.activeConsumer && e.activeConsumer.depVersions && e.activeConsumer.depVersions.set(v, o), i;
110
+ let t = e.activeConsumer;
111
+ return t && t !== v && (v.subscribers.add(t), t.dependencies.add(v), t.activeRunId !== void 0 && (v._lastSeenInRunId = t.activeRunId)), g(v), t && t.depVersions && t.depVersions.set(y, o), i;
112
112
  },
113
113
  get valueWithoutTracking() {
114
114
  return i;
@@ -125,21 +125,21 @@ function e(e, t, n) {
125
125
  type: "effect",
126
126
  run: () => {
127
127
  if (!n.isDisposed) try {
128
- t(v.value);
128
+ t(y.value);
129
129
  } catch (e) {
130
130
  console.error(e);
131
131
  }
132
132
  }
133
133
  };
134
- return _.subscribers.add(n), t(v.value), () => {
135
- n.isDisposed = !0, _.subscribers.delete(n);
134
+ return v.subscribers.add(n), t(y.value), () => {
135
+ n.isDisposed = !0, v.subscribers.delete(n);
136
136
  };
137
137
  },
138
138
  subscribeState(e) {
139
- return v.subscribe(e);
139
+ return y.subscribe(e);
140
140
  },
141
141
  destroy: () => {
142
- _.subscribers.clear(), p(_), e.computedCache.delete(t), a = !0, l = 2, s = !1;
142
+ v.subscribers.clear(), p(v), e.computedCache.delete(t), a = !0, l = 2, s = !1;
143
143
  },
144
144
  __subscribe(t) {
145
145
  let n = {
@@ -148,12 +148,12 @@ function e(e, t, n) {
148
148
  run: t,
149
149
  isDirty: !1
150
150
  };
151
- return _.subscribers.add(n), () => {
151
+ return v.subscribers.add(n), () => {
152
152
  m.delete(n);
153
153
  };
154
154
  }
155
155
  };
156
- return v._node = _, v.subscribers = m, v.dependencies = u, v._isDirty = () => l > 0, v.type = "computed", v.run = () => _.run(), e.computedCache.set(t, v), v;
156
+ return y._node = v, y.subscribers = m, y.dependencies = u, y._isDirty = () => l > 0, y.type = "computed", y.run = () => v.run(), e.computedCache.set(t, y), y;
157
157
  }
158
158
  //#endregion
159
159
  export { e as createComputed };
@@ -1 +1 @@
1
- {"version":3,"file":"core.method.computed.mjs","names":[],"sources":["../src/core/core.method.computed.ts"],"sourcesContent":["import { Computed, CleanupFn } from './types'\n\nexport function createComputed<T>(\n engine: any,\n fn: () => T,\n signalName?: string\n): Computed<T> {\n const existing = engine.computedCache.get(fn)\n if (existing) return existing as Computed<T>\n\n let value: T\n let isDirty = true\n let version = 0\n let isInitialized = false\n let evaluatedInEpoch = -1\n let state = 2\n\n const dependencies = new Set<any>()\n const depVersions = new Map<any, number>()\n const ownedEffects = new Set<any>()\n\n const releaseNode = (node: any): void => {\n if (!node) return\n const actNode = node._node || node\n\n if (actNode.dependencies && actNode.dependencies.size > 0) {\n // ⚡ ОПТИМИЗАЦИЯ: Полностью убираем Array.from()! Итерируемся прямо по Set.\n // Чтобы безопасно удалять элементы во время итерации (избегая бесконечных циклов в JS),\n // мы очищаем родительские подписки, а сам actNode.dependencies.clear() вызовем строго ПОСЛЕ цикла.\n for (const unknownDep of actNode.dependencies) {\n const dep = unknownDep as any\n const rawDepNode = dep._node || dep\n\n if (rawDepNode.subscribers) {\n // Выполняем точечное удаление. Если узел есть — удаляем, не дергая Set вхолостую\n rawDepNode.subscribers.delete(actNode)\n rawDepNode.subscribers.delete(node)\n rawDepNode.subscribers.delete(computedNode)\n\n // Рекурсивный спуск делаем только для живых computed-сирот,\n // у которых реально не осталось активных потребителей\n if (rawDepNode.type === 'computed' && rawDepNode.subscribers.size === 0) {\n releaseNode(rawDepNode)\n }\n }\n }\n\n // Атомарно очищаем зависимости узла за один такт O(1) после завершения обхода\n actNode.dependencies.clear()\n if (actNode.depVersions) actNode.depVersions.clear()\n }\n }\n\n const subscribers = new Set<any>()\n let verifiedInEpoch = -1\n\n const updateIfNecessary = (node: any): boolean => {\n if (!isInitialized) return node.run()\n if (node.state === 2) return node.run()\n\n if (verifiedInEpoch === engine.epoch) {\n return false\n }\n\n if (node.state === 1) {\n let hasChangedParent = false\n\n if (node.dependencies && node.dependencies.size > 0) {\n for (const unknownDep of node.dependencies) {\n const dep = unknownDep as any\n const rawDep = dep._node || dep\n\n if (!hasChangedParent) {\n if (rawDep.type === 'computed' && rawDep.state > 0) {\n updateIfNecessary(rawDep)\n }\n\n if (node.depVersions.get(dep) !== rawDep.version) {\n hasChangedParent = true\n }\n }\n }\n }\n\n verifiedInEpoch = engine.epoch\n node.state = 0\n\n if (hasChangedParent || isDirty) {\n return node.run()\n }\n return false\n }\n\n verifiedInEpoch = engine.epoch\n return false\n }\n\n const computedNode: any = {\n id: engine.subscriberId++,\n dependencies,\n subscribers,\n ownedEffects,\n depth: 1,\n type: 'computed',\n fn,\n get version() { return version },\n get state() { return state },\n set state(val: number) { state = val },\n get depVersions() { return depVersions },\n update: () => updateIfNecessary(computedNode),\n run: () => {\n if (evaluatedInEpoch === engine.epoch && isInitialized) {\n return false\n }\n evaluatedInEpoch = engine.epoch\n verifiedInEpoch = engine.epoch\n\n // ⚡ СВЕРХБЫСТРАЯ ЗАЩИТА ОТ ЦИКЛОВ (O(1) Inline Flag Bypass):\n // Вместо тяжелых runtime-мутаций глобальной коллекции Set, используем плоский флаг на узле.\n if (computedNode.isEvaluating) {\n throw new Error('[Graph Error] Cyclic dependency detected')\n }\n computedNode.isEvaluating = true // Блокируем узел перед вычислением\n\n const prevConsumer = engine.activeConsumer\n const prevOwner = engine.activeOwner\n\n engine.activeConsumer = computedNode\n engine.activeOwner = computedNode\n\n const oldDeps = dependencies.size > 0 ? Array.from(dependencies) : null\n dependencies.clear()\n\n try {\n if (ownedEffects.size > 0) {\n for (const child of ownedEffects) {\n if (child && typeof child.dispose === 'function') {\n child.dispose()\n }\n }\n ownedEffects.clear()\n }\n\n const newValue = fn()\n\n if (oldDeps !== null) {\n for (const unknownDep of oldDeps) {\n const dep = unknownDep as any\n if (!dependencies.has(dep)) {\n const rawDepNode = dep._node || dep\n if (rawDepNode.subscribers) rawDepNode.subscribers.delete(computedNode)\n depVersions.delete(dep)\n }\n }\n }\n\n const changed = isDirty || !Object.is(value, newValue)\n\n if (changed) {\n const previousValueSnapshot = isDirty ? undefined : (typeof value === 'object' && value !== null ? JSON.parse(JSON.stringify(value)) : value)\n value = newValue\n version++\n\n if (engine.log && signalName) {\n engine.log({\n type: 'computed',\n label: signalName,\n details: { from: previousValueSnapshot, to: newValue }\n })\n }\n\n for (const sub of subscribers) {\n const rawSub = sub._node || sub\n if (rawSub.type === 'effect') {\n rawSub.state = 2\n rawSub.isDirty = true\n engine.scheduleEffect(sub)\n } else if (rawSub.markDirty) {\n rawSub.markDirty(1)\n }\n }\n }\n\n isDirty = false\n state = 0\n isInitialized = true\n\n let maxDepDepth = 0\n for (const unknownDep of dependencies) {\n const dep = unknownDep as any\n const rawNode = dep._node || dep\n depVersions.set(dep, rawNode.version)\n if (rawNode.subscribers) rawNode.subscribers.add(computedNode)\n if (rawNode.depth !== undefined && rawNode.depth > maxDepDepth) {\n maxDepDepth = rawNode.depth\n }\n }\n\n for (const sub of subscribers) {\n const rawSub = sub._node || sub\n if (rawSub.type === 'effect') {\n rawSub.state = 2\n rawSub.isDirty = true\n engine.scheduleEffect(sub)\n } else if (rawSub.markDirty) {\n rawSub.markDirty(1)\n }\n }\n\n computedNode.depth = maxDepDepth + 1\n return changed\n } finally {\n engine.activeConsumer = prevConsumer\n engine.activeOwner = prevOwner\n computedNode.isEvaluating = false // ⚡ Снимаем блокировку строго в finally\n }\n },\n markDirty: (parentState: number) => {\n if (state >= parentState) return\n state = parentState\n\n for (const sub of subscribers) {\n const rawSub = sub._node || sub\n if (rawSub.type === 'effect') {\n rawSub.isDirty = true\n engine.scheduleEffect(sub)\n } else if (rawSub.markDirty) {\n rawSub.markDirty(1)\n }\n }\n }\n }\n\n const computedInstance: Computed<T> = {\n get value() {\n if (engine.activeConsumer && engine.activeConsumer !== computedNode) {\n computedNode.subscribers.add(engine.activeConsumer)\n engine.activeConsumer.dependencies.add(computedNode)\n }\n\n updateIfNecessary(computedNode)\n\n if (engine.activeConsumer && engine.activeConsumer.depVersions) {\n engine.activeConsumer.depVersions.set(computedInstance, version)\n }\n return value\n },\n get valueWithoutTracking() { return value },\n get version() { return version },\n subscribe(cb: (val: T) => void): CleanupFn {\n const fakeEffect: any = {\n id: engine.subscriberId++,\n isDirty: true,\n depth: 9999,\n dependencies: new Set(),\n type: 'effect',\n run: () => {\n if (fakeEffect.isDisposed) return\n try { cb(computedInstance.value) } catch (err) { console.error(err) }\n }\n }\n computedNode.subscribers.add(fakeEffect)\n cb(computedInstance.value)\n return () => {\n fakeEffect.isDisposed = true\n computedNode.subscribers.delete(fakeEffect)\n }\n },\n subscribeState(cb: () => void): CleanupFn {\n return (computedInstance as any).subscribe(cb)\n },\n destroy: () => {\n computedNode.subscribers.clear()\n releaseNode(computedNode)\n engine.computedCache.delete(fn)\n isDirty = true\n state = 2\n isInitialized = false\n },\n __subscribe(cb: () => void): CleanupFn {\n const hookEffect: any = {\n id: engine.subscriberId++,\n type: 'effect',\n run: cb,\n isDirty: false\n }\n computedNode.subscribers.add(hookEffect)\n return () => {\n subscribers.delete(hookEffect)\n }\n }\n } as any\n\n ;(computedInstance as any)._node = computedNode\n ;(computedInstance as any).subscribers = subscribers\n ;(computedInstance as any).dependencies = dependencies\n computedInstance._isDirty = () => state > 0\n computedInstance.type = 'computed'\n computedInstance.run = () => computedNode.run()\n\n engine.computedCache.set(fn, computedInstance)\n return computedInstance\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"core.method.computed.mjs","names":[],"sources":["../src/core/core.method.computed.ts"],"sourcesContent":["import { Computed, CleanupFn } from './types'\n\nexport function createComputed<T>(\n engine: any,\n fn: () => T,\n signalName?: string\n): Computed<T> {\n const existing = engine.computedCache.get(fn)\n if (existing) return existing as Computed<T>\n\n let value: T\n let isDirty = true\n let version = 0\n let isInitialized = false\n let evaluatedInEpoch = -1\n let state = 2\n\n const dependencies = new Set<any>()\n const depVersions = new Map<any, number>()\n const ownedEffects = new Set<any>()\n\n const releaseNode = (node: any): void => {\n if (!node) return\n const actNode = node._node || node\n\n if (actNode.dependencies && actNode.dependencies.size > 0) {\n // ⚡ ОПТИМИЗАЦИЯ: Полностью убираем Array.from()! Итерируемся прямо по Set.\n // Чтобы безопасно удалять элементы во время итерации (избегая бесконечных циклов в JS),\n // мы очищаем родительские подписки, а сам actNode.dependencies.clear() вызовем строго ПОСЛЕ цикла.\n for (const unknownDep of actNode.dependencies) {\n const dep = unknownDep as any\n const rawDepNode = dep._node || dep\n\n if (rawDepNode.subscribers) {\n // Выполняем точечное удаление. Если узел есть — удаляем, не дергая Set вхолостую\n rawDepNode.subscribers.delete(actNode)\n rawDepNode.subscribers.delete(node)\n rawDepNode.subscribers.delete(computedNode)\n\n // Рекурсивный спуск делаем только для живых computed-сирот,\n // у которых реально не осталось активных потребителей\n if (rawDepNode.type === 'computed' && rawDepNode.subscribers.size === 0) {\n releaseNode(rawDepNode)\n }\n }\n }\n\n // Атомарно очищаем зависимости узла за один такт O(1) после завершения обхода\n actNode.dependencies.clear()\n if (actNode.depVersions) actNode.depVersions.clear()\n }\n }\n\n const subscribers = new Set<any>()\n let verifiedInEpoch = -1\n\n const updateIfNecessary = (node: any): boolean => {\n if (!isInitialized) return node.run()\n if (node.state === 2) return node.run()\n\n if (verifiedInEpoch === engine.epoch) {\n return false\n }\n\n if (node.state === 1) {\n let hasChangedParent = false\n\n if (node.dependencies && node.dependencies.size > 0) {\n for (const unknownDep of node.dependencies) {\n const dep = unknownDep as any\n const rawDep = dep._node || dep\n\n if (!hasChangedParent) {\n if (rawDep.type === 'computed' && rawDep.state > 0) {\n updateIfNecessary(rawDep)\n }\n\n if (node.depVersions.get(dep) !== rawDep.version) {\n hasChangedParent = true\n }\n }\n }\n }\n\n verifiedInEpoch = engine.epoch\n node.state = 0\n\n if (hasChangedParent || isDirty) {\n return node.run()\n }\n return false\n }\n\n verifiedInEpoch = engine.epoch\n return false\n }\n\n // Счечтик итераций: Мы внедрим маркерную эпоху вычисления прямо на связь.\n // Для этого мы будем инкрементировать системный счетчик запусков узла (computedNode.runId), а при чтении геттеров родители будут запоминать этот runId.\n let currentRunId = 0\n\n const computedNode: any = {\n id: engine.subscriberId++,\n dependencies,\n subscribers,\n ownedEffects,\n depth: 1,\n type: 'computed',\n fn,\n get version() { return version },\n get state() { return state },\n set state(val: number) { state = val },\n get depVersions() { return depVersions },\n update: () => updateIfNecessary(computedNode),\n run: () => {\n if (evaluatedInEpoch === engine.epoch && isInitialized) {\n return false\n }\n evaluatedInEpoch = engine.epoch\n verifiedInEpoch = engine.epoch\n\n if (engine.cycleDetectionStack.has(computedNode)) {\n throw new Error('[Graph Error] Cyclic dependency detected')\n }\n engine.cycleDetectionStack.add(computedNode)\n\n const prevConsumer = engine.activeConsumer\n const prevOwner = engine.activeOwner\n\n engine.activeConsumer = computedNode\n engine.activeOwner = computedNode\n\n // Инкрементируем уникальный ID текущего расчета\n currentRunId++\n computedNode.activeRunId = currentRunId\n\n try {\n if (ownedEffects.size > 0) {\n for (const child of ownedEffects) {\n if (child && typeof child.dispose === 'function') {\n child.dispose()\n }\n }\n ownedEffects.clear()\n }\n\n // Вычисляем пользовательскую функцию.\n // В процессе выполнения геттеры сигналов запишут dep._lastSeenInRunId = currentRunId\n const newValue = fn()\n\n // ⚡ СВЕРХБЫСТРЫЙ МАРКЕРНЫЙ ДИФФ (Zero-Allocation Hot Path):\n // Вместо полной очистки коллекции dependencies и создания временных массивов,\n // мы в один плоский проход удаляем только те ребра, которые не были прочитаны в этом цикле!\n if (isInitialized && dependencies.size > 0) {\n // Чтобы безопасно удалять элементы Set во время итерации for...of, V8 не требует копирования,\n // если мы удаляем элементы точечно.\n for (const unknownDep of dependencies) {\n const dep = unknownDep as any\n if (dep._lastSeenInRunId !== currentRunId) {\n // Это ребро графа умерло в текущем кадре (условное ветвление)\n dependencies.delete(dep)\n const rawDepNode = dep._node || dep\n if (rawDepNode.subscribers) rawDepNode.subscribers.delete(computedNode)\n depVersions.delete(dep)\n }\n }\n }\n\n const changed = isDirty || !Object.is(value, newValue)\n\n if (changed) {\n const previousValueSnapshot = isDirty ? undefined : (typeof value === 'object' && value !== null ? JSON.parse(JSON.stringify(value)) : value)\n value = newValue\n version++\n\n if (engine.log && signalName) {\n engine.log({\n type: 'computed',\n label: signalName,\n details: { from: previousValueSnapshot, to: newValue }\n })\n }\n\n for (const sub of subscribers) {\n const rawSub = sub._node || sub\n if (rawSub.type === 'effect') {\n rawSub.state = 2\n rawSub.isDirty = true\n engine.scheduleEffect(sub)\n } else if (rawSub.markDirty) {\n rawSub.markDirty(1)\n }\n }\n }\n\n isDirty = false\n state = 0\n isInitialized = true\n\n let maxDepDepth = 0\n for (const unknownDep of dependencies) {\n const dep = unknownDep as any\n const rawNode = dep._node || dep\n depVersions.set(dep, rawNode.version)\n if (rawNode.subscribers) rawNode.subscribers.add(computedNode)\n if (rawNode.depth !== undefined && rawNode.depth > maxDepDepth) {\n maxDepDepth = rawNode.depth\n }\n }\n\n for (const sub of subscribers) {\n const rawSub = sub._node || sub\n if (rawSub.type === 'effect') {\n rawSub.state = 2\n rawSub.isDirty = true\n engine.scheduleEffect(sub)\n } else if (rawSub.markDirty) {\n rawSub.markDirty(1)\n }\n }\n\n computedNode.depth = maxDepDepth + 1\n return changed\n } finally {\n engine.activeConsumer = prevConsumer\n engine.activeOwner = prevOwner\n engine.cycleDetectionStack.delete(computedNode)\n }\n },\n markDirty: (parentState: number) => {\n if (state >= parentState) return\n state = parentState\n\n for (const sub of subscribers) {\n const rawSub = sub._node || sub\n if (rawSub.type === 'effect') {\n rawSub.isDirty = true\n engine.scheduleEffect(sub)\n } else if (rawSub.markDirty) {\n rawSub.markDirty(1)\n }\n }\n }\n }\n\n const computedInstance: Computed<T> = {\n get value() {\n const consumer = engine.activeConsumer\n if (consumer && consumer !== computedNode) {\n computedNode.subscribers.add(consumer)\n consumer.dependencies.add(computedNode)\n\n // ⚡ Маркерная эпоха (Zero-Allocation Track)\n if (consumer.activeRunId !== undefined) {\n computedNode._lastSeenInRunId = consumer.activeRunId\n }\n }\n\n updateIfNecessary(computedNode)\n\n // Оптимизация: используем локальную ссылку consumer вместо повторного обращения к engine\n if (consumer && consumer.depVersions) {\n consumer.depVersions.set(computedInstance, version)\n }\n return value\n },\n get valueWithoutTracking() { return value },\n get version() { return version },\n subscribe(cb: (val: T) => void): CleanupFn {\n const fakeEffect: any = {\n id: engine.subscriberId++,\n isDirty: true,\n depth: 9999,\n dependencies: new Set(),\n type: 'effect',\n run: () => {\n if (fakeEffect.isDisposed) return\n try { cb(computedInstance.value) } catch (err) { console.error(err) }\n }\n }\n computedNode.subscribers.add(fakeEffect)\n cb(computedInstance.value)\n return () => {\n fakeEffect.isDisposed = true\n computedNode.subscribers.delete(fakeEffect)\n }\n },\n subscribeState(cb: () => void): CleanupFn {\n return (computedInstance as any).subscribe(cb)\n },\n destroy: () => {\n computedNode.subscribers.clear()\n releaseNode(computedNode)\n engine.computedCache.delete(fn)\n isDirty = true\n state = 2\n isInitialized = false\n },\n __subscribe(cb: () => void): CleanupFn {\n const hookEffect: any = {\n id: engine.subscriberId++,\n type: 'effect',\n run: cb,\n isDirty: false\n }\n computedNode.subscribers.add(hookEffect)\n return () => {\n subscribers.delete(hookEffect)\n }\n }\n } as any\n\n ;(computedInstance as any)._node = computedNode\n ;(computedInstance as any).subscribers = subscribers\n ;(computedInstance as any).dependencies = dependencies\n computedInstance._isDirty = () => state > 0\n computedInstance.type = 'computed'\n computedInstance.run = () => computedNode.run()\n\n engine.computedCache.set(fn, computedInstance)\n return computedInstance\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- const e=require("./utils/getExtractedValues.cjs");function t(t,n,r){let i=n,a=0,o=typeof r==`string`?r:r?.name,s=!!o&&e.getExtractedValues({tested:[o],expectedKey:`CORE_INTERNAL_SIGNAL`,valueType:`number`})?.[0]===`1`||!1,c=new Set,l=!1,u=n,d={type:`signal`,get version(){return a},subscribers:c},f=()=>{for(let e of c){let n=e._node||e;if(n.type===`effect`)n.isDirty=!0,t.scheduleEffect(e);else if(n.type===`computed`)n.markDirty&&n.markDirty(2);else if(typeof e==`function`)try{e(i)}catch(e){console.error(e)}else if(e&&typeof e.run==`function`)try{e.run()}catch(e){console.error(e)}}},p={get value(){return t.activeConsumer&&(c.add(t.activeConsumer),t.activeConsumer.dependencies.add(p)),i},set value(e){if(Object.is(i,e)&&!(i===e&&typeof i==`object`&&i))return;if(r&&typeof r==`object`&&r.validate){let t=r.validate(e);if(t!==!0){console.error(typeof t==`string`?t:`[Validation Error]`);return}}if(t.batchDepth>0){l||(l=!0,u=i),i=e,t.batchedSignals.add(p);return}let n=i;i=e,a++,t.epoch++,t.log({type:`signal`,label:o||`signal`,details:{from:n,to:e},isInternalCoreSignal:s}),f(),t.batchDepth===0&&t.flushEffects()},get version(){return a},type:`signal`,subscribe(e){return c.add(e),e(i),()=>{c.delete(e)}},_flushBatch:()=>{l&&((!Object.is(u,i)||typeof i==`object`&&i)&&(a++,t.epoch++,t.log({type:`signal`,label:o||`signal_batched`,details:{from:u,to:i},isInternalCoreSignal:s}),f()),l=!1,u=i)}};return p._node=d,p.subscribers=c,p}exports.createSignal=t;
1
+ const e=require("./utils/getExtractedValues.cjs");function t(t,n,r){let i=n,a=0,o=typeof r==`string`?r:r?.name,s=!!o&&e.getExtractedValues({tested:[o],expectedKey:`CORE_INTERNAL_SIGNAL`,valueType:`number`})?.[0]===`1`||!1,c=new Set,l=!1,u=n,d={type:`signal`,get version(){return a},subscribers:c},f=()=>{for(let e of c){let n=e._node||e;if(n.type===`effect`)n.isDirty=!0,t.scheduleEffect(e);else if(n.type===`computed`)n.markDirty&&n.markDirty(2);else if(typeof e==`function`)try{e(i)}catch(e){console.error(e)}else if(e&&typeof e.run==`function`)try{e.run()}catch(e){console.error(e)}}},p={get value(){let e=t.activeConsumer;return e&&(c.add(t.activeConsumer),t.activeConsumer.dependencies.add(p),e.activeRunId!==void 0&&(p._lastSeenInRunId=e.activeRunId)),i},set value(e){if(Object.is(i,e)&&!(i===e&&typeof i==`object`&&i))return;if(r&&typeof r==`object`&&r.validate){let t=r.validate(e);if(t!==!0){console.error(typeof t==`string`?t:`[Validation Error]`);return}}if(t.batchDepth>0){l||(l=!0,u=i),i=e,t.batchedSignals.add(p);return}let n=i;i=e,a++,t.epoch++,t.log({type:`signal`,label:o||`signal`,details:{from:n,to:e},isInternalCoreSignal:s}),f(),t.batchDepth===0&&t.flushEffects()},get version(){return a},type:`signal`,subscribe(e){return c.add(e),e(i),()=>{c.delete(e)}},_flushBatch:()=>{l&&((!Object.is(u,i)||typeof i==`object`&&i)&&(a++,t.epoch++,t.log({type:`signal`,label:o||`signal_batched`,details:{from:u,to:i},isInternalCoreSignal:s}),f()),l=!1,u=i)}};return p._node=d,p.subscribers=c,p}exports.createSignal=t;
2
2
  //# sourceMappingURL=core.method.signal.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"core.method.signal.cjs","names":[],"sources":["../src/core/core.method.signal.ts"],"sourcesContent":["import { getExtractedValues } from '../utils/getExtractedValues'\nimport { Signal, SignalOptions } from './types'\n\nexport function createSignal<T>(\n engine: any,\n initialValue: T,\n optionsOrName?: SignalOptions<T> | string\n): Signal<T> {\n let value = initialValue\n let version = 0\n let name = typeof optionsOrName === 'string' ? optionsOrName : optionsOrName?.name\n const isInternalCoreSignal = !!name && getExtractedValues({\n tested: [name],\n expectedKey: 'CORE_INTERNAL_SIGNAL',\n valueType: 'number',\n })?.[0] === '1' || false\n const subscribers = new Set<any>()\n\n let hasBatchValue = false\n let batchInitialValue: T = initialValue\n\n const signalNode = {\n type: 'signal',\n get version() { return version },\n subscribers\n }\n\n const notifySubscribers = () => {\n // ⚡ ОПТИМИЗАЦИЯ: Прямой проход по Set через for...of (без Array.from)\n for (const sub of subscribers) {\n const rawSub = sub._node || sub\n if (rawSub.type === 'effect') {\n rawSub.isDirty = true\n engine.scheduleEffect(sub)\n } else if (rawSub.type === 'computed') {\n if (rawSub.markDirty) rawSub.markDirty(2)\n } else {\n if (typeof sub === 'function') {\n try { sub(value) } catch (err) { console.error(err) }\n } else if (sub && typeof sub.run === 'function') {\n try { sub.run() } catch (err) { console.error(err) }\n }\n }\n }\n }\n\n const signalInstance: Signal<T> = {\n get value() {\n if (engine.activeConsumer) {\n subscribers.add(engine.activeConsumer)\n engine.activeConsumer.dependencies.add(signalInstance)\n }\n return value\n },\n\n set value(newValue: T) {\n const isObjectKick = value === newValue && value !== null && typeof value === 'object'\n if (Object.is(value, newValue) && !isObjectKick) return\n\n if (optionsOrName && typeof optionsOrName === 'object' && optionsOrName.validate) {\n const validation = optionsOrName.validate(newValue)\n if (validation !== true) {\n console.error(typeof validation === 'string' ? validation : '[Validation Error]')\n return\n }\n }\n\n if (engine.batchDepth > 0) {\n if (!hasBatchValue) {\n hasBatchValue = true\n batchInitialValue = value\n }\n value = newValue\n engine.batchedSignals.add(signalInstance)\n return\n }\n\n const oldValue = value\n value = newValue\n\n version++\n engine.epoch++\n\n engine.log({\n type: 'signal',\n label: name || 'signal',\n details: { from: oldValue, to: newValue },\n isInternalCoreSignal\n })\n\n notifySubscribers()\n if (engine.batchDepth === 0) engine.flushEffects()\n },\n\n get version() { return version },\n type: 'signal',\n\n subscribe(cb: (val: T) => void) {\n subscribers.add(cb)\n cb(value)\n return () => { subscribers.delete(cb) }\n },\n\n _flushBatch: () => {\n if (!hasBatchValue) return\n\n const wasChanged = !Object.is(batchInitialValue, value) || (value !== null && typeof value === 'object')\n\n if (wasChanged) {\n version++\n engine.epoch++\n\n engine.log({\n type: 'signal',\n label: name || 'signal_batched',\n details: { from: batchInitialValue, to: value },\n isInternalCoreSignal\n })\n\n notifySubscribers()\n }\n\n hasBatchValue = false\n batchInitialValue = value\n }\n } as any\n\n ;(signalInstance as any)._node = signalNode\n ;(signalInstance as any).subscribers = subscribers\n return signalInstance\n}\n"],"mappings":"kDAGA,SAAgB,EACd,EACA,EACA,EACW,CACX,IAAI,EAAQ,EACR,EAAU,EACV,EAAO,OAAO,GAAkB,SAAW,EAAgB,GAAe,KACxE,EAAuB,CAAC,CAAC,GAAQ,EAAA,mBAAmB,CACxD,OAAQ,CAAC,CAAI,EACb,YAAa,uBACb,UAAW,QACb,CAAC,CAAC,GAAG,KAAO,KAAO,GACb,EAAc,IAAI,IAEpB,EAAgB,GAChB,EAAuB,EAErB,EAAa,CACjB,KAAM,SACN,IAAI,SAAU,CAAE,OAAO,CAAQ,EAC/B,aACF,EAEM,MAA0B,CAE9B,IAAK,IAAM,KAAO,EAAa,CAC7B,IAAM,EAAS,EAAI,OAAS,EAC5B,GAAI,EAAO,OAAS,SAClB,EAAO,QAAU,GACjB,EAAO,eAAe,CAAG,OACpB,GAAI,EAAO,OAAS,WACrB,EAAO,WAAW,EAAO,UAAU,CAAC,OAExC,GAAI,OAAO,GAAQ,WACjB,GAAI,CAAE,EAAI,CAAK,CAAE,OAAS,EAAK,CAAE,QAAQ,MAAM,CAAG,CAAE,MAC/C,GAAI,GAAO,OAAO,EAAI,KAAQ,WACnC,GAAI,CAAE,EAAI,IAAI,CAAE,OAAS,EAAK,CAAE,QAAQ,MAAM,CAAG,CAAE,CAGzD,CACF,EAEM,EAA4B,CAChC,IAAI,OAAQ,CAKV,OAJI,EAAO,iBACT,EAAY,IAAI,EAAO,cAAc,EACrC,EAAO,eAAe,aAAa,IAAI,CAAc,GAEhD,CACT,EAEA,IAAI,MAAM,EAAa,CAErB,GAAI,OAAO,GAAG,EAAO,CAAQ,GAAK,EADb,IAAU,GAA8B,OAAO,GAAU,UAAnC,GACM,OAEjD,GAAI,GAAiB,OAAO,GAAkB,UAAY,EAAc,SAAU,CAChF,IAAM,EAAa,EAAc,SAAS,CAAQ,EAClD,GAAI,IAAe,GAAM,CACvB,QAAQ,MAAM,OAAO,GAAe,SAAW,EAAa,oBAAoB,EAChF,MACF,CACF,CAEA,GAAI,EAAO,WAAa,EAAG,CACpB,IACH,EAAgB,GAChB,EAAoB,GAEtB,EAAQ,EACR,EAAO,eAAe,IAAI,CAAc,EACxC,MACF,CAEA,IAAM,EAAW,EACjB,EAAQ,EAER,IACA,EAAO,QAEP,EAAO,IAAI,CACT,KAAM,SACN,MAAO,GAAQ,SACf,QAAS,CAAE,KAAM,EAAU,GAAI,CAAS,EACxC,sBACF,CAAC,EAED,EAAkB,EACd,EAAO,aAAe,GAAG,EAAO,aAAa,CACnD,EAEA,IAAI,SAAU,CAAE,OAAO,CAAQ,EAC/B,KAAM,SAEN,UAAU,EAAsB,CAG9B,OAFA,EAAY,IAAI,CAAE,EAClB,EAAG,CAAK,MACK,CAAE,EAAY,OAAO,CAAE,CAAE,CACxC,EAEA,gBAAmB,CACZ,KAEc,CAAC,OAAO,GAAG,EAAmB,CAAK,GAAwB,OAAO,GAAU,UAAnC,KAG1D,IACA,EAAO,QAEP,EAAO,IAAI,CACT,KAAM,SACN,MAAO,GAAQ,iBACf,QAAS,CAAE,KAAM,EAAmB,GAAI,CAAM,EAC9C,sBACF,CAAC,EAED,EAAkB,GAGpB,EAAgB,GAChB,EAAoB,EACtB,CACF,EAIA,MAFC,GAAwB,MAAQ,EAChC,EAAwB,YAAc,EAChC,CACT"}
1
+ {"version":3,"file":"core.method.signal.cjs","names":[],"sources":["../src/core/core.method.signal.ts"],"sourcesContent":["import { getExtractedValues } from '../utils/getExtractedValues'\nimport { Signal, SignalOptions } from './types'\n\nexport function createSignal<T>(\n engine: any,\n initialValue: T,\n optionsOrName?: SignalOptions<T> | string\n): Signal<T> {\n let value = initialValue\n let version = 0\n let name = typeof optionsOrName === 'string' ? optionsOrName : optionsOrName?.name\n const isInternalCoreSignal = !!name && getExtractedValues({\n tested: [name],\n expectedKey: 'CORE_INTERNAL_SIGNAL',\n valueType: 'number',\n })?.[0] === '1' || false\n const subscribers = new Set<any>()\n\n let hasBatchValue = false\n let batchInitialValue: T = initialValue\n\n const signalNode = {\n type: 'signal',\n get version() { return version },\n subscribers\n }\n\n const notifySubscribers = () => {\n // ⚡ ОПТИМИЗАЦИЯ: Прямой проход по Set через for...of (без Array.from)\n for (const sub of subscribers) {\n const rawSub = sub._node || sub\n if (rawSub.type === 'effect') {\n rawSub.isDirty = true\n engine.scheduleEffect(sub)\n } else if (rawSub.type === 'computed') {\n if (rawSub.markDirty) rawSub.markDirty(2)\n } else {\n if (typeof sub === 'function') {\n try { sub(value) } catch (err) { console.error(err) }\n } else if (sub && typeof sub.run === 'function') {\n try { sub.run() } catch (err) { console.error(err) }\n }\n }\n }\n }\n\n const signalInstance: Signal<T> = {\n get value() {\n const consumer = engine.activeConsumer\n if (consumer) {\n subscribers.add(engine.activeConsumer)\n engine.activeConsumer.dependencies.add(signalInstance)\n\n // Запоминаем маркер: этот сигнал активен в текущем расчете consumer-а\n if (consumer.activeRunId !== undefined) {\n (signalInstance as any)._lastSeenInRunId = consumer.activeRunId\n }\n }\n return value\n },\n\n set value(newValue: T) {\n const isObjectKick = value === newValue && value !== null && typeof value === 'object'\n if (Object.is(value, newValue) && !isObjectKick) return\n\n if (optionsOrName && typeof optionsOrName === 'object' && optionsOrName.validate) {\n const validation = optionsOrName.validate(newValue)\n if (validation !== true) {\n console.error(typeof validation === 'string' ? validation : '[Validation Error]')\n return\n }\n }\n\n if (engine.batchDepth > 0) {\n if (!hasBatchValue) {\n hasBatchValue = true\n batchInitialValue = value\n }\n value = newValue\n engine.batchedSignals.add(signalInstance)\n return\n }\n\n const oldValue = value\n value = newValue\n\n version++\n engine.epoch++\n\n engine.log({\n type: 'signal',\n label: name || 'signal',\n details: { from: oldValue, to: newValue },\n isInternalCoreSignal\n })\n\n notifySubscribers()\n if (engine.batchDepth === 0) engine.flushEffects()\n },\n\n get version() { return version },\n type: 'signal',\n\n subscribe(cb: (val: T) => void) {\n subscribers.add(cb)\n cb(value)\n return () => { subscribers.delete(cb) }\n },\n\n _flushBatch: () => {\n if (!hasBatchValue) return\n\n const wasChanged = !Object.is(batchInitialValue, value) || (value !== null && typeof value === 'object')\n\n if (wasChanged) {\n version++\n engine.epoch++\n\n engine.log({\n type: 'signal',\n label: name || 'signal_batched',\n details: { from: batchInitialValue, to: value },\n isInternalCoreSignal\n })\n\n notifySubscribers()\n }\n\n hasBatchValue = false\n batchInitialValue = value\n }\n } as any\n\n ;(signalInstance as any)._node = signalNode\n ;(signalInstance as any).subscribers = subscribers\n return signalInstance\n}\n"],"mappings":"kDAGA,SAAgB,EACd,EACA,EACA,EACW,CACX,IAAI,EAAQ,EACR,EAAU,EACV,EAAO,OAAO,GAAkB,SAAW,EAAgB,GAAe,KACxE,EAAuB,CAAC,CAAC,GAAQ,EAAA,mBAAmB,CACxD,OAAQ,CAAC,CAAI,EACb,YAAa,uBACb,UAAW,QACb,CAAC,CAAC,GAAG,KAAO,KAAO,GACb,EAAc,IAAI,IAEpB,EAAgB,GAChB,EAAuB,EAErB,EAAa,CACjB,KAAM,SACN,IAAI,SAAU,CAAE,OAAO,CAAQ,EAC/B,aACF,EAEM,MAA0B,CAE9B,IAAK,IAAM,KAAO,EAAa,CAC7B,IAAM,EAAS,EAAI,OAAS,EAC5B,GAAI,EAAO,OAAS,SAClB,EAAO,QAAU,GACjB,EAAO,eAAe,CAAG,OACpB,GAAI,EAAO,OAAS,WACrB,EAAO,WAAW,EAAO,UAAU,CAAC,OAExC,GAAI,OAAO,GAAQ,WACjB,GAAI,CAAE,EAAI,CAAK,CAAE,OAAS,EAAK,CAAE,QAAQ,MAAM,CAAG,CAAE,MAC/C,GAAI,GAAO,OAAO,EAAI,KAAQ,WACnC,GAAI,CAAE,EAAI,IAAI,CAAE,OAAS,EAAK,CAAE,QAAQ,MAAM,CAAG,CAAE,CAGzD,CACF,EAEM,EAA4B,CAChC,IAAI,OAAQ,CACV,IAAM,EAAW,EAAO,eAUxB,OATI,IACF,EAAY,IAAI,EAAO,cAAc,EACrC,EAAO,eAAe,aAAa,IAAI,CAAc,EAGjD,EAAS,cAAgB,IAAA,KAC3B,EAAwB,iBAAmB,EAAS,cAGjD,CACT,EAEA,IAAI,MAAM,EAAa,CAErB,GAAI,OAAO,GAAG,EAAO,CAAQ,GAAK,EADb,IAAU,GAA8B,OAAO,GAAU,UAAnC,GACM,OAEjD,GAAI,GAAiB,OAAO,GAAkB,UAAY,EAAc,SAAU,CAChF,IAAM,EAAa,EAAc,SAAS,CAAQ,EAClD,GAAI,IAAe,GAAM,CACvB,QAAQ,MAAM,OAAO,GAAe,SAAW,EAAa,oBAAoB,EAChF,MACF,CACF,CAEA,GAAI,EAAO,WAAa,EAAG,CACpB,IACH,EAAgB,GAChB,EAAoB,GAEtB,EAAQ,EACR,EAAO,eAAe,IAAI,CAAc,EACxC,MACF,CAEA,IAAM,EAAW,EACjB,EAAQ,EAER,IACA,EAAO,QAEP,EAAO,IAAI,CACT,KAAM,SACN,MAAO,GAAQ,SACf,QAAS,CAAE,KAAM,EAAU,GAAI,CAAS,EACxC,sBACF,CAAC,EAED,EAAkB,EACd,EAAO,aAAe,GAAG,EAAO,aAAa,CACnD,EAEA,IAAI,SAAU,CAAE,OAAO,CAAQ,EAC/B,KAAM,SAEN,UAAU,EAAsB,CAG9B,OAFA,EAAY,IAAI,CAAE,EAClB,EAAG,CAAK,MACK,CAAE,EAAY,OAAO,CAAE,CAAE,CACxC,EAEA,gBAAmB,CACZ,KAEc,CAAC,OAAO,GAAG,EAAmB,CAAK,GAAwB,OAAO,GAAU,UAAnC,KAG1D,IACA,EAAO,QAEP,EAAO,IAAI,CACT,KAAM,SACN,MAAO,GAAQ,iBACf,QAAS,CAAE,KAAM,EAAmB,GAAI,CAAM,EAC9C,sBACF,CAAC,EAED,EAAkB,GAGpB,EAAgB,GAChB,EAAoB,EACtB,CACF,EAIA,MAFC,GAAwB,MAAQ,EAChC,EAAwB,YAAc,EAChC,CACT"}
@@ -29,7 +29,8 @@ function t(t, n, r) {
29
29
  }
30
30
  }, p = {
31
31
  get value() {
32
- return t.activeConsumer && (c.add(t.activeConsumer), t.activeConsumer.dependencies.add(p)), i;
32
+ let e = t.activeConsumer;
33
+ return e && (c.add(t.activeConsumer), t.activeConsumer.dependencies.add(p), e.activeRunId !== void 0 && (p._lastSeenInRunId = e.activeRunId)), i;
33
34
  },
34
35
  set value(e) {
35
36
  if (Object.is(i, e) && !(i === e && typeof i == "object" && i)) return;
@@ -1 +1 @@
1
- {"version":3,"file":"core.method.signal.mjs","names":[],"sources":["../src/core/core.method.signal.ts"],"sourcesContent":["import { getExtractedValues } from '../utils/getExtractedValues'\nimport { Signal, SignalOptions } from './types'\n\nexport function createSignal<T>(\n engine: any,\n initialValue: T,\n optionsOrName?: SignalOptions<T> | string\n): Signal<T> {\n let value = initialValue\n let version = 0\n let name = typeof optionsOrName === 'string' ? optionsOrName : optionsOrName?.name\n const isInternalCoreSignal = !!name && getExtractedValues({\n tested: [name],\n expectedKey: 'CORE_INTERNAL_SIGNAL',\n valueType: 'number',\n })?.[0] === '1' || false\n const subscribers = new Set<any>()\n\n let hasBatchValue = false\n let batchInitialValue: T = initialValue\n\n const signalNode = {\n type: 'signal',\n get version() { return version },\n subscribers\n }\n\n const notifySubscribers = () => {\n // ⚡ ОПТИМИЗАЦИЯ: Прямой проход по Set через for...of (без Array.from)\n for (const sub of subscribers) {\n const rawSub = sub._node || sub\n if (rawSub.type === 'effect') {\n rawSub.isDirty = true\n engine.scheduleEffect(sub)\n } else if (rawSub.type === 'computed') {\n if (rawSub.markDirty) rawSub.markDirty(2)\n } else {\n if (typeof sub === 'function') {\n try { sub(value) } catch (err) { console.error(err) }\n } else if (sub && typeof sub.run === 'function') {\n try { sub.run() } catch (err) { console.error(err) }\n }\n }\n }\n }\n\n const signalInstance: Signal<T> = {\n get value() {\n if (engine.activeConsumer) {\n subscribers.add(engine.activeConsumer)\n engine.activeConsumer.dependencies.add(signalInstance)\n }\n return value\n },\n\n set value(newValue: T) {\n const isObjectKick = value === newValue && value !== null && typeof value === 'object'\n if (Object.is(value, newValue) && !isObjectKick) return\n\n if (optionsOrName && typeof optionsOrName === 'object' && optionsOrName.validate) {\n const validation = optionsOrName.validate(newValue)\n if (validation !== true) {\n console.error(typeof validation === 'string' ? validation : '[Validation Error]')\n return\n }\n }\n\n if (engine.batchDepth > 0) {\n if (!hasBatchValue) {\n hasBatchValue = true\n batchInitialValue = value\n }\n value = newValue\n engine.batchedSignals.add(signalInstance)\n return\n }\n\n const oldValue = value\n value = newValue\n\n version++\n engine.epoch++\n\n engine.log({\n type: 'signal',\n label: name || 'signal',\n details: { from: oldValue, to: newValue },\n isInternalCoreSignal\n })\n\n notifySubscribers()\n if (engine.batchDepth === 0) engine.flushEffects()\n },\n\n get version() { return version },\n type: 'signal',\n\n subscribe(cb: (val: T) => void) {\n subscribers.add(cb)\n cb(value)\n return () => { subscribers.delete(cb) }\n },\n\n _flushBatch: () => {\n if (!hasBatchValue) return\n\n const wasChanged = !Object.is(batchInitialValue, value) || (value !== null && typeof value === 'object')\n\n if (wasChanged) {\n version++\n engine.epoch++\n\n engine.log({\n type: 'signal',\n label: name || 'signal_batched',\n details: { from: batchInitialValue, to: value },\n isInternalCoreSignal\n })\n\n notifySubscribers()\n }\n\n hasBatchValue = false\n batchInitialValue = value\n }\n } as any\n\n ;(signalInstance as any)._node = signalNode\n ;(signalInstance as any).subscribers = subscribers\n return signalInstance\n}\n"],"mappings":";;AAGA,SAAgB,EACd,GACA,GACA,GACW;CACX,IAAI,IAAQ,GACR,IAAU,GACV,IAAO,OAAO,KAAkB,WAAW,IAAgB,GAAe,MACxE,IAAuB,CAAC,CAAC,KAAQ,EAAmB;EACxD,QAAQ,CAAC,CAAI;EACb,aAAa;EACb,WAAW;CACb,CAAC,CAAC,GAAG,OAAO,OAAO,IACb,oBAAc,IAAI,IAAS,GAE7B,IAAgB,IAChB,IAAuB,GAErB,IAAa;EACjB,MAAM;EACN,IAAI,UAAU;GAAE,OAAO;EAAQ;EAC/B;CACF,GAEM,UAA0B;EAE9B,KAAK,IAAM,KAAO,GAAa;GAC7B,IAAM,IAAS,EAAI,SAAS;GAC5B,IAAI,EAAO,SAAS,UAElB,AADA,EAAO,UAAU,IACjB,EAAO,eAAe,CAAG;QACpB,IAAI,EAAO,SAAS,YACrB,EAAO,aAAW,EAAO,UAAU,CAAC;QAExC,IAAI,OAAO,KAAQ,YACjB,IAAI;IAAE,EAAI,CAAK;GAAE,SAAS,GAAK;IAAE,QAAQ,MAAM,CAAG;GAAE;QAC/C,IAAI,KAAO,OAAO,EAAI,OAAQ,YACnC,IAAI;IAAE,EAAI,IAAI;GAAE,SAAS,GAAK;IAAE,QAAQ,MAAM,CAAG;GAAE;EAGzD;CACF,GAEM,IAA4B;EAChC,IAAI,QAAQ;GAKV,OAJI,EAAO,mBACT,EAAY,IAAI,EAAO,cAAc,GACrC,EAAO,eAAe,aAAa,IAAI,CAAc,IAEhD;EACT;EAEA,IAAI,MAAM,GAAa;GAErB,IAAI,OAAO,GAAG,GAAO,CAAQ,KAAK,EADb,MAAU,KAA8B,OAAO,KAAU,YAAnC,IACM;GAEjD,IAAI,KAAiB,OAAO,KAAkB,YAAY,EAAc,UAAU;IAChF,IAAM,IAAa,EAAc,SAAS,CAAQ;IAClD,IAAI,MAAe,IAAM;KACvB,QAAQ,MAAM,OAAO,KAAe,WAAW,IAAa,oBAAoB;KAChF;IACF;GACF;GAEA,IAAI,EAAO,aAAa,GAAG;IAMzB,AALK,MACH,IAAgB,IAChB,IAAoB,IAEtB,IAAQ,GACR,EAAO,eAAe,IAAI,CAAc;IACxC;GACF;GAEA,IAAM,IAAW;GAcjB,AAbA,IAAQ,GAER,KACA,EAAO,SAEP,EAAO,IAAI;IACT,MAAM;IACN,OAAO,KAAQ;IACf,SAAS;KAAE,MAAM;KAAU,IAAI;IAAS;IACxC;GACF,CAAC,GAED,EAAkB,GACd,EAAO,eAAe,KAAG,EAAO,aAAa;EACnD;EAEA,IAAI,UAAU;GAAE,OAAO;EAAQ;EAC/B,MAAM;EAEN,UAAU,GAAsB;GAG9B,OAFA,EAAY,IAAI,CAAE,GAClB,EAAG,CAAK,SACK;IAAE,EAAY,OAAO,CAAE;GAAE;EACxC;EAEA,mBAAmB;GACZ,OAEc,CAAC,OAAO,GAAG,GAAmB,CAAK,KAAwB,OAAO,KAAU,YAAnC,OAG1D,KACA,EAAO,SAEP,EAAO,IAAI;IACT,MAAM;IACN,OAAO,KAAQ;IACf,SAAS;KAAE,MAAM;KAAmB,IAAI;IAAM;IAC9C;GACF,CAAC,GAED,EAAkB,IAGpB,IAAgB,IAChB,IAAoB;EACtB;CACF;CAIA,OAFC,EAAwB,QAAQ,GAChC,EAAwB,cAAc,GAChC;AACT"}
1
+ {"version":3,"file":"core.method.signal.mjs","names":[],"sources":["../src/core/core.method.signal.ts"],"sourcesContent":["import { getExtractedValues } from '../utils/getExtractedValues'\nimport { Signal, SignalOptions } from './types'\n\nexport function createSignal<T>(\n engine: any,\n initialValue: T,\n optionsOrName?: SignalOptions<T> | string\n): Signal<T> {\n let value = initialValue\n let version = 0\n let name = typeof optionsOrName === 'string' ? optionsOrName : optionsOrName?.name\n const isInternalCoreSignal = !!name && getExtractedValues({\n tested: [name],\n expectedKey: 'CORE_INTERNAL_SIGNAL',\n valueType: 'number',\n })?.[0] === '1' || false\n const subscribers = new Set<any>()\n\n let hasBatchValue = false\n let batchInitialValue: T = initialValue\n\n const signalNode = {\n type: 'signal',\n get version() { return version },\n subscribers\n }\n\n const notifySubscribers = () => {\n // ⚡ ОПТИМИЗАЦИЯ: Прямой проход по Set через for...of (без Array.from)\n for (const sub of subscribers) {\n const rawSub = sub._node || sub\n if (rawSub.type === 'effect') {\n rawSub.isDirty = true\n engine.scheduleEffect(sub)\n } else if (rawSub.type === 'computed') {\n if (rawSub.markDirty) rawSub.markDirty(2)\n } else {\n if (typeof sub === 'function') {\n try { sub(value) } catch (err) { console.error(err) }\n } else if (sub && typeof sub.run === 'function') {\n try { sub.run() } catch (err) { console.error(err) }\n }\n }\n }\n }\n\n const signalInstance: Signal<T> = {\n get value() {\n const consumer = engine.activeConsumer\n if (consumer) {\n subscribers.add(engine.activeConsumer)\n engine.activeConsumer.dependencies.add(signalInstance)\n\n // Запоминаем маркер: этот сигнал активен в текущем расчете consumer-а\n if (consumer.activeRunId !== undefined) {\n (signalInstance as any)._lastSeenInRunId = consumer.activeRunId\n }\n }\n return value\n },\n\n set value(newValue: T) {\n const isObjectKick = value === newValue && value !== null && typeof value === 'object'\n if (Object.is(value, newValue) && !isObjectKick) return\n\n if (optionsOrName && typeof optionsOrName === 'object' && optionsOrName.validate) {\n const validation = optionsOrName.validate(newValue)\n if (validation !== true) {\n console.error(typeof validation === 'string' ? validation : '[Validation Error]')\n return\n }\n }\n\n if (engine.batchDepth > 0) {\n if (!hasBatchValue) {\n hasBatchValue = true\n batchInitialValue = value\n }\n value = newValue\n engine.batchedSignals.add(signalInstance)\n return\n }\n\n const oldValue = value\n value = newValue\n\n version++\n engine.epoch++\n\n engine.log({\n type: 'signal',\n label: name || 'signal',\n details: { from: oldValue, to: newValue },\n isInternalCoreSignal\n })\n\n notifySubscribers()\n if (engine.batchDepth === 0) engine.flushEffects()\n },\n\n get version() { return version },\n type: 'signal',\n\n subscribe(cb: (val: T) => void) {\n subscribers.add(cb)\n cb(value)\n return () => { subscribers.delete(cb) }\n },\n\n _flushBatch: () => {\n if (!hasBatchValue) return\n\n const wasChanged = !Object.is(batchInitialValue, value) || (value !== null && typeof value === 'object')\n\n if (wasChanged) {\n version++\n engine.epoch++\n\n engine.log({\n type: 'signal',\n label: name || 'signal_batched',\n details: { from: batchInitialValue, to: value },\n isInternalCoreSignal\n })\n\n notifySubscribers()\n }\n\n hasBatchValue = false\n batchInitialValue = value\n }\n } as any\n\n ;(signalInstance as any)._node = signalNode\n ;(signalInstance as any).subscribers = subscribers\n return signalInstance\n}\n"],"mappings":";;AAGA,SAAgB,EACd,GACA,GACA,GACW;CACX,IAAI,IAAQ,GACR,IAAU,GACV,IAAO,OAAO,KAAkB,WAAW,IAAgB,GAAe,MACxE,IAAuB,CAAC,CAAC,KAAQ,EAAmB;EACxD,QAAQ,CAAC,CAAI;EACb,aAAa;EACb,WAAW;CACb,CAAC,CAAC,GAAG,OAAO,OAAO,IACb,oBAAc,IAAI,IAAS,GAE7B,IAAgB,IAChB,IAAuB,GAErB,IAAa;EACjB,MAAM;EACN,IAAI,UAAU;GAAE,OAAO;EAAQ;EAC/B;CACF,GAEM,UAA0B;EAE9B,KAAK,IAAM,KAAO,GAAa;GAC7B,IAAM,IAAS,EAAI,SAAS;GAC5B,IAAI,EAAO,SAAS,UAElB,AADA,EAAO,UAAU,IACjB,EAAO,eAAe,CAAG;QACpB,IAAI,EAAO,SAAS,YACrB,EAAO,aAAW,EAAO,UAAU,CAAC;QAExC,IAAI,OAAO,KAAQ,YACjB,IAAI;IAAE,EAAI,CAAK;GAAE,SAAS,GAAK;IAAE,QAAQ,MAAM,CAAG;GAAE;QAC/C,IAAI,KAAO,OAAO,EAAI,OAAQ,YACnC,IAAI;IAAE,EAAI,IAAI;GAAE,SAAS,GAAK;IAAE,QAAQ,MAAM,CAAG;GAAE;EAGzD;CACF,GAEM,IAA4B;EAChC,IAAI,QAAQ;GACV,IAAM,IAAW,EAAO;GAUxB,OATI,MACF,EAAY,IAAI,EAAO,cAAc,GACrC,EAAO,eAAe,aAAa,IAAI,CAAc,GAGjD,EAAS,gBAAgB,KAAA,MAC3B,EAAwB,mBAAmB,EAAS,eAGjD;EACT;EAEA,IAAI,MAAM,GAAa;GAErB,IAAI,OAAO,GAAG,GAAO,CAAQ,KAAK,EADb,MAAU,KAA8B,OAAO,KAAU,YAAnC,IACM;GAEjD,IAAI,KAAiB,OAAO,KAAkB,YAAY,EAAc,UAAU;IAChF,IAAM,IAAa,EAAc,SAAS,CAAQ;IAClD,IAAI,MAAe,IAAM;KACvB,QAAQ,MAAM,OAAO,KAAe,WAAW,IAAa,oBAAoB;KAChF;IACF;GACF;GAEA,IAAI,EAAO,aAAa,GAAG;IAMzB,AALK,MACH,IAAgB,IAChB,IAAoB,IAEtB,IAAQ,GACR,EAAO,eAAe,IAAI,CAAc;IACxC;GACF;GAEA,IAAM,IAAW;GAcjB,AAbA,IAAQ,GAER,KACA,EAAO,SAEP,EAAO,IAAI;IACT,MAAM;IACN,OAAO,KAAQ;IACf,SAAS;KAAE,MAAM;KAAU,IAAI;IAAS;IACxC;GACF,CAAC,GAED,EAAkB,GACd,EAAO,eAAe,KAAG,EAAO,aAAa;EACnD;EAEA,IAAI,UAAU;GAAE,OAAO;EAAQ;EAC/B,MAAM;EAEN,UAAU,GAAsB;GAG9B,OAFA,EAAY,IAAI,CAAE,GAClB,EAAG,CAAK,SACK;IAAE,EAAY,OAAO,CAAE;GAAE;EACxC;EAEA,mBAAmB;GACZ,OAEc,CAAC,OAAO,GAAG,GAAmB,CAAK,KAAwB,OAAO,KAAU,YAAnC,OAG1D,KACA,EAAO,SAEP,EAAO,IAAI;IACT,MAAM;IACN,OAAO,KAAQ;IACf,SAAS;KAAE,MAAM;KAAmB,IAAI;IAAM;IAC9C;GACF,CAAC,GAED,EAAkB,IAGpB,IAAgB,IAChB,IAAoB;EACtB;CACF;CAIA,OAFC,EAAwB,QAAQ,GAChC,EAAwB,cAAc,GAChC;AACT"}