first
This commit is contained in:
commit
f4be03ceba
1826 changed files with 830924 additions and 0 deletions
95
frontend/node_modules/svelte/src/reactivity/create-subscriber.js
generated
vendored
Normal file
95
frontend/node_modules/svelte/src/reactivity/create-subscriber.js
generated
vendored
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
import { get, tick, untrack } from '../internal/client/runtime.js';
|
||||
import { effect_tracking, render_effect } from '../internal/client/reactivity/effects.js';
|
||||
import { source, increment } from '../internal/client/reactivity/sources.js';
|
||||
import { tag } from '../internal/client/dev/tracing.js';
|
||||
import { DEV } from 'esm-env';
|
||||
import { queue_micro_task } from '../internal/client/dom/task.js';
|
||||
|
||||
/**
|
||||
* Returns a `subscribe` function that integrates external event-based systems with Svelte's reactivity.
|
||||
* It's particularly useful for integrating with web APIs like `MediaQuery`, `IntersectionObserver`, or `WebSocket`.
|
||||
*
|
||||
* If `subscribe` is called inside an effect (including indirectly, for example inside a getter),
|
||||
* the `start` callback will be called with an `update` function. Whenever `update` is called, the effect re-runs.
|
||||
*
|
||||
* If `start` returns a cleanup function, it will be called when the effect is destroyed.
|
||||
*
|
||||
* If `subscribe` is called in multiple effects, `start` will only be called once as long as the effects
|
||||
* are active, and the returned teardown function will only be called when all effects are destroyed.
|
||||
*
|
||||
* It's best understood with an example. Here's an implementation of [`MediaQuery`](https://svelte.dev/docs/svelte/svelte-reactivity#MediaQuery):
|
||||
*
|
||||
* ```js
|
||||
* import { createSubscriber } from 'svelte/reactivity';
|
||||
* import { on } from 'svelte/events';
|
||||
*
|
||||
* export class MediaQuery {
|
||||
* #query;
|
||||
* #subscribe;
|
||||
*
|
||||
* constructor(query) {
|
||||
* this.#query = window.matchMedia(`(${query})`);
|
||||
*
|
||||
* this.#subscribe = createSubscriber((update) => {
|
||||
* // when the `change` event occurs, re-run any effects that read `this.current`
|
||||
* const off = on(this.#query, 'change', update);
|
||||
*
|
||||
* // stop listening when all the effects are destroyed
|
||||
* return () => off();
|
||||
* });
|
||||
* }
|
||||
*
|
||||
* get current() {
|
||||
* // This makes the getter reactive, if read in an effect
|
||||
* this.#subscribe();
|
||||
*
|
||||
* // Return the current state of the query, whether or not we're in an effect
|
||||
* return this.#query.matches;
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
* @param {(update: () => void) => (() => void) | void} start
|
||||
* @since 5.7.0
|
||||
*/
|
||||
export function createSubscriber(start) {
|
||||
let subscribers = 0;
|
||||
let version = source(0);
|
||||
/** @type {(() => void) | void} */
|
||||
let stop;
|
||||
|
||||
if (DEV) {
|
||||
tag(version, 'createSubscriber version');
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (effect_tracking()) {
|
||||
get(version);
|
||||
|
||||
render_effect(() => {
|
||||
if (subscribers === 0) {
|
||||
stop = untrack(() => start(() => increment(version)));
|
||||
}
|
||||
|
||||
subscribers += 1;
|
||||
|
||||
return () => {
|
||||
queue_micro_task(() => {
|
||||
// Only count down after a microtask, else we would reach 0 before our own render effect reruns,
|
||||
// but reach 1 again when the tick callback of the prior teardown runs. That would mean we
|
||||
// re-subcribe unnecessarily and create a memory leak because the old subscription is never cleaned up.
|
||||
subscribers -= 1;
|
||||
|
||||
if (subscribers === 0) {
|
||||
stop?.();
|
||||
stop = undefined;
|
||||
// Increment the version to ensure any dependent deriveds are marked dirty when the subscription is picked up again later.
|
||||
// If we didn't do this then the comparison of write versions would determine that the derived has a later version than
|
||||
// the subscriber, and it would not be re-run.
|
||||
increment(version);
|
||||
}
|
||||
});
|
||||
};
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue