From 35157760096f9975e942908b658637e41a021f7e Mon Sep 17 00:00:00 2001
From: Simon H <5968653+dummdidumm@users.noreply.github.com>
Date: Thu, 25 Jul 2024 16:36:43 +0200
Subject: [PATCH] docs: tweak `$state.is` warning (#12599)
Also add a detailed explanation which can later appear on the docs site
closes #11556
---
.../messages/client-warnings/warnings.md | 22 ++++++++++++++++++-
.../svelte/scripts/process-messages/index.js | 2 +-
.../src/internal/client/dev/equality.js | 19 +++++++++++-----
.../svelte/src/internal/client/warnings.js | 7 +++---
4 files changed, 40 insertions(+), 10 deletions(-)
diff --git a/packages/svelte/messages/client-warnings/warnings.md b/packages/svelte/messages/client-warnings/warnings.md
index 7a5a495251..695776dd60 100644
--- a/packages/svelte/messages/client-warnings/warnings.md
+++ b/packages/svelte/messages/client-warnings/warnings.md
@@ -40,4 +40,24 @@
## state_proxy_equality_mismatch
-> Reactive `$state(...)` proxies and the values they proxy have different identities. Because of this, comparisons with `%operator%` will produce unexpected results. Consider using `$state.is(a, b)` instead
+> Reactive `$state(...)` proxies and the values they proxy have different identities. Because of this, comparisons with `%operator%` will produce unexpected results. Consider using `$state.is(a, b)` instead%details%
+
+`$state(...)` does create a proxy of the value it is passed. Therefore, the resulting object has a different identity and equality checks will always return `false`:
+
+```svelte
+
+```
+
+Most of the time this will not be a problem in practise because it is very rare to keep the original value around to later compare it against a state value. In case it happens, Svelte will warn you about it in development mode and suggest to use `$state.is` instead, which is able to unwrap the proxy and compare the original values:
+
+```svelte
+
+```
diff --git a/packages/svelte/scripts/process-messages/index.js b/packages/svelte/scripts/process-messages/index.js
index 5eea56fa04..8ee58cad9d 100644
--- a/packages/svelte/scripts/process-messages/index.js
+++ b/packages/svelte/scripts/process-messages/index.js
@@ -33,7 +33,7 @@ for (const category of fs.readdirSync('messages')) {
const sections = text.trim().split('\n\n');
let details = null;
- if (!sections[sections.length - 1].startsWith('> ')) {
+ while (!sections[sections.length - 1].startsWith('> ')) {
details = /** @type {string} */ (sections.pop());
}
diff --git a/packages/svelte/src/internal/client/dev/equality.js b/packages/svelte/src/internal/client/dev/equality.js
index c1c392ba87..67fc039da1 100644
--- a/packages/svelte/src/internal/client/dev/equality.js
+++ b/packages/svelte/src/internal/client/dev/equality.js
@@ -20,7 +20,10 @@ export function init_array_prototype_warnings() {
const test = indexOf.call(get_proxied_value(this), get_proxied_value(item), from_index);
if (test !== -1) {
- w.state_proxy_equality_mismatch('array.indexOf(...)');
+ w.state_proxy_equality_mismatch(
+ 'array.indexOf(...)',
+ ': `array.findIndex(entry => $state.is(entry, item))`'
+ );
}
}
@@ -42,7 +45,10 @@ export function init_array_prototype_warnings() {
);
if (test !== -1) {
- w.state_proxy_equality_mismatch('array.lastIndexOf(...)');
+ w.state_proxy_equality_mismatch(
+ 'array.lastIndexOf(...)',
+ ': `array.findLastIndex(entry => $state.is(entry, item))`'
+ );
}
}
@@ -56,7 +62,10 @@ export function init_array_prototype_warnings() {
const test = includes.call(get_proxied_value(this), get_proxied_value(item), from_index);
if (test) {
- w.state_proxy_equality_mismatch('array.includes(...)');
+ w.state_proxy_equality_mismatch(
+ 'array.includes(...)',
+ ': `array.some(entry => $state.is(entry, item))`'
+ );
}
}
@@ -79,7 +88,7 @@ export function init_array_prototype_warnings() {
*/
export function strict_equals(a, b, equal = true) {
if ((a === b) !== (get_proxied_value(a) === get_proxied_value(b))) {
- w.state_proxy_equality_mismatch(equal ? '===' : '!==');
+ w.state_proxy_equality_mismatch(equal ? '===' : '!==', '');
}
return (a === b) === equal;
@@ -93,7 +102,7 @@ export function strict_equals(a, b, equal = true) {
*/
export function equals(a, b, equal = true) {
if ((a == b) !== (get_proxied_value(a) == get_proxied_value(b))) {
- w.state_proxy_equality_mismatch(equal ? '==' : '!=');
+ w.state_proxy_equality_mismatch(equal ? '==' : '!=', '');
}
return (a == b) === equal;
diff --git a/packages/svelte/src/internal/client/warnings.js b/packages/svelte/src/internal/client/warnings.js
index 31f67a725a..23c00f971d 100644
--- a/packages/svelte/src/internal/client/warnings.js
+++ b/packages/svelte/src/internal/client/warnings.js
@@ -114,12 +114,13 @@ export function ownership_invalid_mutation(component, owner) {
}
/**
- * Reactive `$state(...)` proxies and the values they proxy have different identities. Because of this, comparisons with `%operator%` will produce unexpected results. Consider using `$state.is(a, b)` instead
+ * Reactive `$state(...)` proxies and the values they proxy have different identities. Because of this, comparisons with `%operator%` will produce unexpected results. Consider using `$state.is(a, b)` instead%details%
* @param {string} operator
+ * @param {string} details
*/
-export function state_proxy_equality_mismatch(operator) {
+export function state_proxy_equality_mismatch(operator, details) {
if (DEV) {
- console.warn(`%c[svelte] state_proxy_equality_mismatch\n%cReactive \`$state(...)\` proxies and the values they proxy have different identities. Because of this, comparisons with \`${operator}\` will produce unexpected results. Consider using \`$state.is(a, b)\` instead`, bold, normal);
+ console.warn(`%c[svelte] state_proxy_equality_mismatch\n%cReactive \`$state(...)\` proxies and the values they proxy have different identities. Because of this, comparisons with \`${operator}\` will produce unexpected results. Consider using \`$state.is(a, b)\` instead${details}`, bold, normal);
} else {
// TODO print a link to the documentation
console.warn("state_proxy_equality_mismatch");