diff --git a/CHANGELOG.md b/CHANGELOG.md index cc53511860..63f4f0fa2a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Svelte changelog +## Unreleased + +* Fix reactivity when passing `$$props` to a `` ([#3364](https://github.com/sveltejs/svelte/issues/3364)) + ## 3.24.0 * Support nullish coalescing (`??`) and optional chaining (`?.`) operators ([#1972](https://github.com/sveltejs/svelte/issues/1972)) diff --git a/src/compiler/compile/render_dom/wrappers/Slot.ts b/src/compiler/compile/render_dom/wrappers/Slot.ts index 268875acaf..bf808196c0 100644 --- a/src/compiler/compile/render_dom/wrappers/Slot.ts +++ b/src/compiler/compile/render_dom/wrappers/Slot.ts @@ -7,6 +7,7 @@ import { b, p, x } from 'code-red'; import { sanitize } from '../../../utils/names'; import add_to_set from '../../utils/add_to_set'; import get_slot_data from '../../utils/get_slot_data'; +import { is_reserved_keyword } from '../../utils/reserved_keywords'; import Expression from '../../nodes/shared/Expression'; import is_dynamic from './shared/is_dynamic'; import { Identifier, ObjectExpression } from 'estree'; @@ -94,11 +95,7 @@ export default class SlotWrapper extends Wrapper { } }); - const dynamic_dependencies = Array.from(attribute.dependencies).filter(name => { - if (this.node.scope.is_let(name)) return true; - const variable = renderer.component.var_lookup.get(name); - return is_dynamic(variable); - }); + const dynamic_dependencies = Array.from(attribute.dependencies).filter((name) => this.is_dependency_dynamic(name)); if (dynamic_dependencies.length > 0) { changes.properties.push(p`${attribute.name}: ${renderer.dirty(dynamic_dependencies)}`); @@ -157,17 +154,10 @@ export default class SlotWrapper extends Wrapper { b`@transition_out(${slot_or_fallback}, #local);` ); - const is_dependency_dynamic = name => { - if (name === '$$scope') return true; - if (this.node.scope.is_let(name)) return true; - const variable = renderer.component.var_lookup.get(name); - return is_dynamic(variable); - }; - - const dynamic_dependencies = Array.from(this.dependencies).filter(is_dependency_dynamic); + const dynamic_dependencies = Array.from(this.dependencies).filter((name) => this.is_dependency_dynamic(name)); const fallback_dynamic_dependencies = has_fallback - ? Array.from(this.fallback.dependencies).filter(is_dependency_dynamic) + ? Array.from(this.fallback.dependencies).filter((name) => this.is_dependency_dynamic(name)) : []; const slot_update = b` @@ -201,4 +191,12 @@ export default class SlotWrapper extends Wrapper { b`if (${slot_or_fallback}) ${slot_or_fallback}.d(detaching);` ); } + + is_dependency_dynamic(name: string) { + if (name === '$$scope') return true; + if (this.node.scope.is_let(name)) return true; + if (is_reserved_keyword(name)) return true; + const variable = this.renderer.component.var_lookup.get(name); + return is_dynamic(variable); + } } diff --git a/test/runtime/samples/props-reactive-slot/Comp.svelte b/test/runtime/samples/props-reactive-slot/Comp.svelte new file mode 100644 index 0000000000..bf9e12a58a --- /dev/null +++ b/test/runtime/samples/props-reactive-slot/Comp.svelte @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/test/runtime/samples/props-reactive-slot/_config.js b/test/runtime/samples/props-reactive-slot/_config.js new file mode 100644 index 0000000000..286bba2f08 --- /dev/null +++ b/test/runtime/samples/props-reactive-slot/_config.js @@ -0,0 +1,21 @@ +export default { + html: ` +

hi

+ + `, + + async test({ assert, component, target, window }) { + const btn = target.querySelector("button"); + const clickEvent = new window.MouseEvent("click"); + + await btn.dispatchEvent(clickEvent); + + assert.htmlEqual( + target.innerHTML, + ` +

changed

+ + ` + ); + }, +}; diff --git a/test/runtime/samples/props-reactive-slot/main.svelte b/test/runtime/samples/props-reactive-slot/main.svelte new file mode 100644 index 0000000000..84777bf8ab --- /dev/null +++ b/test/runtime/samples/props-reactive-slot/main.svelte @@ -0,0 +1,13 @@ + + + +

+ {props.someprop} +

+
+ + \ No newline at end of file