Merge pull request #1377 from sveltejs/gh-1303

implement full-state computed properties
pull/1381/head
Rich Harris 6 years ago committed by GitHub
commit ddf2d9dbcf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -564,16 +564,29 @@ export default class Compiler {
if (templateProperties.computed) {
const dependencies = new Map();
const fullStateComputations = [];
templateProperties.computed.value.properties.forEach((prop: Node) => {
const key = getName(prop.key);
const value = prop.value;
const deps = value.params[0].properties.map(prop => prop.key.name);
deps.forEach(dep => {
this.expectedProperties.add(dep);
addDeclaration(key, value, false, 'computed', {
state: true,
changed: true
});
dependencies.set(key, deps);
const param = value.params[0];
if (param.type === 'ObjectPattern') {
const deps = param.properties.map(prop => prop.key.name);
deps.forEach(dep => {
this.expectedProperties.add(dep);
});
dependencies.set(key, deps);
} else {
fullStateComputations.push({ key, deps: null })
}
});
const visited = new Set();
@ -590,16 +603,15 @@ export default class Compiler {
computations.push({ key, deps });
const prop = templateProperties.computed.value.properties.find((prop: Node) => getName(prop.key) === key);
addDeclaration(key, prop.value, false, 'computed', {
state: true,
changed: true
});
};
templateProperties.computed.value.properties.forEach((prop: Node) =>
visit(getName(prop.key))
);
if (fullStateComputations.length > 0) {
computations.push(...fullStateComputations);
}
}
if (templateProperties.data) {

@ -64,10 +64,6 @@ export default function dom(
if (computations.length) {
computations.forEach(({ key, deps }) => {
deps.forEach(dep => {
computationDeps.add(dep);
});
if (target.readonly.has(key)) {
// <svelte:window> bindings
throw new Error(
@ -77,11 +73,22 @@ export default function dom(
target.readonly.add(key);
const condition = `${deps.map(dep => `changed.${dep}`).join(' || ')}`;
if (deps) {
deps.forEach(dep => {
computationDeps.add(dep);
});
const statement = `if (this._differs(state.${key}, (state.${key} = %computed-${key}(state)))) changed.${key} = true;`;
const condition = `${deps.map(dep => `changed.${dep}`).join(' || ')}`;
const statement = `if (this._differs(state.${key}, (state.${key} = %computed-${key}(state)))) changed.${key} = true;`;
computationBuilder.addConditional(condition, statement);
computationBuilder.addConditional(condition, statement);
} else {
// computed property depends on entire state object —
// these must go at the end
computationBuilder.addLine(
`if (this._differs(state.${key}, (state.${key} = %computed-${key}(state)))) changed.${key} = true;`
);
}
});
}

@ -120,8 +120,7 @@ export default function ssr(
ctx = Object.assign(${initialState.join(', ')});
${computations.map(
({ key, deps }) =>
`ctx.${key} = %computed-${key}(ctx);`
({ key }) => `ctx.${key} = %computed-${key}(ctx);`
)}
${target.bindings.length &&

@ -81,14 +81,5 @@ export default function computed(validator: Validator, prop: Node) {
message: `Computed properties must take a single argument`
});
}
const param = params[0];
if (param.type !== 'ObjectPattern') {
// TODO post-v2, allow the entire object to be passed in
validator.error(computation.value, {
code: `invalid-computed-argument`,
message: `Computed property argument must be a destructured object pattern`
});
}
});
}

@ -0,0 +1,21 @@
export default {
data: { a: 1 },
html: `
<p>a: 1</p>
<p>x: 2</p>
<p>y: 4</p>
<p>z: 8</p>
`,
test(assert, component, target) {
component.set({ a: 2 });
assert.htmlEqual(target.innerHTML, `
<p>a: 2</p>
<p>x: 4</p>
<p>y: 8</p>
<p>z: 16</p>
`)
},
};

@ -0,0 +1,14 @@
<p>a: {a}</p>
<p>x: {x}</p>
<p>y: {y}</p>
<p>z: {z}</p>
<script>
export default {
computed: {
y: state => state.x * 2,
z: state => state.y * 2,
x: ({ a }) => a * 2
}
};
</script>
Loading…
Cancel
Save