Skip to content

Commit

Permalink
fix: ensure legacy run utility does not cause cycles (#13643)
Browse files Browse the repository at this point in the history
* fix: ensure legacy run utility does not cause cycles

* add warning

* add warning

* lint

* feedback

* lint

* lint
  • Loading branch information
trueadm authored Oct 17, 2024
1 parent ffa2af7 commit 139114b
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changeset/moody-pugs-tan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'svelte': patch
---

fix: ensure legacy run utility does not cause cycles
6 changes: 6 additions & 0 deletions documentation/docs/98-reference/.generated/client-warnings.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ Hydration failed because the initial UI does not match what was rendered on the
The `render` function passed to `createRawSnippet` should return HTML for a single element
```

### legacy_recursive_reactive_block

```
Detected a migrated `$:` reactive block that both accesses and updates the same reactive value. This may cause recursive updates when converted to an `$effect`.
```

### lifecycle_double_unmount

```
Expand Down
4 changes: 4 additions & 0 deletions packages/svelte/messages/client-warnings/warnings.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ The easiest way to log a value as it changes over time is to use the [`$inspect`

> The `render` function passed to `createRawSnippet` should return HTML for a single element
## legacy_recursive_reactive_block

> Detected a migrated `$:` reactive block that both accesses and updates the same reactive value. This may cause recursive updates when converted to an `$effect`.
## lifecycle_double_unmount

> Tried to unmount a component that was not mounted
Expand Down
12 changes: 12 additions & 0 deletions packages/svelte/src/internal/client/warnings.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,18 @@ export function invalid_raw_snippet_render() {
}
}

/**
* Detected a migrated `$:` reactive block that both accesses and updates the same reactive value. This may cause recursive updates when converted to an `$effect`.
*/
export function legacy_recursive_reactive_block() {
if (DEV) {
console.warn(`%c[svelte] legacy_recursive_reactive_block\n%cDetected a migrated \`$:\` reactive block that both accesses and updates the same reactive value. This may cause recursive updates when converted to an \`$effect\`.`, bold, normal);
} else {
// TODO print a link to the documentation
console.warn("legacy_recursive_reactive_block");
}
}

/**
* Tried to unmount a component that was not mounted
*/
Expand Down
20 changes: 18 additions & 2 deletions packages/svelte/src/legacy/legacy-client.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
/** @import { ComponentConstructorOptions, ComponentType, SvelteComponent, Component } from 'svelte' */
import { DIRTY, MAYBE_DIRTY } 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 { component_context, flush_sync, get } from '../internal/client/runtime.js';
import {
active_effect,
component_context,
flush_sync,
get,
set_signal_status
} from '../internal/client/runtime.js';
import { lifecycle_outside_component } from '../internal/shared/errors.js';
import { define_property, is_array } from '../internal/shared/utils.js';
import * as w from '../internal/client/warnings.js';

/**
* Takes the same options as a Svelte 4 component and the component function and returns a Svelte 4 compatible component.
Expand Down Expand Up @@ -169,7 +177,15 @@ class Svelte4Component {
* @returns {void}
*/
export function run(fn) {
user_pre_effect(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) {
w.legacy_recursive_reactive_block();
set_signal_status(effect, MAYBE_DIRTY);
}
});
}

/**
Expand Down

0 comments on commit 139114b

Please sign in to comment.