Skip to content

Commit

Permalink
fix: show :then block for null value (#14440)
Browse files Browse the repository at this point in the history
fixes #14439

This bug was introduced in #13642 because setting the input to null means the equality check ("is the input different") fails if you set the value to null

Also fixes #14441 - this bug was present for a long time, and the reason is the same as for the other bug: The equality check always returns "yes this is the same" if the value is undefined initially. The fix is similar; we need to initialize the input to something that can never be equal to whatever value is passed
  • Loading branch information
dummdidumm authored Nov 26, 2024
1 parent 9e9fb24 commit 3fa08d5
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 12 deletions.
5 changes: 5 additions & 0 deletions .changeset/breezy-insects-live.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'svelte': patch
---

fix: show `:then` block for `null/undefined` value
9 changes: 5 additions & 4 deletions packages/svelte/src/internal/client/dom/blocks/await.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
} from '../../runtime.js';
import { hydrate_next, hydrate_node, hydrating } from '../hydration.js';
import { queue_micro_task } from '../task.js';
import { UNINITIALIZED } from '../../../../constants.js';

const PENDING = 0;
const THEN = 1;
Expand All @@ -40,8 +41,8 @@ export function await_block(node, get_input, pending_fn, then_fn, catch_fn) {
/** @type {any} */
var component_function = DEV ? component_context?.function : null;

/** @type {V | Promise<V> | null} */
var input;
/** @type {V | Promise<V> | typeof UNINITIALIZED} */
var input = UNINITIALIZED;

/** @type {Effect | null} */
var pending_effect;
Expand Down Expand Up @@ -156,8 +157,8 @@ export function await_block(node, get_input, pending_fn, then_fn, catch_fn) {
update(THEN, false);
}

// Set the input to null, in order to disable the promise callbacks
return () => (input = null);
// Set the input to something else, in order to disable the promise callbacks
return () => (input = UNINITIALIZED);
});

if (hydrating) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,27 @@
import { flushSync } from 'svelte';
import { test } from '../../test';
import { ok, test } from '../../test';

export default test({
compileOptions: {
dev: true
},
test() {}
test({ assert, target }) {
const [btn1, btn2] = target.querySelectorAll('button');
const p = target.querySelector('p');
ok(p);

assert.htmlEqual(p.outerHTML, `<p></p>`);

btn1.click();
flushSync();
assert.htmlEqual(p.outerHTML, `<p>1</p>`);

btn2.click();
flushSync();
assert.htmlEqual(p.outerHTML, `<p></p>`);

btn1.click();
flushSync();
assert.htmlEqual(p.outerHTML, `<p>1</p>`);
}
});
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
<script>
let count = $state(43);
let count = $state();
</script>

{#await count}
loading
{:then count}
{count}
{/await}
<button onclick={() => count = 1}>number</button>
<button onclick={() => count = null}>nullify</button>

<p>
{#await count}
loading
{:then count}
{count}
{/await}
</p>

0 comments on commit 3fa08d5

Please sign in to comment.