diff --git a/src/compiler/compile/render_dom/wrappers/Slot.ts b/src/compiler/compile/render_dom/wrappers/Slot.ts
index 937a75b0aa..09366dcaaf 100644
--- a/src/compiler/compile/render_dom/wrappers/Slot.ts
+++ b/src/compiler/compile/render_dom/wrappers/Slot.ts
@@ -107,7 +107,7 @@ export default class SlotWrapper extends Wrapper {
if (spread_dynamic_dependencies.size) {
get_slot_spread_changes_fn = renderer.component.get_unique_name(`get_${sanitize(slot_name)}_slot_spread_changes`);
renderer.blocks.push(b`
- const ${get_slot_spread_changes_fn} = #dirty => ${renderer.dirty(Array.from(spread_dynamic_dependencies))} > 0 ? -1 : 0;
+ const ${get_slot_spread_changes_fn} = #dirty => ${renderer.dirty(Array.from(spread_dynamic_dependencies))};
`);
}
} else {
@@ -168,27 +168,41 @@ export default class SlotWrapper extends Wrapper {
if (block.has_outros) {
condition = x`!#current || ${condition}`;
}
- let dirty = x`#dirty`;
- if (block.has_outros) {
- dirty = x`!#current ? ${renderer.get_initial_dirty()} : ${dirty}`;
+
+ // conditions to treat everything as dirty
+ const all_dirty_conditions = [
+ get_slot_spread_changes_fn ? x`${get_slot_spread_changes_fn}(#dirty)` : null,
+ block.has_outros ? x`!#current` : null
+ ].filter(Boolean);
+ const all_dirty_condition = all_dirty_conditions.length ? all_dirty_conditions.reduce((condition1, condition2) => x`${condition1} || ${condition2}`): null;
+
+ let slot_update;
+ if (all_dirty_condition) {
+ const dirty = x`${all_dirty_condition} ? @get_all_dirty_from_scope(${renderer.reference('$$scope')}) : @get_slot_changes(${slot_definition}, ${renderer.reference('$$scope')}, #dirty, ${get_slot_changes_fn})`;
+
+ slot_update = b`
+ if (${slot}.p && ${condition}) {
+ @update_slot_base(${slot}, ${slot_definition}, #ctx, ${renderer.reference('$$scope')}, ${dirty}, ${get_slot_context_fn});
+ }
+ `;
+ } else {
+ slot_update = b`
+ if (${slot}.p && ${condition}) {
+ @update_slot(${slot}, ${slot_definition}, #ctx, ${renderer.reference('$$scope')}, #dirty, ${get_slot_changes_fn}, ${get_slot_context_fn});
+ }
+ `;
}
- const slot_update = get_slot_spread_changes_fn ? b`
- if (${slot}.p && ${condition}) {
- @update_slot_spread(${slot}, ${slot_definition}, #ctx, ${renderer.reference('$$scope')}, ${dirty}, ${get_slot_changes_fn}, ${get_slot_spread_changes_fn}, ${get_slot_context_fn});
- }
- ` : b`
- if (${slot}.p && ${condition}) {
- @update_slot(${slot}, ${slot_definition}, #ctx, ${renderer.reference('$$scope')}, ${dirty}, ${get_slot_changes_fn}, ${get_slot_context_fn});
- }
- `;
let fallback_condition = renderer.dirty(fallback_dynamic_dependencies);
+ let fallback_dirty = x`#dirty`;
if (block.has_outros) {
fallback_condition = x`!#current || ${fallback_condition}`;
+ fallback_dirty = x`!#current ? ${renderer.get_initial_dirty()} : ${fallback_dirty}`;
}
+
const fallback_update = has_fallback && fallback_dynamic_dependencies.length > 0 && b`
if (${slot_or_fallback} && ${slot_or_fallback}.p && ${fallback_condition}) {
- ${slot_or_fallback}.p(#ctx, ${dirty});
+ ${slot_or_fallback}.p(#ctx, ${fallback_dirty});
}
`;
diff --git a/src/runtime/internal/utils.ts b/src/runtime/internal/utils.ts
index 646851d0a5..8868e38ee2 100644
--- a/src/runtime/internal/utils.ts
+++ b/src/runtime/internal/utils.ts
@@ -119,20 +119,28 @@ export function get_slot_changes(definition, $$scope, dirty, fn) {
return $$scope.dirty;
}
-export function update_slot(slot, slot_definition, ctx, $$scope, dirty, get_slot_changes_fn, get_slot_context_fn) {
- const slot_changes = get_slot_changes(slot_definition, $$scope, dirty, get_slot_changes_fn);
+export function update_slot_base(slot, slot_definition, ctx, $$scope, slot_changes, get_slot_context_fn) {
if (slot_changes) {
const slot_context = get_slot_context(slot_definition, ctx, $$scope, get_slot_context_fn);
slot.p(slot_context, slot_changes);
}
}
-export function update_slot_spread(slot, slot_definition, ctx, $$scope, dirty, get_slot_changes_fn, get_slot_spread_changes_fn, get_slot_context_fn) {
- const slot_changes = get_slot_spread_changes_fn(dirty) | get_slot_changes(slot_definition, $$scope, dirty, get_slot_changes_fn);
- if (slot_changes) {
- const slot_context = get_slot_context(slot_definition, ctx, $$scope, get_slot_context_fn);
- slot.p(slot_context, slot_changes);
+export function update_slot(slot, slot_definition, ctx, $$scope, dirty, get_slot_changes_fn, get_slot_context_fn) {
+ const slot_changes = get_slot_changes(slot_definition, $$scope, dirty, get_slot_changes_fn);
+ update_slot_base(slot, slot_definition, ctx, $$scope, slot_changes, get_slot_context_fn);
+}
+
+export function get_all_dirty_from_scope($$scope) {
+ if ($$scope.ctx.length > 32) {
+ const dirty = [];
+ const length = $$scope.ctx.length / 32;
+ for (let i = 0; i < length; i++) {
+ dirty[i] = -1;
+ }
+ return dirty;
}
+ return -1;
}
export function exclude_internal_props(props) {
diff --git a/test/runtime/samples/transition-js-slot-2/_config.js b/test/runtime/samples/transition-js-slot-2/_config.js
index 67cc0b46d2..0f0cad5e41 100644
--- a/test/runtime/samples/transition-js-slot-2/_config.js
+++ b/test/runtime/samples/transition-js-slot-2/_config.js
@@ -1,3 +1,4 @@
+// cancelled the transition halfway
export default {
html: `
Foo
diff --git a/test/runtime/samples/transition-js-slot-4-cancelled/Nested.svelte b/test/runtime/samples/transition-js-slot-4-cancelled/Nested.svelte
new file mode 100644
index 0000000000..04eea750fd
--- /dev/null
+++ b/test/runtime/samples/transition-js-slot-4-cancelled/Nested.svelte
@@ -0,0 +1,19 @@
+
+
+{#if visible}
+
+
+
+{/if}
\ No newline at end of file
diff --git a/test/runtime/samples/transition-js-slot-4-cancelled/_config.js b/test/runtime/samples/transition-js-slot-4-cancelled/_config.js
new file mode 100644
index 0000000000..d6b7c31132
--- /dev/null
+++ b/test/runtime/samples/transition-js-slot-4-cancelled/_config.js
@@ -0,0 +1,35 @@
+// updated props in the middle of transitions
+// and cancelled the transition halfway
+export default {
+ html: `
+ outside Foo Foo Foo
+ inside Foo Foo Foo
+ `,
+ props: {
+ props: 'Foo'
+ },
+
+ async test({ assert, component, target, window, raf }) {
+ await component.hide();
+ const [, div] = target.querySelectorAll('div');
+
+ raf.tick(50);
+ assert.equal(div.foo, 0.5);
+
+ component.props = 'Bar';
+ assert.htmlEqual(target.innerHTML, `
+ outside Bar Bar Bar
+ inside Foo Foo Foo
+ `);
+
+ await component.show();
+
+ assert.htmlEqual(target.innerHTML, `
+ outside Bar Bar Bar
+ inside Bar Bar Bar
+ `);
+
+ raf.tick(100);
+ assert.equal(div.foo, 1);
+ }
+};
diff --git a/test/runtime/samples/transition-js-slot-4-cancelled/main.svelte b/test/runtime/samples/transition-js-slot-4-cancelled/main.svelte
new file mode 100644
index 0000000000..1003419244
--- /dev/null
+++ b/test/runtime/samples/transition-js-slot-4-cancelled/main.svelte
@@ -0,0 +1,22 @@
+
+
+outside {state} {props} {slotProps}
+
+ inside {state} {props} {slotProps}
+
diff --git a/test/runtime/samples/transition-js-slot-5-cancelled-overflow/Nested.svelte b/test/runtime/samples/transition-js-slot-5-cancelled-overflow/Nested.svelte
new file mode 100644
index 0000000000..10050b6a10
--- /dev/null
+++ b/test/runtime/samples/transition-js-slot-5-cancelled-overflow/Nested.svelte
@@ -0,0 +1,19 @@
+
+
+{#if visible}
+
+
+
+{/if}
diff --git a/test/runtime/samples/transition-js-slot-5-cancelled-overflow/_config.js b/test/runtime/samples/transition-js-slot-5-cancelled-overflow/_config.js
new file mode 100644
index 0000000000..aedc87f0b6
--- /dev/null
+++ b/test/runtime/samples/transition-js-slot-5-cancelled-overflow/_config.js
@@ -0,0 +1,40 @@
+// updated props in the middle of transitions
+// and cancelled the transition halfway
+// + spreaded props + overflow context
+
+export default {
+ html: `
+ outside Foo Foo Foo
+ inside Foo Foo Foo
+ 0
+ `,
+ props: {
+ props: 'Foo'
+ },
+
+ async test({ assert, component, target, window, raf }) {
+ await component.hide();
+ const [, div] = target.querySelectorAll('div');
+
+ raf.tick(50);
+ assert.equal(div.foo, 0.5);
+
+ component.props = 'Bar';
+ assert.htmlEqual(target.innerHTML, `
+ outside Bar Bar Bar
+ inside Foo Foo Foo
+ 0
+ `);
+
+ await component.show();
+
+ assert.htmlEqual(target.innerHTML, `
+ outside Bar Bar Bar
+ inside Bar Bar Bar
+ 0
+ `);
+
+ raf.tick(100);
+ assert.equal(div.foo, 1);
+ }
+};
diff --git a/test/runtime/samples/transition-js-slot-5-cancelled-overflow/main.svelte b/test/runtime/samples/transition-js-slot-5-cancelled-overflow/main.svelte
new file mode 100644
index 0000000000..9c46fd0521
--- /dev/null
+++ b/test/runtime/samples/transition-js-slot-5-cancelled-overflow/main.svelte
@@ -0,0 +1,27 @@
+
+
+outside {state} {props} {slotProps}
+
+
+ inside {state} {props} {slotProps}
+
+
+{a1+a2+a3+a4+a5+a6+a7+a8+a9+a10+a11+a12+a13+a14+a15+a16+a17+a18+a19+a20+a21+a22+a23+a24+a25+a26+a27+a28+a29+a30+a31+a32+a33}
\ No newline at end of file
diff --git a/test/runtime/samples/transition-js-slot-6-spread-cancelled/Nested.svelte b/test/runtime/samples/transition-js-slot-6-spread-cancelled/Nested.svelte
new file mode 100644
index 0000000000..b1853993d3
--- /dev/null
+++ b/test/runtime/samples/transition-js-slot-6-spread-cancelled/Nested.svelte
@@ -0,0 +1,19 @@
+
+
+{#if visible}
+
+
+
+{/if}
\ No newline at end of file
diff --git a/test/runtime/samples/transition-js-slot-6-spread-cancelled/Nested2.svelte b/test/runtime/samples/transition-js-slot-6-spread-cancelled/Nested2.svelte
new file mode 100644
index 0000000000..52f89858a0
--- /dev/null
+++ b/test/runtime/samples/transition-js-slot-6-spread-cancelled/Nested2.svelte
@@ -0,0 +1,19 @@
+
+
+{#if visible}
+
+
+
+{/if}
\ No newline at end of file
diff --git a/test/runtime/samples/transition-js-slot-6-spread-cancelled/_config.js b/test/runtime/samples/transition-js-slot-6-spread-cancelled/_config.js
new file mode 100644
index 0000000000..1d42c9cf71
--- /dev/null
+++ b/test/runtime/samples/transition-js-slot-6-spread-cancelled/_config.js
@@ -0,0 +1,40 @@
+// updated props in the middle of transitions
+// and cancelled the transition halfway
+// with spreaded props
+
+export default {
+ html: `
+ outside Foo Foo Foo
+ inside Foo Foo Foo
+ inside Foo Foo XXX
+ `,
+ props: {
+ props: 'Foo'
+ },
+
+ async test({ assert, component, target, window, raf }) {
+ await component.hide();
+ const [, div] = target.querySelectorAll('div');
+
+ raf.tick(50);
+ assert.equal(div.foo, 0.5);
+
+ component.props = 'Bar';
+ assert.htmlEqual(target.innerHTML, `
+ outside Bar Bar Bar
+ inside Foo Foo Foo
+ inside Foo Foo XXX
+ `);
+
+ await component.show();
+
+ assert.htmlEqual(target.innerHTML, `
+ outside Bar Bar Bar
+ inside Bar Bar Bar
+ inside Bar Bar XXX
+ `);
+
+ raf.tick(100);
+ assert.equal(div.foo, 1);
+ }
+};
diff --git a/test/runtime/samples/transition-js-slot-6-spread-cancelled/main.svelte b/test/runtime/samples/transition-js-slot-6-spread-cancelled/main.svelte
new file mode 100644
index 0000000000..5dd8ce348e
--- /dev/null
+++ b/test/runtime/samples/transition-js-slot-6-spread-cancelled/main.svelte
@@ -0,0 +1,26 @@
+
+
+outside {state} {props} {slotProps.slotProps}
+
+ inside {state} {props} {slotProps}
+
+
+ inside {state} {props} {slotProps}
+
diff --git a/test/runtime/samples/transition-js-slot-7-spread-cancelled-overflow/Nested.svelte b/test/runtime/samples/transition-js-slot-7-spread-cancelled-overflow/Nested.svelte
new file mode 100644
index 0000000000..b01200fd9f
--- /dev/null
+++ b/test/runtime/samples/transition-js-slot-7-spread-cancelled-overflow/Nested.svelte
@@ -0,0 +1,19 @@
+
+
+{#if visible}
+
+
+
+{/if}
diff --git a/test/runtime/samples/transition-js-slot-7-spread-cancelled-overflow/_config.js b/test/runtime/samples/transition-js-slot-7-spread-cancelled-overflow/_config.js
new file mode 100644
index 0000000000..aedc87f0b6
--- /dev/null
+++ b/test/runtime/samples/transition-js-slot-7-spread-cancelled-overflow/_config.js
@@ -0,0 +1,40 @@
+// updated props in the middle of transitions
+// and cancelled the transition halfway
+// + spreaded props + overflow context
+
+export default {
+ html: `
+ outside Foo Foo Foo
+ inside Foo Foo Foo
+ 0
+ `,
+ props: {
+ props: 'Foo'
+ },
+
+ async test({ assert, component, target, window, raf }) {
+ await component.hide();
+ const [, div] = target.querySelectorAll('div');
+
+ raf.tick(50);
+ assert.equal(div.foo, 0.5);
+
+ component.props = 'Bar';
+ assert.htmlEqual(target.innerHTML, `
+ outside Bar Bar Bar
+ inside Foo Foo Foo
+ 0
+ `);
+
+ await component.show();
+
+ assert.htmlEqual(target.innerHTML, `
+ outside Bar Bar Bar
+ inside Bar Bar Bar
+ 0
+ `);
+
+ raf.tick(100);
+ assert.equal(div.foo, 1);
+ }
+};
diff --git a/test/runtime/samples/transition-js-slot-7-spread-cancelled-overflow/main.svelte b/test/runtime/samples/transition-js-slot-7-spread-cancelled-overflow/main.svelte
new file mode 100644
index 0000000000..000b29ee7f
--- /dev/null
+++ b/test/runtime/samples/transition-js-slot-7-spread-cancelled-overflow/main.svelte
@@ -0,0 +1,27 @@
+
+
+outside {state} {props} {slotProps.slotProps}
+
+
+ inside {state} {props} {slotProps}
+
+
+{a1+a2+a3+a4+a5+a6+a7+a8+a9+a10+a11+a12+a13+a14+a15+a16+a17+a18+a19+a20+a21+a22+a23+a24+a25+a26+a27+a28+a29+a30+a31+a32+a33}
\ No newline at end of file