Skip to content

Commit 7834ca3

Browse files
authored
fix slot with context overflow + without let (#4862)
1 parent 185706f commit 7834ca3

File tree

5 files changed

+79
-4
lines changed

5 files changed

+79
-4
lines changed

src/compiler/compile/render_dom/wrappers/Slot.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -172,10 +172,7 @@ export default class SlotWrapper extends Wrapper {
172172

173173
const slot_update = b`
174174
if (${slot}.p && ${renderer.dirty(dynamic_dependencies)}) {
175-
${slot}.p(
176-
@get_slot_context(${slot_definition}, #ctx, ${renderer.reference('$$scope')}, ${get_slot_context_fn}),
177-
@get_slot_changes(${slot_definition}, ${renderer.reference('$$scope')}, #dirty, ${get_slot_changes_fn})
178-
);
175+
@update_slot(${slot}, ${slot_definition}, #ctx, ${renderer.reference('$$scope')}, #dirty, ${get_slot_changes_fn}, ${get_slot_context_fn});
179176
}
180177
`;
181178
const fallback_update = has_fallback && fallback_dynamic_dependencies.length > 0 && b`

src/runtime/internal/utils.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,14 @@ export function get_slot_changes(definition, $$scope, dirty, fn) {
103103
return $$scope.dirty;
104104
}
105105

106+
export function update_slot(slot, slot_definition, ctx, $$scope, dirty, get_slot_changes_fn, get_slot_context_fn) {
107+
const slot_changes = get_slot_changes(slot_definition, $$scope, dirty, get_slot_changes_fn);
108+
if (slot_changes) {
109+
const slot_context = get_slot_context(slot_definition, ctx, $$scope, get_slot_context_fn);
110+
slot.p(slot_context, slot_changes);
111+
}
112+
}
113+
106114
export function exclude_internal_props(props) {
107115
const result = {};
108116
for (const k in props) if (k[0] !== '$') result[k] = props[k];
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<script>
2+
let open = false;
3+
function toggle() {
4+
open = !open;
5+
}
6+
</script>
7+
8+
<div on:click={toggle}>
9+
<slot name="target" {open}></slot>
10+
11+
<!-- This actually isn't necessary to reproduce. -->
12+
{#if open}
13+
<slot name="content"></slot>
14+
{/if}
15+
</div>
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// overflow bitmask + slot missing `let:`
2+
export default {
3+
html: `
4+
<div>
5+
<button slot="target">Toggle inside 1</button>
6+
</div>
7+
<button>Toggle outside</button>
8+
`,
9+
10+
async test({ assert, component, target, window }) {
11+
const button = target.querySelectorAll('button')[1];
12+
const div = target.querySelector('div');
13+
await div.dispatchEvent(new window.MouseEvent('click'));
14+
15+
assert.htmlEqual(target.innerHTML, `
16+
<div>
17+
<button slot="target">Toggle inside 1</button>
18+
<div slot="content">Open</div>
19+
</div>
20+
<button>Toggle outside</button>
21+
`);
22+
23+
await button.dispatchEvent(new window.MouseEvent('click'));
24+
assert.htmlEqual(target.innerHTML, `
25+
<div>
26+
<button slot="target">Toggle inside 2</button>
27+
<div slot="content">Open</div>
28+
</div>
29+
<button>Toggle outside</button>
30+
`);
31+
}
32+
};
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<script>
2+
import Slotted from './Slotted.svelte';
3+
let lotsOfNumbers = Array.from({length: 50}, () => 1);
4+
5+
let [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, aa, ab, ac, ad, ae, af, ag, ah] = lotsOfNumbers;
6+
7+
let last = 1;
8+
function toggle () {
9+
last = 2;
10+
}
11+
</script>
12+
13+
<Slotted>
14+
<button slot="target">
15+
Toggle inside {last}
16+
</button>
17+
18+
<div slot="content">
19+
Open
20+
</div>
21+
</Slotted>
22+
23+
<button on:click={toggle}>Toggle outside</button>

0 commit comments

Comments
 (0)