(fn, label, location)
| 111 | */ |
| 112 | /*#__NO_SIDE_EFFECTS__*/ |
| 113 | export function async_derived(fn, label, location) { |
| 114 | let parent = /** @type {Effect | null} */ (active_effect); |
| 115 | |
| 116 | if (parent === null) { |
| 117 | e.async_derived_orphan(); |
| 118 | } |
| 119 | |
| 120 | var promise = /** @type {Promise<V>} */ (/** @type {unknown} */ (undefined)); |
| 121 | var signal = source(/** @type {V} */ (UNINITIALIZED)); |
| 122 | |
| 123 | if (DEV) signal.label = label ?? fn.toString(); |
| 124 | |
| 125 | // only suspend in async deriveds created on initialisation |
| 126 | var should_suspend = !active_reaction; |
| 127 | |
| 128 | /** @type {Set<ReturnType<typeof deferred<V>>>} */ |
| 129 | var deferreds = new Set(); |
| 130 | |
| 131 | async_effect(() => { |
| 132 | var effect = /** @type {Effect} */ (active_effect); |
| 133 | |
| 134 | if (DEV) { |
| 135 | reactivity_loss_tracker = { effect, effect_deps: new Set(), warned: false }; |
| 136 | } |
| 137 | |
| 138 | /** @type {ReturnType<typeof deferred<V>>} */ |
| 139 | var d = deferred(); |
| 140 | promise = d.promise; |
| 141 | |
| 142 | try { |
| 143 | // If this code is changed at some point, make sure to still access the then property |
| 144 | // of fn() to read any signals it might access, so that we track them as dependencies. |
| 145 | // We call `unset_context` to undo any `save` calls that happen inside `fn()` |
| 146 | Promise.resolve(fn()) |
| 147 | .then(d.resolve, (e) => { |
| 148 | // if the promise was rejected by the user, via `getAbortSignal`, then |
| 149 | // wait for a subsequent resolution instead of flushing the batch |
| 150 | if (e !== STALE_REACTION) d.reject(e); |
| 151 | }) |
| 152 | .finally(unset_context); |
| 153 | } catch (error) { |
| 154 | d.reject(error); |
| 155 | unset_context(); |
| 156 | } |
| 157 | |
| 158 | if (DEV) { |
| 159 | if (reactivity_loss_tracker) { |
| 160 | // Reused deps from previous run (indices 0 to skipped_deps-1) |
| 161 | // We deliberately only track direct dependencies of the async expression to encourage |
| 162 | // dependencies being directly visible at the point of the expression |
| 163 | if (effect.deps !== null) { |
| 164 | for (let i = 0; i < skipped_deps; i += 1) { |
| 165 | reactivity_loss_tracker.effect_deps.add(effect.deps[i]); |
| 166 | } |
| 167 | } |
| 168 | |
| 169 | // New deps discovered this run |
| 170 | if (new_deps !== null) { |
no test coverage detected