Merge pull request #2234 from sveltejs/gh-2163

Interpret `changed` inside slotted content
pull/2237/head
Rich Harris 6 years ago committed by GitHub
commit 5b172d8a61
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -150,7 +150,7 @@ export default class Expression {
}
component.add_reference(name);
component.warn_if_undefined(nodes[0], template_scope, true);
component.warn_if_undefined(nodes[0], template_scope);
}
this.skip();

@ -1,7 +1,6 @@
import Wrapper from '../shared/Wrapper';
import Renderer from '../../Renderer';
import Block from '../../Block';
import Node from '../../../nodes/shared/Node';
import InlineComponent from '../../../nodes/InlineComponent';
import FragmentWrapper from '../Fragment';
import { quoteNameIfNecessary, quotePropIfNecessary } from '../../../../utils/quoteIfNecessary';
@ -85,7 +84,16 @@ export default class InlineComponentWrapper extends Wrapper {
});
this.fragment = new FragmentWrapper(renderer, default_slot, node.children, this, stripWhitespace, nextSibling);
block.addDependencies(default_slot.dependencies);
const dependencies = new Set();
// TODO is this filtering necessary? (I *think* so)
default_slot.dependencies.forEach(name => {
if (!this.node.scope.is_let(name)) {
dependencies.add(name);
}
});
block.addDependencies(dependencies);
}
block.addOutro();
@ -160,7 +168,9 @@ export default class InlineComponentWrapper extends Wrapper {
});
});
if (!usesSpread && (this.node.attributes.filter(a => a.isDynamic).length || this.node.bindings.length || fragment_dependencies.size > 0)) {
const non_let_dependencies = Array.from(fragment_dependencies).filter(name => !this.node.scope.is_let(name));
if (!usesSpread && (this.node.attributes.filter(a => a.isDynamic).length || this.node.bindings.length || non_let_dependencies.length > 0)) {
updates.push(`var ${name_changes} = {};`);
}
@ -231,8 +241,8 @@ export default class InlineComponentWrapper extends Wrapper {
}
}
if (fragment_dependencies.size > 0) {
updates.push(`if (${Array.from(fragment_dependencies).map(n => `changed.${n}`).join(' || ')}) ${name_changes}.$$scope = { changed, ctx };`);
if (non_let_dependencies.length > 0) {
updates.push(`if (${non_let_dependencies.map(n => `changed.${n}`).join(' || ')}) ${name_changes}.$$scope = { changed, ctx };`);
}
const munged_bindings = this.node.bindings.map(binding => {
@ -498,13 +508,4 @@ export default class InlineComponentWrapper extends Wrapper {
);
}
}
}
function isComputed(node: Node) {
while (node.type === 'MemberExpression') {
if (node.computed) return true;
node = node.object;
}
return false;
}
}

@ -142,7 +142,7 @@ export default class SlotWrapper extends Wrapper {
block.builders.update.addBlock(deindent`
if (${slot} && ${update_conditions}) {
${slot}.p(@assign(@assign({}, ${get_slot_changes}(changed)), ctx.$$scope.changed), @get_slot_context(${slot_definition}, ctx, ${get_slot_context}));
${slot}.p(@get_slot_changes(${slot_definition}, ctx, changed, ${get_slot_changes}), @get_slot_context(${slot_definition}, ctx, ${get_slot_context}));
}
`);

@ -4,7 +4,15 @@ export function get_context_merger(lets: Let[]) {
if (lets.length === 0) return null;
const input = lets.map(l => l.value ? `${l.name}: ${l.value}` : l.name).join(', ');
const output = lets.map(l => l.names.join(', ')).join(', ');
const names = new Set();
lets.forEach(l => {
l.names.forEach(name => {
names.add(name);
});
});
const output = Array.from(names).join(', ');
return `({ ${input} }) => ({ ${output} })`;
}

@ -64,6 +64,12 @@ export function get_slot_context(definition, ctx, fn) {
: ctx.$$scope.ctx;
}
export function get_slot_changes(definition, ctx, changed, fn) {
return definition[1]
? assign({}, assign(ctx.$$scope.changed || {}, definition[1](fn ? fn(changed) : {})))
: ctx.$$scope.changed || {};
}
export function exclude_internal_props(props) {
const result = {};
for (const k in props) if (k[0] !== '$') result[k] = props[k];

@ -0,0 +1,7 @@
<script>
let foo = 'a';
</script>
<div on:click="{() => foo = 'b'}">
<slot {foo}></slot>
</div>

@ -0,0 +1,20 @@
export default {
html: `
<div>
<p>a</p>
</div>
`,
async test({ assert, target, window }) {
const div = target.querySelector('div');
const click = new window.MouseEvent('click');
await div.dispatchEvent(click);
assert.htmlEqual(target.innerHTML, `
<div>
<p>b</p>
</div>
`);
}
};

@ -0,0 +1,7 @@
<script>
import Nested from './Nested.svelte';
</script>
<Nested let:foo={bar}>
<p>{bar}</p>
</Nested>
Loading…
Cancel
Save