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 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 | 1x 1x 1x 1x 1x 21x 20x 20x 20x 20x 20x 19x 18x 18x 18x 18x 19x 20x 20x 1x 1x 1x 1x 22x 22x 1x 3x 3x 3x 3x 3x 3x 3x 3x 1x 1023x 1023x 1x 1x 1x 1x 1x 1x 1x 1022x 1022x 1x 33x 33x 3x 3x 3x 3x 3x 3x 3x 30x 30x 1x 1x 1059x 2x 2x 2x 1x 2x 1x 1x 1x | import type { KeyLike } from '../types.js'; import { captureStack } from '../exception.js'; import { anchor } from '../anchor.js'; export type Context<K extends KeyLike, V> = Map<K, V>; let currentContext: Context<KeyLike, unknown> | undefined = undefined; let currentRestore: (() => void) | undefined = undefined; /** * Activates the given context and returns a restore function that can be used to revert to the previous context. * If the given context is already active, the current restore function is returned. * * @template K - The type of keys in the context. * @template V - The type of values in the context. * @param context - The context to activate. * @returns A function that restores the previous context when called. */ export function activateContext<K extends KeyLike, V>(context: Context<K, V>): () => void { if (currentContext === context) return currentRestore as () => void; let restored = false; const prevContext = currentContext; const prevRestore = currentRestore; currentContext = context; currentRestore = () => { if (!restored) { restored = true; currentContext = prevContext; currentRestore = prevRestore; } }; return currentRestore; } /** * Retrieves the currently active context. * * @returns The currently active context, or undefined if no context is active. */ export function getActiveContext() { return currentContext; } /** * Creates a new context with optional initial key-value pairs. * The context is anchored with non-recursive behavior. * * @template K - The type of keys in the context. * @template V - The type of values in the context. * @param init - Optional array of key-value pairs to initialize the context with. * @returns A new anchored Map instance representing the context. */ export function createContext<K extends KeyLike, V>(init?: [K, V][]) { return anchor(new Map<K, V>(init), { recursive: false }); } /** * Executes a function within the specified context. * The context is activated before the function is called and restored afterward. * * @template K - The type of keys in the context. * @template V - The type of values in the context. * @template T - The return type of the function. * @param context - The context to execute the function within. * @param fn - The function to execute. * @returns The result of the function execution. */ export function withinContext<K extends KeyLike, V, T>(context: Map<K, V>, fn: () => T): T { activateGlobalContext(); const restore = activateContext(context); try { return fn(); } finally { restore(); } } /** * Sets a value in the currently active context. * If no context is active, an error is logged. * * @template V - The type of the value to set. * @template K - The type of the key (must extend KeyLike). * @param key - The key to set the value for. * @param value - The value to set. * @throws {Error} If called outside of a context. */ export function setContext<V, K extends KeyLike = KeyLike>(key: K, value: V): void { activateGlobalContext(); if (!currentContext) { const error = new Error('Outside of context.'); captureStack.error.external( 'Set context is called outside of context. Make sure you are calling it within a context.', error ); return; } currentContext.set(key, value); } /** * Retrieves a value from the currently active context by key. * If no context is active, an error is logged and undefined is returned. * * @template V - The type of the value to retrieve. * @template K - The type of the key (must extend KeyLike). * @param key - The key to retrieve the value for. * @returns The value associated with the key, or undefined if not found or if called outside of a context. * @throws {Error} If called outside of a context. */ export function getContext<V, K extends KeyLike = KeyLike>(key: K): V | undefined { activateGlobalContext(); if (!currentContext) { const error = new Error('Outside of context.'); captureStack.error.external( 'Get context is called outside of context. Make sure you are calling it within a context.', error ); return; } return currentContext.get(key) as V | undefined; } let globalContextActivated = false; /** * Activates the global context if it hasn't been activated yet and if the environment is a browser. * This function ensures that a default context is available for client-side operations. * It creates a new context and activates it, setting the global context activation flag to true. * * @remarks * This function is a no-op if: * - The global context has already been activated (`globalContextActivated` is true) * - The code is running in a non-browser environment (e.g., Node.js) */ export function activateGlobalContext() { if (globalContextActivated || typeof window === 'undefined') return; activateContext(createContext()); globalContextActivated = true; } /** * Deactivates the global context if it is currently active. * This function resets the global context activation flag to false and clears the current context. * * @remarks * This function is a no-op if the global context has not been activated yet. */ export function deactivateGlobalContext() { if (!globalContextActivated) return; globalContextActivated = false; currentContext = undefined; } |