incremental-batches
Rich Harris 4 weeks ago
parent d0b8903d90
commit 4bf3ad745f

@ -31,6 +31,7 @@ export const DESTROYED = 1 << 14;
export const REACTION_RAN = 1 << 15;
/** Effect is in the process of getting destroyed. Can be observed in child teardown functions */
export const DESTROYING = 1 << 25;
export const EFFECT_LEGACY = 1 << 26;
// Flags exclusive to effects
/**

@ -23,7 +23,8 @@ import {
ERROR_VALUE,
WAS_MARKED,
MANAGED_EFFECT,
REACTION_RAN
REACTION_RAN,
EFFECT_LEGACY
} from './constants.js';
import { old_values } from './reactivity/sources.js';
import {
@ -116,9 +117,9 @@ export function push_reaction_value(value) {
* and until a new dependency is accessed we track this via `skipped_deps`
* @type {null | Value[]}
*/
let new_deps = null;
export let new_deps = null;
let skipped_deps = 0;
export let skipped_deps = 0;
/**
* Tracks writes that the effect it's executed in doesn't listen to yet,
@ -465,7 +466,7 @@ export function update_effect(effect) {
var teardown = update_reaction(effect);
effect.teardown = typeof teardown === 'function' ? teardown : null;
if (is_runes()) {
if (is_runes() && (effect.f & EFFECT_LEGACY) === 0) {
set_cv(effect, cv);
} else {
// in legacy mode, prevent the effect re-running immediately

@ -1,10 +1,18 @@
/** @import { ComponentConstructorOptions, ComponentType, SvelteComponent, Component } from 'svelte' */
import { DIRTY, LEGACY_PROPS } from '../internal/client/constants.js';
/** @import { Derived, Value } from '#client' */
import { DERIVED, DIRTY, EFFECT_LEGACY, LEGACY_PROPS } from '../internal/client/constants.js';
import { user_pre_effect } from '../internal/client/reactivity/effects.js';
import { mutable_source, set } from '../internal/client/reactivity/sources.js';
import { hydrate, mount, unmount } from '../internal/client/render.js';
import { active_effect, get } from '../internal/client/runtime.js';
import { flushSync } from '../internal/client/reactivity/batch.js';
import {
active_effect,
get,
new_deps,
skipped_deps,
untracked_writes,
write_version
} from '../internal/client/runtime.js';
import { flushSync, get_cv } from '../internal/client/reactivity/batch.js';
import { define_property, is_array } from '../internal/shared/utils.js';
import * as e from '../internal/client/errors.js';
import * as w from '../internal/client/warnings.js';
@ -188,16 +196,37 @@ class Svelte4Component {
*/
export function run(fn) {
user_pre_effect(() => {
fn();
var effect = /** @type {import('#client').Effect} */ (active_effect);
// If the effect is immediately made dirty again, mark it as maybe dirty to emulate legacy behaviour
if ((effect.f & DIRTY) !== 0) {
let filename = "a file (we can't know which one)";
if (DEV) {
// @ts-ignore
filename = dev_current_component_function?.[FILENAME] ?? filename;
// we need this to prevent it from re-running
effect.f |= EFFECT_LEGACY;
fn();
if (untracked_writes !== null) {
/** @type {Set<Value>} */
const all_deps = new Set([...(effect.deps ?? [].slice(skipped_deps)), ...(new_deps ?? [])]);
/** @param {Value} dep */
const add_deps = (dep) => {
all_deps.add(dep);
if ((dep.f & DERIVED) !== 0) {
const deps = /** @type {Derived} */ (dep).deps;
if (deps !== null) deps.forEach(add_deps);
}
};
for (const dep of all_deps) {
if (untracked_writes.includes(dep)) {
let filename = "a file (we can't know which one)";
if (DEV) {
// @ts-ignore
filename = dev_current_component_function?.[FILENAME] ?? filename;
}
w.legacy_recursive_reactive_block(filename);
}
}
w.legacy_recursive_reactive_block(filename);
}
});
}

Loading…
Cancel
Save