Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | 1x 1x 1x 1x 644x 644x 644x 1980x 36x 41x 41x 7x 7x 7x 41x 11x 11x 11x 34x 16x 23x 3x 3x 41x 36x 1980x 644x 29x 1x 1x 29x 29x 644x 2122x 29x 29x 29x 29x 25x 25x 25x 25x 25x 25x 29x 2122x 534x 534x 534x 117x 117x 117x 531x 417x 417x 417x 417x 534x 534x 2122x 644x 644x | import type { Broadcaster, KeyLike, Linkable, StateMetadata, StateSubscriber } from './types.js'; import { BatchMutations, OBSERVER_KEYS } from './enum.js'; import { BATCH_MUTATION_KEYS } from './constant.js'; import { captureStack } from './exception.js'; /** * Creates a broadcaster object for managing state change notifications. * * This function initializes a broadcaster with methods to emit events to observers * and broadcast state changes to subscribers. The broadcaster handles different * types of state changes based on the type of the initial value (array, set, map, or object). * * @param init - The initial linkable state value. * @param meta - Metadata containing subscribers and observers for the state. * @returns A broadcaster object with emit and broadcast methods. */ export function createBroadcaster<T extends Linkable = Linkable>(init: Linkable, meta: StateMetadata<T>): Broadcaster { const { observers, subscribers, exceptionHandlers } = meta; return { /** * Emits a state change event to registered observers. * * This method checks the type of the initial value and notifies observers * based on the specific keys they are interested in. Array and collection * mutations are handled specially, while other changes are notified based * on the event's key path. * * @param event - The state change event to emit. * @param prop - Optional property key that was changed. */ emit(event, prop) { if (observers.size) { for (const observer of observers) { const keys = observer.states.get(init) as Set<KeyLike>; if (Array.isArray(init)) { if (keys.has(OBSERVER_KEYS.ARRAY_MUTATIONS)) { observer.onChange(event); } } else if (init instanceof Set || init instanceof Map) { if (keys.has(OBSERVER_KEYS.COLLECTION_MUTATIONS)) { observer.onChange(event); } } else if (keys.has(prop ?? event.keys.join('.'))) { observer.onChange(event); } else if (BATCH_MUTATION_KEYS.has(event.type as BatchMutations)) { observer.onChange(event); } } } }, catch(error, event) { for (const handler of exceptionHandlers) { handler({ ...event, error, issues: error.issues }); } return true; }, /** * Broadcasts a state snapshot and change event to all subscribers. * * This method delegates to the broadcast function, passing the subscribers * set, current snapshot, event, and optional emitter ID to prevent * self-notification. * * @param snapshot - The current state snapshot. * @param event - The state change event. * @param emitter - Optional identifier of the emitting instance. */ broadcast(snapshot, event, emitter) { if (event.error && !exceptionHandlers.size) { const handlers = Array.from(subscribers).filter( (fn) => (fn as never as { __internal_id__: string }).__internal_id__ ); if (!handlers.length) { captureStack.error.validation( `Unhandled schema validation of a state mutation: "${event.type}"`, event.error, meta.configs.strict ); } } for (const subscriber of subscribers) { if (typeof subscriber === 'function') { const receiver = (subscriber as never as { __internal_id__: string }).__internal_id__; if (receiver) { if (receiver !== emitter) { (subscriber as StateSubscriber<unknown>)(snapshot, event, emitter); } } else { if (!event.error) { (subscriber as StateSubscriber<unknown>)(snapshot, event); } } } } }, } as Broadcaster; } |