UNPKG

react-native-reanimated

Version:

More powerful alternative to Animated library for React Native.

87 lines (83 loc) 2.97 kB
'use strict'; /** * Routes CSS events emitted by the native side to the objects interested in a * given view. Nested animated components can share a view tag, so every tag * keeps a set of subscribers rather than a single one. * * A view that unmounts is retired instead of unregistered: it stops being a * subscriber, but still hears the batch after, because the engine emits its * cancel as it tears down and that batch arrives once the view is gone. */ class CSSCallbacksRegistry { subscribersByTag = new Map(); retiringByTag = new Map(); register(viewTag, subscriber) { this.retiringByTag.get(viewTag)?.delete(subscriber); addSubscriber(this.subscribersByTag, viewTag, subscriber); } unregister(viewTag, subscriber) { const subscribers = this.subscribersByTag.get(viewTag); if (!subscribers) { return; } subscribers.delete(subscriber); if (subscribers.size === 0) { this.subscribersByTag.delete(viewTag); } } /** * Unregistering now, rather than after the batch it still hears, is what lets * a view that mounts again stay subscribed by simply registering. */ retire(viewTag, subscriber) { this.unregister(viewTag, subscriber); addSubscriber(this.retiringByTag, viewTag, subscriber); } dispatch(events) { // Taken up front, so a view retired by a callback in this batch hears the // next one rather than this one. const retiring = this.retiringByTag; this.retiringByTag = new Map(); for (const event of events) { const subscribers = subscribersFor(event.tag, this.subscribersByTag, retiring); // Absent once the event outlives the view it was emitted for. if (!subscribers) { continue; } for (const subscriber of subscribers) { try { subscriber.handleCSSEvent(event); } catch (error) { // Reported the way an uncaught error would be anyway, so one broken // callback stays fatal without starving the views queued behind it. // @ts-expect-error React Native's `ErrorUtils` are hidden from the global scope. globalThis.ErrorUtils.reportFatalError(error); } } } } clear() { this.subscribersByTag.clear(); this.retiringByTag.clear(); } } function addSubscriber(byTag, viewTag, subscriber) { const subscribers = byTag.get(viewTag); if (subscribers) { subscribers.add(subscriber); } else { byTag.set(viewTag, new Set([subscriber])); } } /** One set, because a view that registers again while retiring is in both. */ function subscribersFor(viewTag, subscribed, retiring) { const current = subscribed.get(viewTag); const retired = retiring.get(viewTag); if (!retired) { return current; } return current ? new Set([...current, ...retired]) : retired; } const cssCallbacksRegistry = new CSSCallbacksRegistry(); export default cssCallbacksRegistry; //# sourceMappingURL=CSSCallbacksRegistry.js.map