allow reactive declarations without dependencies - fixes #2285

pull/7738/head
Richard Harris 7 years ago
parent abb7842168
commit 6b1067e8c1

@ -1134,13 +1134,6 @@ export default class Component {
seen.add(declaration); seen.add(declaration);
if (declaration.dependencies.size === 0) {
this.error(declaration.node, {
code: 'invalid-reactive-declaration',
message: 'Invalid reactive declaration — must depend on local state'
});
}
declaration.dependencies.forEach(name => { declaration.dependencies.forEach(name => {
if (declaration.assignees.has(name)) return; if (declaration.assignees.has(name)) return;
const earlier_declarations = lookup.get(name); const earlier_declarations = lookup.get(name);

@ -347,27 +347,33 @@ export default function dom(
.map(({ name }) => `$$self.$$.on_destroy.push(() => $$unsubscribe_${name.slice(1)}());`); .map(({ name }) => `$$self.$$.on_destroy.push(() => $$unsubscribe_${name.slice(1)}());`);
if (has_definition) { if (has_definition) {
const reactive_declarations = component.reactive_declarations.map(d => { const reactive_declarations = [];
const fixed_reactive_declarations = []; // not really 'reactive' but whatever
component.reactive_declarations
.forEach(d => {
let uses_props;
const condition = Array.from(d.dependencies) const condition = Array.from(d.dependencies)
.filter(n => { .filter(n => {
if (n === '$$props') return false; if (n === '$$props') {
uses_props = true;
return false;
}
const variable = component.var_lookup.get(n); const variable = component.var_lookup.get(n);
return variable && variable.writable; return variable && variable.writable;
}) })
.map(n => `$$dirty.${n}`).join(' || '); .map(n => `$$dirty.${n}`).join(' || ');
const snippet = d.node.body.type === 'BlockStatement' let snippet = `[✂${d.node.body.start}-${d.node.end}✂]`;
? `[✂${d.node.body.start}-${d.node.end}✂]` if (condition) snippet = `if (${condition}) { ${snippet} }`;
: deindent`
{
[${d.node.body.start}-${d.node.end}]
}`;
return condition if (condition || uses_props) {
? deindent` reactive_declarations.push(snippet);
if (${condition}) ${snippet}` } else {
: deindent` fixed_reactive_declarations.push(snippet);
${snippet}` }
}); });
const injected = Array.from(component.injected_reactive_declaration_vars).filter(name => { const injected = Array.from(component.injected_reactive_declaration_vars).filter(name => {
@ -410,6 +416,8 @@ export default function dom(
$$self.$$.update = ($$dirty = { ${Array.from(all_reactive_dependencies).map(n => `${n}: 1`).join(', ')} }) => { $$self.$$.update = ($$dirty = { ${Array.from(all_reactive_dependencies).map(n => `${n}: 1`).join(', ')} }) => {
${reactive_declarations} ${reactive_declarations}
}; };
${fixed_reactive_declarations}
`} `}
return ${stringify_props(filtered_declarations)}; return ${stringify_props(filtered_declarations)};

@ -70,9 +70,7 @@ function instance($$self, $$props, $$invalidate) {
}; };
$$self.$$.update = ($$dirty = { foo: 1 }) => { $$self.$$.update = ($$dirty = { foo: 1 }) => {
if ($$dirty.foo) { if ($$dirty.foo) { bar = foo * 2; $$invalidate('bar', bar); }
bar = foo * 2; $$invalidate('bar', bar);
}
}; };
return { foo, bar }; return { foo, bar };

@ -28,12 +28,8 @@ function instance($$self, $$props, $$invalidate) {
}; };
$$self.$$.update = ($$dirty = { x: 1, b: 1 }) => { $$self.$$.update = ($$dirty = { x: 1, b: 1 }) => {
if ($$dirty.x) { if ($$dirty.x) { b = x; $$invalidate('b', b); }
b = x; $$invalidate('b', b); if ($$dirty.b) { a = b; $$invalidate('a', a); }
}
if ($$dirty.b) {
a = b; $$invalidate('a', a);
}
}; };
return { x }; return { x };

@ -27,9 +27,7 @@ function instance($$self, $$props, $$invalidate) {
let max; let max;
$$self.$$.update = ($$dirty = { a: 1, b: 1 }) => { $$self.$$.update = ($$dirty = { a: 1, b: 1 }) => {
if ($$dirty.a || $$dirty.b) { if ($$dirty.a || $$dirty.b) { max = Math.max(a, b); $$invalidate('max', max); }
max = Math.max(a, b); $$invalidate('max', max);
}
}; };
return {}; return {};

@ -1,6 +1,4 @@
export default { export default {
show: 1,
props: { props: {
a: 1, a: 1,
b: 2, b: 2,

@ -0,0 +1,12 @@
export default {
html: `
<p>10 - 90</p>
`,
test({ assert, component, target }) {
component.width = 50;
assert.htmlEqual(target.innerHTML, `
<p>10 - 40</p>
`);
}
};

@ -0,0 +1,10 @@
<script>
export let width = 100;
const padding = 10;
$: x1 = padding;
$: x2 = width - padding;
</script>
<p>{x1} - {x2}</p>

@ -1,7 +0,0 @@
[{
"message": "Invalid reactive declaration — must depend on local state",
"code": "invalid-reactive-declaration",
"start": { "line": 2, "column": 1, "character": 10 },
"end": { "line": 2, "column": 23, "character": 32 },
"pos": 10
}]

@ -1,3 +0,0 @@
<script>
$: console.log('foo');
</script>
Loading…
Cancel
Save