Skip to content

Commit b2d9da3

Browse files
authoredJun 29, 2019
Pass hoisted values through to slots (#3124)
* Fixed bug with slot props variables * dont add hoisted items to context * alternative fix for #2586 * update slots more conservatively
1 parent 6af23ba commit b2d9da3

File tree

7 files changed

+71
-15
lines changed

7 files changed

+71
-15
lines changed
 

‎src/compiler/compile/nodes/shared/Expression.ts

+2-4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import get_object from '../../utils/get_object';
1313
import { nodes_match } from '../../../utils/nodes_match';
1414
import Block from '../../render_dom/Block';
1515
import { INode } from '../interfaces';
16+
import is_dynamic from '../../render_dom/wrappers/shared/is_dynamic';
1617

1718
const binary_operators: Record<string, number> = {
1819
'**': 15,
@@ -211,10 +212,7 @@ export default class Expression {
211212
if (name === '$$props') return true;
212213

213214
const variable = this.component.var_lookup.get(name);
214-
if (!variable) return false;
215-
216-
if (variable.mutated || variable.reassigned) return true; // dynamic internal state
217-
if (!variable.module && variable.writable && variable.export_name) return true; // writable props
215+
return is_dynamic(variable);
218216
});
219217
}
220218

‎src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts

+2-5
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import create_debugging_comment from '../shared/create_debugging_comment';
1313
import { get_context_merger } from '../shared/get_context_merger';
1414
import EachBlock from '../../../nodes/EachBlock';
1515
import TemplateScope from '../../../nodes/shared/TemplateScope';
16+
import is_dynamic from '../shared/is_dynamic';
1617
import bind_this from '../shared/bind_this';
1718

1819
export default class InlineComponentWrapper extends Wrapper {
@@ -161,11 +162,7 @@ export default class InlineComponentWrapper extends Wrapper {
161162
const is_let = slot.scope.is_let(name);
162163
const variable = renderer.component.var_lookup.get(name);
163164

164-
if (is_let) fragment_dependencies.add(name);
165-
166-
if (!variable) return;
167-
if (variable.mutated || variable.reassigned) fragment_dependencies.add(name);
168-
if (!variable.module && variable.writable && variable.export_name) fragment_dependencies.add(name);
165+
if (is_let || is_dynamic(variable)) fragment_dependencies.add(name);
169166
});
170167
});
171168

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

+23-6
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import add_to_set from '../../utils/add_to_set';
99
import get_slot_data from '../../utils/get_slot_data';
1010
import { stringify_props } from '../../utils/stringify_props';
1111
import Expression from '../../nodes/shared/Expression';
12+
import is_dynamic from './shared/is_dynamic';
1213

1314
export default class SlotWrapper extends Wrapper {
1415
node: Slot;
@@ -72,17 +73,27 @@ export default class SlotWrapper extends Wrapper {
7273
this.node.values.forEach(attribute => {
7374
attribute.chunks.forEach(chunk => {
7475
if ((chunk as Expression).dependencies) {
75-
add_to_set(dependencies, (chunk as Expression).dependencies);
7676
add_to_set(dependencies, (chunk as Expression).contextual_dependencies);
77+
78+
// add_to_set(dependencies, (chunk as Expression).dependencies);
79+
(chunk as Expression).dependencies.forEach(name => {
80+
const variable = renderer.component.var_lookup.get(name);
81+
if (variable && !variable.hoistable) dependencies.add(name);
82+
});
7783
}
7884
});
7985

80-
if (attribute.dependencies.size > 0) {
81-
changes_props.push(`${attribute.name}: ${[...attribute.dependencies].join(' || ')}`);
86+
const dynamic_dependencies = Array.from(attribute.dependencies).filter(name => {
87+
const variable = renderer.component.var_lookup.get(name);
88+
return is_dynamic(variable);
89+
});
90+
91+
if (dynamic_dependencies.length > 0) {
92+
changes_props.push(`${attribute.name}: ${dynamic_dependencies.join(' || ')}`);
8293
}
8394
});
8495

85-
const arg = dependencies.size > 0 ? `{ ${Array.from(dependencies).join(', ')} }` : '{}';
96+
const arg = dependencies.size > 0 ? `{ ${Array.from(dependencies).join(', ')} }` : '';
8697

8798
renderer.blocks.push(deindent`
8899
const ${get_slot_changes} = (${arg}) => (${stringify_props(changes_props)});
@@ -149,8 +160,14 @@ export default class SlotWrapper extends Wrapper {
149160
`@transition_out(${slot}, #local);`
150161
);
151162

152-
let update_conditions = [...this.dependencies].map(name => `changed.${name}`).join(' || ');
153-
if (this.dependencies.size > 1) update_conditions = `(${update_conditions})`;
163+
const dynamic_dependencies = Array.from(this.dependencies).filter(name => {
164+
if (name === '$$scope') return true;
165+
const variable = renderer.component.var_lookup.get(name);
166+
return is_dynamic(variable);
167+
});
168+
169+
let update_conditions = dynamic_dependencies.map(name => `changed.${name}`).join(' || ');
170+
if (dynamic_dependencies.length > 1) update_conditions = `(${update_conditions})`;
154171

155172
block.builders.update.add_block(deindent`
156173
if (${slot} && ${slot}.p && ${update_conditions}) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { Var } from '../../../../interfaces';
2+
3+
export default function is_dynamic(variable: Var) {
4+
if (variable) {
5+
if (variable.mutated || variable.reassigned) return true; // dynamic internal state
6+
if (!variable.module && variable.writable && variable.export_name) return true; // writable props
7+
}
8+
9+
return false;
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<script>
2+
let fooText = 'foo';
3+
</script>
4+
5+
<div>
6+
<slot someText={fooText}></slot>
7+
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
export default {
2+
html: `
3+
<div>
4+
<p>foo</p>
5+
</div>
6+
`,
7+
8+
async test({ assert, target, window }) {
9+
const div = target.querySelector('div');
10+
const click = new window.MouseEvent('click');
11+
12+
await div.dispatchEvent(click);
13+
14+
assert.htmlEqual(target.innerHTML, `
15+
<div>
16+
<p>foo</p>
17+
</div>
18+
`);
19+
}
20+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<script>
2+
import Nested from './Nested.svelte';
3+
</script>
4+
5+
<Nested let:someText={someText}>
6+
<p>{someText}</p>
7+
</Nested>

0 commit comments

Comments
 (0)