A
B
C
diff --git a/packages/svelte/tests/runtime-legacy/shared.ts b/packages/svelte/tests/runtime-legacy/shared.ts
index 02168c79f9..e8074b9e5b 100644
--- a/packages/svelte/tests/runtime-legacy/shared.ts
+++ b/packages/svelte/tests/runtime-legacy/shared.ts
@@ -66,7 +66,7 @@ export interface RuntimeTest = RecordTesting
+123 ;
+ 456
`,
+ ssrHtml: `A B C D
Testing
+123 ;
+ 456
`
});
diff --git a/packages/svelte/tests/runtime-runes/samples/snippet-whitespace/main.svelte b/packages/svelte/tests/runtime-runes/samples/snippet-whitespace/main.svelte
index a85a932602..35bbf4b310 100644
--- a/packages/svelte/tests/runtime-runes/samples/snippet-whitespace/main.svelte
+++ b/packages/svelte/tests/runtime-runes/samples/snippet-whitespace/main.svelte
@@ -1,5 +1,15 @@
+
A
{#snippet snip()}C{/snippet}
B
{@render snip()}
D
+
+
+ Testing
+123 ;
+ 456
+
\ No newline at end of file
diff --git a/packages/svelte/tests/runtime-runes/samples/snippet-whitespace/pre.svelte b/packages/svelte/tests/runtime-runes/samples/snippet-whitespace/pre.svelte
new file mode 100644
index 0000000000..821b578fa9
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/snippet-whitespace/pre.svelte
@@ -0,0 +1,5 @@
+
+
+
{@render children()}
From 767b5a8824998a57813a7f135b7442d829e93806 Mon Sep 17 00:00:00 2001
From: Simon H <5968653+dummdidumm@users.noreply.github.com>
Date: Tue, 5 Mar 2024 01:07:44 +0100
Subject: [PATCH 2/6] chore: remove obsolete test (#10679)
Checking for expected or unexpected props in 2024 is the job TypeScript, and runtime validation has resulted in false positives previously - therefore leave this out in Svelte 5.
closes #10672
---
.../no-missing-prop-warnings/_config.js | 23 -------------------
.../no-missing-prop-warnings/main.svelte | 9 --------
2 files changed, 32 deletions(-)
delete mode 100644 packages/svelte/tests/runtime-browser/custom-elements-samples/no-missing-prop-warnings/_config.js
delete mode 100644 packages/svelte/tests/runtime-browser/custom-elements-samples/no-missing-prop-warnings/main.svelte
diff --git a/packages/svelte/tests/runtime-browser/custom-elements-samples/no-missing-prop-warnings/_config.js b/packages/svelte/tests/runtime-browser/custom-elements-samples/no-missing-prop-warnings/_config.js
deleted file mode 100644
index 45dc13fea0..0000000000
--- a/packages/svelte/tests/runtime-browser/custom-elements-samples/no-missing-prop-warnings/_config.js
+++ /dev/null
@@ -1,23 +0,0 @@
-import { test } from '../../assert';
-const tick = () => Promise.resolve();
-
-export default test({
- dev: true,
- skip: true, // TODO: needs dev time warning
- async test({ assert, target }) {
- /** @type {string[]} */
- const warnings = [];
- const warn = console.warn;
-
- console.warn = (warning) => {
- warnings.push(warning);
- };
-
- target.innerHTML = '
';
- await tick();
-
- assert.deepEqual(warnings, ["
was created without expected prop 'bar'"]);
-
- console.warn = warn;
- }
-});
diff --git a/packages/svelte/tests/runtime-browser/custom-elements-samples/no-missing-prop-warnings/main.svelte b/packages/svelte/tests/runtime-browser/custom-elements-samples/no-missing-prop-warnings/main.svelte
deleted file mode 100644
index 31076dc357..0000000000
--- a/packages/svelte/tests/runtime-browser/custom-elements-samples/no-missing-prop-warnings/main.svelte
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-foo: {foo}
-bar: {bar}
From 6fb64c99147d69dde4908d6e58f6e3d98108ffc8 Mon Sep 17 00:00:00 2001
From: Ahmad
Date: Tue, 5 Mar 2024 02:28:25 +0200
Subject: [PATCH 3/6] fix: improve namespace inference when having `{@render}`
and `{@html}` tags (#10631)
* fix: treat snippets like normal components when inferring namespace
* n
* simplify
* better desc
* slight adjustment
* feedback
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
* feedback
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
* skip html tag
* test
* changeset name
* cleanup
---------
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
---
.changeset/giant-planets-shake.md | 5 ++
.../src/compiler/phases/3-transform/utils.js | 85 +++++++++----------
.../svg-namespace-infer/Wrapper.svelte | 14 ++-
.../samples/svg-namespace-infer/_config.js | 5 +-
4 files changed, 60 insertions(+), 49 deletions(-)
create mode 100644 .changeset/giant-planets-shake.md
diff --git a/.changeset/giant-planets-shake.md b/.changeset/giant-planets-shake.md
new file mode 100644
index 0000000000..1197567abd
--- /dev/null
+++ b/.changeset/giant-planets-shake.md
@@ -0,0 +1,5 @@
+---
+"svelte": patch
+---
+
+fix: improve namespace inference when having `{@render}` and `{@html}` tags
diff --git a/packages/svelte/src/compiler/phases/3-transform/utils.js b/packages/svelte/src/compiler/phases/3-transform/utils.js
index 97fc45d7a8..3429748e29 100644
--- a/packages/svelte/src/compiler/phases/3-transform/utils.js
+++ b/packages/svelte/src/compiler/phases/3-transform/utils.js
@@ -5,6 +5,7 @@ import {
regex_whitespaces_strict
} from '../patterns.js';
import * as b from '../../utils/builders.js';
+import { walk } from 'zimmerframe';
/**
* @param {string} s
@@ -249,51 +250,49 @@ export function infer_namespace(namespace, parent, nodes, path) {
* @param {import('#compiler').Namespace | 'keep' | 'maybe_html'} namespace
*/
function check_nodes_for_namespace(nodes, namespace) {
+ /**
+ * @param {import('#compiler').SvelteElement | import('#compiler').RegularElement} node}
+ * @param {{stop: () => void}} context
+ */
+ const RegularElement = (node, { stop }) => {
+ if (!node.metadata.svg) {
+ namespace = 'html';
+ stop();
+ } else if (namespace === 'keep') {
+ namespace = 'svg';
+ }
+ };
+
for (const node of nodes) {
- if (node.type === 'RegularElement' || node.type === 'SvelteElement') {
- if (!node.metadata.svg) {
- namespace = 'html';
- break;
- } else if (namespace === 'keep') {
- namespace = 'svg';
- }
- } else if (
- (node.type === 'Text' && node.data.trim() !== '') ||
- node.type === 'HtmlTag' ||
- node.type === 'RenderTag'
- ) {
- namespace = 'maybe_html';
- } else if (node.type === 'EachBlock') {
- namespace = check_nodes_for_namespace(node.body.nodes, namespace);
- if (namespace === 'html') break;
- if (node.fallback) {
- namespace = check_nodes_for_namespace(node.fallback.nodes, namespace);
- if (namespace === 'html') break;
- }
- } else if (node.type === 'IfBlock') {
- namespace = check_nodes_for_namespace(node.consequent.nodes, namespace);
- if (namespace === 'html') break;
- if (node.alternate) {
- namespace = check_nodes_for_namespace(node.alternate.nodes, namespace);
- if (namespace === 'html') break;
- }
- } else if (node.type === 'AwaitBlock') {
- if (node.pending) {
- namespace = check_nodes_for_namespace(node.pending.nodes, namespace);
- if (namespace === 'html') break;
+ walk(
+ node,
+ {},
+ {
+ _(node, { next }) {
+ if (
+ node.type === 'EachBlock' ||
+ node.type === 'IfBlock' ||
+ node.type === 'AwaitBlock' ||
+ node.type === 'Fragment' ||
+ node.type === 'KeyBlock' ||
+ node.type === 'RegularElement' ||
+ node.type === 'SvelteElement' ||
+ node.type === 'Text'
+ ) {
+ next();
+ }
+ },
+ SvelteElement: RegularElement,
+ RegularElement,
+ Text(node) {
+ if (node.data.trim() !== '') {
+ namespace = 'maybe_html';
+ }
+ }
}
- if (node.then) {
- namespace = check_nodes_for_namespace(node.then.nodes, namespace);
- if (namespace === 'html') break;
- }
- if (node.catch) {
- namespace = check_nodes_for_namespace(node.catch.nodes, namespace);
- if (namespace === 'html') break;
- }
- } else if (node.type === 'KeyBlock') {
- namespace = check_nodes_for_namespace(node.fragment.nodes, namespace);
- if (namespace === 'html') break;
- }
+ );
+
+ if (namespace === 'html') return namespace;
}
return namespace;
diff --git a/packages/svelte/tests/runtime-runes/samples/svg-namespace-infer/Wrapper.svelte b/packages/svelte/tests/runtime-runes/samples/svg-namespace-infer/Wrapper.svelte
index 41f3f38fa8..5231a0c44a 100644
--- a/packages/svelte/tests/runtime-runes/samples/svg-namespace-infer/Wrapper.svelte
+++ b/packages/svelte/tests/runtime-runes/samples/svg-namespace-infer/Wrapper.svelte
@@ -2,12 +2,18 @@
{#if true}
true
-{:else}
- false
{/if}
-{#each Array(3).fill(0) as item, idx}
+{#each Array(2).fill(0) as item, idx}
{idx}
{/each}
-
+{@html 'html'}
+
+{@render test("snippet")}
+
+{#snippet test(text)}
+{text}
+{/snippet}
+
+
diff --git a/packages/svelte/tests/runtime-runes/samples/svg-namespace-infer/_config.js b/packages/svelte/tests/runtime-runes/samples/svg-namespace-infer/_config.js
index 46118026af..9ea299b21a 100644
--- a/packages/svelte/tests/runtime-runes/samples/svg-namespace-infer/_config.js
+++ b/packages/svelte/tests/runtime-runes/samples/svg-namespace-infer/_config.js
@@ -7,7 +7,8 @@ export default test({
true
0
1
- 2
+ html
+ snippet
`,
test({ assert, target }) {
@@ -18,7 +19,7 @@ export default test({
const text_elements = target.querySelectorAll('text');
- assert.equal(text_elements.length, 5);
+ assert.equal(text_elements.length, 6);
for (const { namespaceURI } of text_elements)
assert.equal(namespaceURI, 'http://www.w3.org/2000/svg');
From d577740c82d5bf05d00e13969d1742f7960ea8ac Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Mon, 4 Mar 2024 17:31:08 -0700
Subject: [PATCH 4/6] Version Packages (next) (#10693)
Co-authored-by: github-actions[bot]
---
.changeset/pre.json | 2 ++
packages/svelte/CHANGELOG.md | 8 ++++++++
packages/svelte/package.json | 2 +-
packages/svelte/src/version.js | 2 +-
4 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/.changeset/pre.json b/.changeset/pre.json
index 06f31fc7d6..5d4b668ce9 100644
--- a/.changeset/pre.json
+++ b/.changeset/pre.json
@@ -97,6 +97,7 @@
"gentle-sheep-hug",
"gentle-spies-happen",
"giant-moons-own",
+ "giant-planets-shake",
"giant-roses-press",
"good-buses-reply",
"good-cars-visit",
@@ -108,6 +109,7 @@
"green-eggs-approve",
"green-hounds-play",
"green-tigers-judge",
+ "happy-beds-scream",
"happy-suits-film",
"healthy-planes-vanish",
"heavy-comics-move",
diff --git a/packages/svelte/CHANGELOG.md b/packages/svelte/CHANGELOG.md
index 5a92088173..0fce88cce7 100644
--- a/packages/svelte/CHANGELOG.md
+++ b/packages/svelte/CHANGELOG.md
@@ -1,5 +1,13 @@
# svelte
+## 5.0.0-next.71
+
+### Patch Changes
+
+- fix: improve namespace inference when having `{@render}` and `{@html}` tags ([#10631](https://github.com/sveltejs/svelte/pull/10631))
+
+- fix: don't collapse whitespace within text nodes ([#10691](https://github.com/sveltejs/svelte/pull/10691))
+
## 5.0.0-next.70
### Patch Changes
diff --git a/packages/svelte/package.json b/packages/svelte/package.json
index 9ebe29acd9..e8d9e43c1c 100644
--- a/packages/svelte/package.json
+++ b/packages/svelte/package.json
@@ -2,7 +2,7 @@
"name": "svelte",
"description": "Cybernetically enhanced web apps",
"license": "MIT",
- "version": "5.0.0-next.70",
+ "version": "5.0.0-next.71",
"type": "module",
"types": "./types/index.d.ts",
"engines": {
diff --git a/packages/svelte/src/version.js b/packages/svelte/src/version.js
index 8b92139b74..86694f4697 100644
--- a/packages/svelte/src/version.js
+++ b/packages/svelte/src/version.js
@@ -6,5 +6,5 @@
* https://svelte.dev/docs/svelte-compiler#svelte-version
* @type {string}
*/
-export const VERSION = '5.0.0-next.70';
+export const VERSION = '5.0.0-next.71';
export const PUBLIC_VERSION = '5';
From 2d15c9de3f5ea7f99964342afad7bdbb6c8f0ea9 Mon Sep 17 00:00:00 2001
From: Rich Harris
Date: Mon, 4 Mar 2024 17:53:47 -0700
Subject: [PATCH 5/6] create #client types alias (#10695)
Co-authored-by: Rich Harris
---
packages/svelte/tsconfig.json | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/packages/svelte/tsconfig.json b/packages/svelte/tsconfig.json
index 869225f89f..0764cde0cb 100644
--- a/packages/svelte/tsconfig.json
+++ b/packages/svelte/tsconfig.json
@@ -24,7 +24,8 @@
"svelte/motion": ["./src/motion/public.d.ts"],
"svelte/server": ["./src/server/index.js"],
"svelte/store": ["./src/store/public.d.ts"],
- "#compiler": ["./src/compiler/types/index.d.ts"]
+ "#compiler": ["./src/compiler/types/index.d.ts"],
+ "#client": ["./src/internal/client/types.d.ts"]
}
},
"include": [
From aa29a853dd1bb3bad623b7427588c82fc380c5f6 Mon Sep 17 00:00:00 2001
From: Rich Harris
Date: Mon, 4 Mar 2024 18:31:35 -0700
Subject: [PATCH 6/6] chore: move reactivity code around (#10696)
* move some code
* split computations.js into deriveds.js and effects.js
* move reactivity types into separate .d.ts file
* move some signal code
---------
Co-authored-by: Rich Harris
---
.../src/internal/client/custom-element.js | 2 +-
.../src/internal/client/dom/blocks/await.js | 2 +-
.../src/internal/client/dom/blocks/each.js | 12 +-
.../src/internal/client/dom/blocks/if.js | 2 +-
.../src/internal/client/dom/blocks/key.js | 2 +-
packages/svelte/src/internal/client/proxy.js | 8 +-
.../internal/client/reactivity/deriveds.js | 36 ++++
.../{computations.js => effects.js} | 34 +---
.../src/internal/client/reactivity/props.js | 21 +++
.../src/internal/client/reactivity/sources.js | 128 +++++++++++++-
.../src/internal/client/reactivity/store.js | 6 +-
.../src/internal/client/reactivity/types.d.ts | 74 +++++++++
packages/svelte/src/internal/client/render.js | 7 +-
.../svelte/src/internal/client/runtime.js | 157 +++---------------
.../svelte/src/internal/client/transitions.js | 2 +-
.../svelte/src/internal/client/types.d.ts | 82 +--------
packages/svelte/src/internal/index.js | 9 +-
packages/svelte/src/reactivity/index.js | 4 +-
packages/svelte/tests/signals/test.ts | 60 ++++---
19 files changed, 332 insertions(+), 316 deletions(-)
create mode 100644 packages/svelte/src/internal/client/reactivity/deriveds.js
rename packages/svelte/src/internal/client/reactivity/{computations.js => effects.js} (86%)
create mode 100644 packages/svelte/src/internal/client/reactivity/props.js
create mode 100644 packages/svelte/src/internal/client/reactivity/types.d.ts
diff --git a/packages/svelte/src/internal/client/custom-element.js b/packages/svelte/src/internal/client/custom-element.js
index 92d1a46573..0bd64cdf50 100644
--- a/packages/svelte/src/internal/client/custom-element.js
+++ b/packages/svelte/src/internal/client/custom-element.js
@@ -1,6 +1,6 @@
import { createClassComponent } from '../../legacy/legacy-client.js';
import { destroy_signal } from './runtime.js';
-import { render_effect } from './reactivity/computations.js';
+import { render_effect } from './reactivity/effects.js';
import { open, close } from './render.js';
import { define_property } from './utils.js';
diff --git a/packages/svelte/src/internal/client/dom/blocks/await.js b/packages/svelte/src/internal/client/dom/blocks/await.js
index ede2a759e9..4f24a4d4ae 100644
--- a/packages/svelte/src/internal/client/dom/blocks/await.js
+++ b/packages/svelte/src/internal/client/dom/blocks/await.js
@@ -8,7 +8,7 @@ import {
flushSync,
push_destroy_fn
} from '../../runtime.js';
-import { render_effect } from '../../reactivity/computations.js';
+import { render_effect } from '../../reactivity/effects.js';
import { trigger_transitions } from '../../transitions.js';
import { AWAIT_BLOCK, UNINITIALIZED } from '../../constants.js';
diff --git a/packages/svelte/src/internal/client/dom/blocks/each.js b/packages/svelte/src/internal/client/dom/blocks/each.js
index 8c40d6c774..59bf93319c 100644
--- a/packages/svelte/src/internal/client/dom/blocks/each.js
+++ b/packages/svelte/src/internal/client/dom/blocks/each.js
@@ -16,15 +16,9 @@ import {
} from '../../hydration.js';
import { clear_text_content, empty, map_get, map_set } from '../../operations.js';
import { insert, remove } from '../../reconciler.js';
-import {
- current_block,
- destroy_signal,
- execute_effect,
- push_destroy_fn,
- set_signal_value
-} from '../../runtime.js';
-import { render_effect } from '../../reactivity/computations.js';
-import { source, mutable_source } from '../../reactivity/sources.js';
+import { current_block, destroy_signal, execute_effect, push_destroy_fn } from '../../runtime.js';
+import { render_effect } from '../../reactivity/effects.js';
+import { source, mutable_source, set_signal_value } from '../../reactivity/sources.js';
import { trigger_transitions } from '../../transitions.js';
import { is_array } from '../../utils.js';
import { EACH_BLOCK, EACH_ITEM_BLOCK } from '../../constants.js';
diff --git a/packages/svelte/src/internal/client/dom/blocks/if.js b/packages/svelte/src/internal/client/dom/blocks/if.js
index 1aa742fd43..6a2372596b 100644
--- a/packages/svelte/src/internal/client/dom/blocks/if.js
+++ b/packages/svelte/src/internal/client/dom/blocks/if.js
@@ -7,7 +7,7 @@ import {
} from '../../hydration.js';
import { remove } from '../../reconciler.js';
import { current_block, destroy_signal, execute_effect, push_destroy_fn } from '../../runtime.js';
-import { render_effect } from '../../reactivity/computations.js';
+import { render_effect } from '../../reactivity/effects.js';
import { trigger_transitions } from '../../transitions.js';
/** @returns {import('../../types.js').IfBlock} */
diff --git a/packages/svelte/src/internal/client/dom/blocks/key.js b/packages/svelte/src/internal/client/dom/blocks/key.js
index 9499590817..d4cfd175b7 100644
--- a/packages/svelte/src/internal/client/dom/blocks/key.js
+++ b/packages/svelte/src/internal/client/dom/blocks/key.js
@@ -2,7 +2,7 @@ import { UNINITIALIZED, KEY_BLOCK } from '../../constants.js';
import { hydrate_block_anchor } from '../../hydration.js';
import { remove } from '../../reconciler.js';
import { current_block, destroy_signal, execute_effect, push_destroy_fn } from '../../runtime.js';
-import { render_effect } from '../../reactivity/computations.js';
+import { render_effect } from '../../reactivity/effects.js';
import { trigger_transitions } from '../../transitions.js';
import { safe_not_equal } from '../../reactivity/equality.js';
diff --git a/packages/svelte/src/internal/client/proxy.js b/packages/svelte/src/internal/client/proxy.js
index 290dc187ff..8627fc1f4a 100644
--- a/packages/svelte/src/internal/client/proxy.js
+++ b/packages/svelte/src/internal/client/proxy.js
@@ -1,14 +1,12 @@
import { DEV } from 'esm-env';
import {
get,
- set,
updating_derived,
batch_inspect,
current_component_context,
- untrack,
- set_signal_value
+ untrack
} from './runtime.js';
-import { effect_active } from './reactivity/computations.js';
+import { effect_active } from './reactivity/effects.js';
import {
array_prototype,
define_property,
@@ -20,7 +18,7 @@ import {
object_prototype
} from './utils.js';
import { add_owner, check_ownership, strip_owner } from './dev/ownership.js';
-import { mutable_source, source } from './reactivity/sources.js';
+import { mutable_source, source, set, set_signal_value } from './reactivity/sources.js';
import { STATE_SYMBOL, UNINITIALIZED } from './constants.js';
/**
diff --git a/packages/svelte/src/internal/client/reactivity/deriveds.js b/packages/svelte/src/internal/client/reactivity/deriveds.js
new file mode 100644
index 0000000000..c710d34afc
--- /dev/null
+++ b/packages/svelte/src/internal/client/reactivity/deriveds.js
@@ -0,0 +1,36 @@
+import { CLEAN, DERIVED, UNINITIALIZED, UNOWNED } from '../constants.js';
+import { current_block, current_consumer, current_effect } from '../runtime.js';
+import { create_computation_signal, push_reference } from './effects.js';
+import { default_equals, safe_equal } from './equality.js';
+
+/**
+ * @template V
+ * @param {() => V} fn
+ * @returns {import('../types.js').ComputationSignal}
+ */
+/*#__NO_SIDE_EFFECTS__*/
+export function derived(fn) {
+ const is_unowned = current_effect === null;
+ const flags = is_unowned ? DERIVED | UNOWNED : DERIVED;
+ const signal = /** @type {import('../types.js').ComputationSignal} */ (
+ create_computation_signal(flags | CLEAN, UNINITIALIZED, current_block)
+ );
+ signal.i = fn;
+ signal.e = default_equals;
+ if (current_consumer !== null) {
+ push_reference(current_consumer, signal);
+ }
+ return signal;
+}
+
+/**
+ * @template V
+ * @param {() => V} fn
+ * @returns {import('../types.js').ComputationSignal}
+ */
+/*#__NO_SIDE_EFFECTS__*/
+export function derived_safe_equal(fn) {
+ const signal = derived(fn);
+ signal.e = safe_equal;
+ return signal;
+}
diff --git a/packages/svelte/src/internal/client/reactivity/computations.js b/packages/svelte/src/internal/client/reactivity/effects.js
similarity index 86%
rename from packages/svelte/src/internal/client/reactivity/computations.js
rename to packages/svelte/src/internal/client/reactivity/effects.js
index 13052e410a..8d1ae7f81e 100644
--- a/packages/svelte/src/internal/client/reactivity/computations.js
+++ b/packages/svelte/src/internal/client/reactivity/effects.js
@@ -27,7 +27,7 @@ import {
* @param {V} value
* @param {import('../types.js').Block | null} block
*/
-function create_computation_signal(flags, value, block) {
+export function create_computation_signal(flags, value, block) {
/** @type {import('../types.js').ComputationSignal} */
const signal = {
b: block,
@@ -224,35 +224,3 @@ export function render_effect(fn, block = current_block, managed = false, sync =
}
return internal_create_effect(flags, /** @type {any} */ (fn), sync, block, true);
}
-
-/**
- * @template V
- * @param {() => V} fn
- * @returns {import('../types.js').ComputationSignal}
- */
-/*#__NO_SIDE_EFFECTS__*/
-export function derived(fn) {
- const is_unowned = current_effect === null;
- const flags = is_unowned ? DERIVED | UNOWNED : DERIVED;
- const signal = /** @type {import('../types.js').ComputationSignal} */ (
- create_computation_signal(flags | CLEAN, UNINITIALIZED, current_block)
- );
- signal.i = fn;
- signal.e = default_equals;
- if (current_consumer !== null) {
- push_reference(current_consumer, signal);
- }
- return signal;
-}
-
-/**
- * @template V
- * @param {() => V} fn
- * @returns {import('../types.js').ComputationSignal}
- */
-/*#__NO_SIDE_EFFECTS__*/
-export function derived_safe_equal(fn) {
- const signal = derived(fn);
- signal.e = safe_equal;
- return signal;
-}
diff --git a/packages/svelte/src/internal/client/reactivity/props.js b/packages/svelte/src/internal/client/reactivity/props.js
new file mode 100644
index 0000000000..99e5048627
--- /dev/null
+++ b/packages/svelte/src/internal/client/reactivity/props.js
@@ -0,0 +1,21 @@
+/**
+ * @param {((value?: number) => number)} fn
+ * @param {1 | -1} [d]
+ * @returns {number}
+ */
+export function update_prop(fn, d = 1) {
+ const value = fn();
+ fn(value + d);
+ return value;
+}
+
+/**
+ * @param {((value?: number) => number)} fn
+ * @param {1 | -1} [d]
+ * @returns {number}
+ */
+export function update_pre_prop(fn, d = 1) {
+ const value = fn() + d;
+ fn(value);
+ return value;
+}
diff --git a/packages/svelte/src/internal/client/reactivity/sources.js b/packages/svelte/src/internal/client/reactivity/sources.js
index d0b6de7cba..050b7faac6 100644
--- a/packages/svelte/src/internal/client/reactivity/sources.js
+++ b/packages/svelte/src/internal/client/reactivity/sources.js
@@ -1,7 +1,25 @@
import { DEV } from 'esm-env';
-import { current_component_context } from '../runtime.js';
+import {
+ current_component_context,
+ current_consumer,
+ current_dependencies,
+ current_effect,
+ current_untracked_writes,
+ current_untracking,
+ flushSync,
+ get,
+ ignore_mutation_validation,
+ is_batching_effect,
+ is_runes,
+ mark_signal_consumers,
+ schedule_effect,
+ set_current_untracked_writes,
+ set_last_inspected_signal,
+ set_signal_status,
+ untrack
+} from '../runtime.js';
import { default_equals, safe_equal } from './equality.js';
-import { CLEAN, SOURCE } from '../constants.js';
+import { CLEAN, DERIVED, DIRTY, MANAGED, SOURCE } from '../constants.js';
/**
* @template V
@@ -68,3 +86,109 @@ function create_source_signal(flags, value) {
w: 0
};
}
+
+/**
+ * @template V
+ * @param {import('./types.js').Signal} signal
+ * @param {V} value
+ * @returns {V}
+ */
+export function set(signal, value) {
+ set_signal_value(signal, value);
+ return value;
+}
+
+/**
+ * @template V
+ * @param {import('./types.js').Signal} signal
+ * @param {V} value
+ * @returns {void}
+ */
+export function set_sync(signal, value) {
+ flushSync(() => set(signal, value));
+}
+
+/**
+ * @template V
+ * @param {import('./types.js').Signal} source
+ * @param {V} value
+ */
+export function mutate(source, value) {
+ set_signal_value(
+ source,
+ untrack(() => get(source))
+ );
+ return value;
+}
+
+/**
+ * @template V
+ * @param {import('./types.js').Signal} signal
+ * @param {V} value
+ * @returns {void}
+ */
+export function set_signal_value(signal, value) {
+ if (
+ !current_untracking &&
+ !ignore_mutation_validation &&
+ current_consumer !== null &&
+ is_runes(null) &&
+ (current_consumer.f & DERIVED) !== 0
+ ) {
+ throw new Error(
+ 'ERR_SVELTE_UNSAFE_MUTATION' +
+ (DEV
+ ? ": Unsafe mutations during Svelte's render or derived phase are not permitted in runes mode. " +
+ 'This can lead to unexpected errors and possibly cause infinite loops.\n\nIf this mutation is not meant ' +
+ 'to be reactive do not use the "$state" rune for that declaration.'
+ : '')
+ );
+ }
+ if (
+ (signal.f & SOURCE) !== 0 &&
+ !(/** @type {import('#client').EqualsFunctions} */ (signal.e)(value, signal.v))
+ ) {
+ signal.v = value;
+ // Increment write version so that unowned signals can properly track dirtyness
+ signal.w++;
+ // If the current signal is running for the first time, it won't have any
+ // consumers as we only allocate and assign the consumers after the signal
+ // has fully executed. So in the case of ensuring it registers the consumer
+ // properly for itself, we need to ensure the current effect actually gets
+ // scheduled. i.e:
+ //
+ // $effect(() => x++)
+ //
+ // We additionally want to skip this logic for when ignore_mutation_validation is
+ // true, as stores write to source signal on initialization.
+ if (
+ is_runes(null) &&
+ !ignore_mutation_validation &&
+ current_effect !== null &&
+ current_effect.c === null &&
+ (current_effect.f & CLEAN) !== 0 &&
+ (current_effect.f & MANAGED) === 0
+ ) {
+ if (current_dependencies !== null && current_dependencies.includes(signal)) {
+ set_signal_status(current_effect, DIRTY);
+ schedule_effect(current_effect, false);
+ } else {
+ if (current_untracked_writes === null) {
+ set_current_untracked_writes([signal]);
+ } else {
+ current_untracked_writes.push(signal);
+ }
+ }
+ }
+ mark_signal_consumers(signal, DIRTY, true);
+
+ // @ts-expect-error
+ if (DEV && signal.inspect) {
+ if (is_batching_effect) {
+ set_last_inspected_signal(/** @type {import('./types.js').SignalDebug} */ (signal));
+ } else {
+ for (const fn of /** @type {import('./types.js').SignalDebug} */ (signal).inspect) fn();
+ }
+ }
+ }
+}
diff --git a/packages/svelte/src/internal/client/reactivity/store.js b/packages/svelte/src/internal/client/reactivity/store.js
index 3680b95052..7226fb879f 100644
--- a/packages/svelte/src/internal/client/reactivity/store.js
+++ b/packages/svelte/src/internal/client/reactivity/store.js
@@ -1,9 +1,9 @@
import { subscribe_to_store } from '../../../store/utils.js';
import { noop } from '../../common.js';
import { UNINITIALIZED } from '../constants.js';
-import { get, set, set_ignore_mutation_validation, untrack } from '../runtime.js';
-import { user_effect } from './computations.js';
-import { mutable_source } from './sources.js';
+import { get, set_ignore_mutation_validation, untrack } from '../runtime.js';
+import { user_effect } from './effects.js';
+import { mutable_source, set } from './sources.js';
/**
* Gets the current value of a store. If the store isn't subscribed to yet, it will create a proxy
diff --git a/packages/svelte/src/internal/client/reactivity/types.d.ts b/packages/svelte/src/internal/client/reactivity/types.d.ts
new file mode 100644
index 0000000000..86c810ff90
--- /dev/null
+++ b/packages/svelte/src/internal/client/reactivity/types.d.ts
@@ -0,0 +1,74 @@
+import type { Block, ComponentContext, EqualsFunctions } from '#client';
+import type { DERIVED, EFFECT, PRE_EFFECT, RENDER_EFFECT, SOURCE } from '../constants';
+
+export type SignalFlags =
+ | typeof SOURCE
+ | typeof DERIVED
+ | typeof EFFECT
+ | typeof PRE_EFFECT
+ | typeof RENDER_EFFECT;
+export type EffectType = typeof EFFECT | typeof PRE_EFFECT | typeof RENDER_EFFECT;
+
+// We keep two shapes rather than a single monomorphic shape to improve the memory usage.
+// Source signals don't need the same shape as they simply don't do as much as computations
+// (effects and derived signals). Thus we can improve the memory profile at the slight cost
+// of some runtime performance.
+
+export type SourceSignal = {
+ /** consumers: Signals that read from the current signal */
+ c: null | ComputationSignal[];
+ /** equals: For value equality */
+ e: null | EqualsFunctions;
+ /** flags: The types that the signal represent, as a bitwise value */
+ f: SignalFlags;
+ /** value: The latest value for this signal */
+ v: V;
+ // write version
+ w: number;
+};
+
+export type SourceSignalDebug = {
+ /** This is DEV only */
+ inspect: Set;
+};
+
+export type ComputationSignal = {
+ /** block: The block associated with this effect/computed */
+ b: null | Block;
+ /** consumers: Signals that read from the current signal */
+ c: null | ComputationSignal[];
+ /** context: The associated component if this signal is an effect/computed */
+ x: null | ComponentContext;
+ /** dependencies: Signals that this signal reads from */
+ d: null | Signal[];
+ /** destroy: Thing(s) that need destroying */
+ y: null | (() => void) | Array<() => void>;
+ /** equals: For value equality */
+ e: null | EqualsFunctions;
+ /** The types that the signal represent, as a bitwise value */
+ f: SignalFlags;
+ /** init: The function that we invoke for effects and computeds */
+ i:
+ | null
+ | (() => V)
+ | (() => void | (() => void))
+ | ((b: Block, s: Signal) => void | (() => void));
+ /** references: Anything that a signal owns */
+ r: null | ComputationSignal[];
+ /** value: The latest value for this signal, doubles as the teardown for effects */
+ v: V;
+ /** level: the depth from the root signal, used for ordering render/pre-effects topologically **/
+ l: number;
+ /** write version: used for unowned signals to track if their depdendencies are dirty or not **/
+ w: number;
+};
+
+export type Signal = SourceSignal | ComputationSignal;
+
+export type SignalDebug = SourceSignalDebug & Signal;
+
+export type EffectSignal = ComputationSignal void)>;
+
+export type MaybeSignal = T | Signal;
+
+export type UnwrappedSignal = T extends Signal ? U : T;
diff --git a/packages/svelte/src/internal/client/render.js b/packages/svelte/src/internal/client/render.js
index 836be712b3..8942e8ad87 100644
--- a/packages/svelte/src/internal/client/render.js
+++ b/packages/svelte/src/internal/client/render.js
@@ -45,19 +45,18 @@ import {
pop,
current_component_context,
get,
- set,
is_signals_recorded,
inspect_fn,
deep_read_state
} from './runtime.js';
+import { derived } from './reactivity/deriveds.js';
import {
render_effect,
effect,
managed_effect,
- derived,
pre_effect,
user_effect
-} from './reactivity/computations.js';
+} from './reactivity/effects.js';
import {
current_hydration_fragment,
get_hydration_fragment,
@@ -76,7 +75,7 @@ import {
} from './utils.js';
import { run } from '../common.js';
import { bind_transition, trigger_transitions } from './transitions.js';
-import { mutable_source, source } from './reactivity/sources.js';
+import { mutable_source, source, set } from './reactivity/sources.js';
import { safe_equal, safe_not_equal } from './reactivity/equality.js';
/** @type {Set} */
diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js
index 6190d16987..ed8d76f6f8 100644
--- a/packages/svelte/src/internal/client/runtime.js
+++ b/packages/svelte/src/internal/client/runtime.js
@@ -10,7 +10,7 @@ import {
object_prototype
} from './utils.js';
import { unstate } from './proxy.js';
-import { pre_effect } from './reactivity/computations.js';
+import { pre_effect } from './reactivity/effects.js';
import {
EACH_BLOCK,
IF_BLOCK,
@@ -31,6 +31,7 @@ import {
} from './constants.js';
import { flush_tasks } from './dom/task.js';
import { add_owner } from './dev/ownership.js';
+import { mutate, set_signal_value } from './reactivity/sources.js';
const IS_EFFECT = EFFECT | PRE_EFFECT | RENDER_EFFECT;
@@ -64,20 +65,32 @@ export let current_consumer = null;
export let current_effect = null;
/** @type {null | import('./types.js').Signal[]} */
-let current_dependencies = null;
+export let current_dependencies = null;
let current_dependencies_index = 0;
/**
* Tracks writes that the effect it's executed in doesn't listen to yet,
* so that the dependency can be added to the effect later on if it then reads it
* @type {null | import('./types.js').Signal[]}
*/
-let current_untracked_writes = null;
+export let current_untracked_writes = null;
+
+/** @param {null | import('./types.js').Signal[]} value */
+export function set_current_untracked_writes(value) {
+ current_untracked_writes = value;
+}
+
/** @type {null | import('./types.js').SignalDebug} */
-let last_inspected_signal = null;
+export let last_inspected_signal = null;
+
+/** @param {null | import('./types.js').SignalDebug} signal */
+export function set_last_inspected_signal(signal) {
+ last_inspected_signal = signal;
+}
+
/** If `true`, `get`ting the signal should not register it as a dependency */
export let current_untracking = false;
/** Exists to opt out of the mutation validation for stores which may be set for the first time during a derivation */
-let ignore_mutation_validation = false;
+export let ignore_mutation_validation = false;
/** @param {boolean} value */
export function set_ignore_mutation_validation(value) {
ignore_mutation_validation = value;
@@ -110,7 +123,7 @@ export let updating_derived = false;
* @param {null | import('./types.js').ComponentContext} context
* @returns {boolean}
*/
-function is_runes(context) {
+export function is_runes(context) {
const component_context = context || current_component_context;
return component_context !== null && component_context.r;
}
@@ -767,27 +780,6 @@ export function get(signal) {
return signal.v;
}
-/**
- * @template V
- * @param {import('./types.js').Signal} signal
- * @param {V} value
- * @returns {V}
- */
-export function set(signal, value) {
- set_signal_value(signal, value);
- return value;
-}
-
-/**
- * @template V
- * @param {import('./types.js').Signal} signal
- * @param {V} value
- * @returns {void}
- */
-export function set_sync(signal, value) {
- flushSync(() => set(signal, value));
-}
-
/**
* Invokes a function and captures all signals that are read during the invocation,
* then invalidates them.
@@ -816,19 +808,6 @@ export function invalidate_inner_signals(fn) {
}
}
-/**
- * @template V
- * @param {import('./types.js').Signal} source
- * @param {V} value
- */
-export function mutate(source, value) {
- set_signal_value(
- source,
- untrack(() => get(source))
- );
- return value;
-}
-
/**
* @param {import('./types.js').ComputationSignal} signal
* @param {boolean} inert
@@ -900,7 +879,7 @@ export function mark_subtree_inert(signal, inert, visited_blocks = new Set()) {
* @param {boolean} force_schedule
* @returns {void}
*/
-function mark_signal_consumers(signal, to_status, force_schedule) {
+export function mark_signal_consumers(signal, to_status, force_schedule) {
const runes = is_runes(null);
const consumers = signal.c;
if (consumers !== null) {
@@ -932,78 +911,6 @@ function mark_signal_consumers(signal, to_status, force_schedule) {
}
}
-/**
- * @template V
- * @param {import('./types.js').Signal} signal
- * @param {V} value
- * @returns {void}
- */
-export function set_signal_value(signal, value) {
- if (
- !current_untracking &&
- !ignore_mutation_validation &&
- current_consumer !== null &&
- is_runes(null) &&
- (current_consumer.f & DERIVED) !== 0
- ) {
- throw new Error(
- 'ERR_SVELTE_UNSAFE_MUTATION' +
- (DEV
- ? ": Unsafe mutations during Svelte's render or derived phase are not permitted in runes mode. " +
- 'This can lead to unexpected errors and possibly cause infinite loops.\n\nIf this mutation is not meant ' +
- 'to be reactive do not use the "$state" rune for that declaration.'
- : '')
- );
- }
- if (
- (signal.f & SOURCE) !== 0 &&
- !(/** @type {import('./types.js').EqualsFunctions} */ (signal.e)(value, signal.v))
- ) {
- signal.v = value;
- // Increment write version so that unowned signals can properly track dirtyness
- signal.w++;
- // If the current signal is running for the first time, it won't have any
- // consumers as we only allocate and assign the consumers after the signal
- // has fully executed. So in the case of ensuring it registers the consumer
- // properly for itself, we need to ensure the current effect actually gets
- // scheduled. i.e:
- //
- // $effect(() => x++)
- //
- // We additionally want to skip this logic for when ignore_mutation_validation is
- // true, as stores write to source signal on initialization.
- if (
- is_runes(null) &&
- !ignore_mutation_validation &&
- current_effect !== null &&
- current_effect.c === null &&
- (current_effect.f & CLEAN) !== 0 &&
- (current_effect.f & MANAGED) === 0
- ) {
- if (current_dependencies !== null && current_dependencies.includes(signal)) {
- set_signal_status(current_effect, DIRTY);
- schedule_effect(current_effect, false);
- } else {
- if (current_untracked_writes === null) {
- current_untracked_writes = [signal];
- } else {
- current_untracked_writes.push(signal);
- }
- }
- }
- mark_signal_consumers(signal, DIRTY, true);
-
- // @ts-expect-error
- if (DEV && signal.inspect) {
- if (is_batching_effect) {
- last_inspected_signal = /** @type {import('./types.js').SignalDebug} */ (signal);
- } else {
- for (const fn of /** @type {import('./types.js').SignalDebug} */ (signal).inspect) fn();
- }
- }
- }
-}
-
/**
* @template V
* @param {import('./types.js').ComputationSignal} signal
@@ -1071,7 +978,7 @@ const STATUS_MASK = ~(DIRTY | MAYBE_DIRTY | CLEAN);
* @param {number} status
* @returns {void}
*/
-function set_signal_status(signal, status) {
+export function set_signal_status(signal, status) {
signal.f = (signal.f & STATUS_MASK) | status;
}
@@ -1208,17 +1115,6 @@ export function update(signal, d = 1) {
return value;
}
-/**
- * @param {((value?: number) => number)} fn
- * @param {1 | -1} [d]
- * @returns {number}
- */
-export function update_prop(fn, d = 1) {
- const value = fn();
- fn(value + d);
- return value;
-}
-
/**
* @param {import('./types.js').Signal} signal
* @param {1 | -1} [d]
@@ -1230,17 +1126,6 @@ export function update_pre(signal, d = 1) {
return value;
}
-/**
- * @param {((value?: number) => number)} fn
- * @param {1 | -1} [d]
- * @returns {number}
- */
-export function update_pre_prop(fn, d = 1) {
- const value = fn() + d;
- fn(value);
- return value;
-}
-
/**
* @param {Record} obj
* @param {string[]} keys
diff --git a/packages/svelte/src/internal/client/transitions.js b/packages/svelte/src/internal/client/transitions.js
index 59eb3ad60d..deb3a27598 100644
--- a/packages/svelte/src/internal/client/transitions.js
+++ b/packages/svelte/src/internal/client/transitions.js
@@ -12,7 +12,7 @@ import {
import { destroy_each_item_block, get_first_element } from './dom/blocks/each.js';
import { schedule_raf_task } from './dom/task.js';
import { append_child, empty } from './operations.js';
-import { effect, managed_effect, managed_pre_effect } from './reactivity/computations.js';
+import { effect, managed_effect, managed_pre_effect } from './reactivity/effects.js';
import {
current_block,
current_effect,
diff --git a/packages/svelte/src/internal/client/types.d.ts b/packages/svelte/src/internal/client/types.d.ts
index 028f81af43..853b960717 100644
--- a/packages/svelte/src/internal/client/types.d.ts
+++ b/packages/svelte/src/internal/client/types.d.ts
@@ -1,9 +1,4 @@
import {
- DERIVED,
- EFFECT,
- RENDER_EFFECT,
- SOURCE,
- PRE_EFFECT,
ROOT_BLOCK,
EACH_BLOCK,
EACH_ITEM_BLOCK,
@@ -16,16 +11,7 @@ import {
SNIPPET_BLOCK,
STATE_SYMBOL
} from './constants.js';
-
-// Put all internal types in this file. Once we convert to JSDoc, we can make this a d.ts file
-
-export type SignalFlags =
- | typeof SOURCE
- | typeof DERIVED
- | typeof EFFECT
- | typeof PRE_EFFECT
- | typeof RENDER_EFFECT;
-export type EffectType = typeof EFFECT | typeof PRE_EFFECT | typeof RENDER_EFFECT;
+import type { ComputationSignal, EffectSignal, Signal, SourceSignal } from './reactivity/types.js';
type EventCallback = (event: Event) => boolean;
export type EventCallbackMap = Record;
@@ -67,70 +53,6 @@ export type ComponentContext = {
};
};
-// We keep two shapes rather than a single monomorphic shape to improve the memory usage.
-// Source signals don't need the same shape as they simply don't do as much as computations
-// (effects and derived signals). Thus we can improve the memory profile at the slight cost
-// of some runtime performance.
-
-export type SourceSignal = {
- /** consumers: Signals that read from the current signal */
- c: null | ComputationSignal[];
- /** equals: For value equality */
- e: null | EqualsFunctions;
- /** flags: The types that the signal represent, as a bitwise value */
- f: SignalFlags;
- /** value: The latest value for this signal */
- v: V;
- // write version
- w: number;
-};
-
-export type SourceSignalDebug = {
- /** This is DEV only */
- inspect: Set;
-};
-
-export type ComputationSignal = {
- /** block: The block associated with this effect/computed */
- b: null | Block;
- /** consumers: Signals that read from the current signal */
- c: null | ComputationSignal[];
- /** context: The associated component if this signal is an effect/computed */
- x: null | ComponentContext;
- /** dependencies: Signals that this signal reads from */
- d: null | Signal[];
- /** destroy: Thing(s) that need destroying */
- y: null | (() => void) | Array<() => void>;
- /** equals: For value equality */
- e: null | EqualsFunctions;
- /** The types that the signal represent, as a bitwise value */
- f: SignalFlags;
- /** init: The function that we invoke for effects and computeds */
- i:
- | null
- | (() => V)
- | (() => void | (() => void))
- | ((b: Block, s: Signal) => void | (() => void));
- /** references: Anything that a signal owns */
- r: null | ComputationSignal[];
- /** value: The latest value for this signal, doubles as the teardown for effects */
- v: V;
- /** level: the depth from the root signal, used for ordering render/pre-effects topologically **/
- l: number;
- /** write version: used for unowned signals to track if their depdendencies are dirty or not **/
- w: number;
-};
-
-export type Signal = SourceSignal | ComputationSignal;
-
-export type SignalDebug = SourceSignalDebug & Signal;
-
-export type EffectSignal = ComputationSignal void)>;
-
-export type MaybeSignal = T | Signal;
-
-export type UnwrappedSignal = T extends Signal ? U : T;
-
export type EqualsFunctions = (a: T, v: T) => boolean;
export type BlockType =
@@ -421,3 +343,5 @@ export interface ProxyMetadata> {
export type ProxyStateObject> = T & {
[STATE_SYMBOL]: ProxyMetadata;
};
+
+export * from './reactivity/types';
diff --git a/packages/svelte/src/internal/index.js b/packages/svelte/src/internal/index.js
index cb57244def..1503477eb5 100644
--- a/packages/svelte/src/internal/index.js
+++ b/packages/svelte/src/internal/index.js
@@ -1,16 +1,11 @@
export {
get,
- set,
- set_sync,
invalidate_inner_signals,
flushSync,
tick,
untrack,
update,
- update_prop,
update_pre,
- update_pre_prop,
- mutate,
value_or_fallback,
exclude_from_object,
pop,
@@ -30,9 +25,11 @@ export { await_block as await } from './client/dom/blocks/await.js';
export { if_block as if } from './client/dom/blocks/if.js';
export { key_block as key } from './client/dom/blocks/key.js';
export * from './client/dom/blocks/each.js';
-export * from './client/reactivity/computations.js';
+export * from './client/reactivity/deriveds.js';
+export * from './client/reactivity/effects.js';
export * from './client/reactivity/sources.js';
export * from './client/reactivity/equality.js';
+export * from './client/reactivity/props.js';
export * from './client/reactivity/store.js';
export * from './client/render.js';
export * from './client/validate.js';
diff --git a/packages/svelte/src/reactivity/index.js b/packages/svelte/src/reactivity/index.js
index b68cef7be3..f802121a2e 100644
--- a/packages/svelte/src/reactivity/index.js
+++ b/packages/svelte/src/reactivity/index.js
@@ -1,5 +1,5 @@
-import { source } from '../internal/client/reactivity/sources.js';
-import { get, set } from '../internal/client/runtime.js';
+import { source, set } from '../internal/client/reactivity/sources.js';
+import { get } from '../internal/client/runtime.js';
/** @type {Array} */
const read = [
diff --git a/packages/svelte/tests/signals/test.ts b/packages/svelte/tests/signals/test.ts
index 0df1218f57..a0c8454600 100644
--- a/packages/svelte/tests/signals/test.ts
+++ b/packages/svelte/tests/signals/test.ts
@@ -1,12 +1,8 @@
import { describe, assert, it } from 'vitest';
import * as $ from '../../src/internal/client/runtime';
-import {
- derived,
- effect,
- render_effect,
- user_effect
-} from '../../src/internal/client/reactivity/computations';
-import { source } from '../../src/internal/client/reactivity/sources';
+import { derived } from '../../src/internal/client/reactivity/deriveds';
+import { effect, render_effect, user_effect } from '../../src/internal/client/reactivity/effects';
+import { source, set } from '../../src/internal/client/reactivity/sources';
import type { ComputationSignal } from '../../src/internal/client/types';
import { proxy } from '../../src/internal/client/proxy';
@@ -51,8 +47,8 @@ describe('signals', () => {
});
return () => {
- $.flushSync(() => $.set(count, 1));
- $.flushSync(() => $.set(count, 2));
+ $.flushSync(() => set(count, 1));
+ $.flushSync(() => set(count, 2));
assert.deepEqual(log, ['0:0', '1:2', '2:4']);
};
@@ -72,8 +68,8 @@ describe('signals', () => {
});
return () => {
- $.flushSync(() => $.set(count, 1));
- $.flushSync(() => $.set(count, 2));
+ $.flushSync(() => set(count, 1));
+ $.flushSync(() => set(count, 2));
assert.deepEqual(log, ['A:0:0', 'B:0', 'A:1:2', 'B:2', 'A:2:4', 'B:4']);
};
@@ -93,8 +89,8 @@ describe('signals', () => {
});
return () => {
- $.flushSync(() => $.set(count, 1));
- $.flushSync(() => $.set(count, 2));
+ $.flushSync(() => set(count, 1));
+ $.flushSync(() => set(count, 2));
assert.deepEqual(log, ['A:0', 'B:0:0', 'A:2', 'B:1:2', 'A:4', 'B:2:4']);
};
@@ -111,8 +107,8 @@ describe('signals', () => {
});
return () => {
- $.flushSync(() => $.set(count, 1));
- $.flushSync(() => $.set(count, 2));
+ $.flushSync(() => set(count, 1));
+ $.flushSync(() => set(count, 2));
assert.deepEqual(log, [0, 2, 4]);
};
@@ -130,8 +126,8 @@ describe('signals', () => {
});
return () => {
- $.flushSync(() => $.set(count, 1));
- $.flushSync(() => $.set(count, 2));
+ $.flushSync(() => set(count, 1));
+ $.flushSync(() => set(count, 2));
assert.deepEqual(log, [0, 4, 8]);
};
@@ -167,12 +163,12 @@ describe('signals', () => {
let i = 2;
while (--i) {
res.length = 0;
- $.set(B, 1);
- $.set(A, 1 + i * 2);
+ set(B, 1);
+ set(A, 1 + i * 2);
$.flushSync();
- $.set(A, 2 + i * 2);
- $.set(B, 2);
+ set(A, 2 + i * 2);
+ set(B, 2);
$.flushSync();
assert.equal(res.length, 4);
@@ -195,13 +191,13 @@ describe('signals', () => {
});
return () => {
- $.flushSync(() => $.set(count, 1));
+ $.flushSync(() => set(count, 1));
// Ensure we're not leaking consumers
assert.deepEqual(count.c?.length, 1);
- $.flushSync(() => $.set(count, 2));
+ $.flushSync(() => set(count, 2));
// Ensure we're not leaking consumers
assert.deepEqual(count.c?.length, 1);
- $.flushSync(() => $.set(count, 3));
+ $.flushSync(() => set(count, 3));
// Ensure we're not leaking consumers
assert.deepEqual(count.c?.length, 1);
assert.deepEqual(log, [0, 1, 2, 3]);
@@ -224,11 +220,11 @@ describe('signals', () => {
$.get(c);
- $.flushSync(() => $.set(a, 1));
+ $.flushSync(() => set(a, 1));
$.get(c);
- $.flushSync(() => $.set(b, 1));
+ $.flushSync(() => set(b, 1));
$.get(c);
@@ -257,11 +253,11 @@ describe('signals', () => {
});
return () => {
- $.flushSync(() => $.set(count, 1));
- $.flushSync(() => $.set(count, 2));
- $.flushSync(() => $.set(count, 3));
- $.flushSync(() => $.set(count, 4));
- $.flushSync(() => $.set(count, 0));
+ $.flushSync(() => set(count, 1));
+ $.flushSync(() => set(count, 2));
+ $.flushSync(() => set(count, 3));
+ $.flushSync(() => set(count, 4));
+ $.flushSync(() => set(count, 0));
// Ensure we're not leaking consumers
assert.deepEqual(count.c?.length, 1);
assert.deepEqual(log, [0, 2, 'limit', 0]);
@@ -319,7 +315,7 @@ describe('signals', () => {
const value = source({ count: 0 });
user_effect(() => {
- $.set(value, { count: 0 });
+ set(value, { count: 0 });
$.get(value);
});