Skip to content

Commit ddf2d9d

Browse files
authored
Merge pull request #1377 from sveltejs/gh-1303
implement full-state computed properties
2 parents 7246997 + 0dafc34 commit ddf2d9d

File tree

6 files changed

+72
-28
lines changed

6 files changed

+72
-28
lines changed

src/compile/Compiler.ts

+22-10
Original file line numberDiff line numberDiff line change
@@ -564,16 +564,29 @@ export default class Compiler {
564564
if (templateProperties.computed) {
565565
const dependencies = new Map();
566566

567+
const fullStateComputations = [];
568+
567569
templateProperties.computed.value.properties.forEach((prop: Node) => {
568570
const key = getName(prop.key);
569571
const value = prop.value;
570572

571-
const deps = value.params[0].properties.map(prop => prop.key.name);
572-
573-
deps.forEach(dep => {
574-
this.expectedProperties.add(dep);
573+
addDeclaration(key, value, false, 'computed', {
574+
state: true,
575+
changed: true
575576
});
576-
dependencies.set(key, deps);
577+
578+
const param = value.params[0];
579+
580+
if (param.type === 'ObjectPattern') {
581+
const deps = param.properties.map(prop => prop.key.name);
582+
583+
deps.forEach(dep => {
584+
this.expectedProperties.add(dep);
585+
});
586+
dependencies.set(key, deps);
587+
} else {
588+
fullStateComputations.push({ key, deps: null })
589+
}
577590
});
578591

579592
const visited = new Set();
@@ -590,16 +603,15 @@ export default class Compiler {
590603
computations.push({ key, deps });
591604

592605
const prop = templateProperties.computed.value.properties.find((prop: Node) => getName(prop.key) === key);
593-
594-
addDeclaration(key, prop.value, false, 'computed', {
595-
state: true,
596-
changed: true
597-
});
598606
};
599607

600608
templateProperties.computed.value.properties.forEach((prop: Node) =>
601609
visit(getName(prop.key))
602610
);
611+
612+
if (fullStateComputations.length > 0) {
613+
computations.push(...fullStateComputations);
614+
}
603615
}
604616

605617
if (templateProperties.data) {

src/compile/dom/index.ts

+14-7
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,6 @@ export default function dom(
6464

6565
if (computations.length) {
6666
computations.forEach(({ key, deps }) => {
67-
deps.forEach(dep => {
68-
computationDeps.add(dep);
69-
});
70-
7167
if (target.readonly.has(key)) {
7268
// <svelte:window> bindings
7369
throw new Error(
@@ -77,11 +73,22 @@ export default function dom(
7773

7874
target.readonly.add(key);
7975

80-
const condition = `${deps.map(dep => `changed.${dep}`).join(' || ')}`;
76+
if (deps) {
77+
deps.forEach(dep => {
78+
computationDeps.add(dep);
79+
});
8180

82-
const statement = `if (this._differs(state.${key}, (state.${key} = %computed-${key}(state)))) changed.${key} = true;`;
81+
const condition = `${deps.map(dep => `changed.${dep}`).join(' || ')}`;
82+
const statement = `if (this._differs(state.${key}, (state.${key} = %computed-${key}(state)))) changed.${key} = true;`;
8383

84-
computationBuilder.addConditional(condition, statement);
84+
computationBuilder.addConditional(condition, statement);
85+
} else {
86+
// computed property depends on entire state object —
87+
// these must go at the end
88+
computationBuilder.addLine(
89+
`if (this._differs(state.${key}, (state.${key} = %computed-${key}(state)))) changed.${key} = true;`
90+
);
91+
}
8592
});
8693
}
8794

src/compile/ssr/index.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,7 @@ export default function ssr(
120120
ctx = Object.assign(${initialState.join(', ')});
121121
122122
${computations.map(
123-
({ key, deps }) =>
124-
`ctx.${key} = %computed-${key}(ctx);`
123+
({ key }) => `ctx.${key} = %computed-${key}(ctx);`
125124
)}
126125
127126
${target.bindings.length &&

src/validate/js/propValidators/computed.ts

-9
Original file line numberDiff line numberDiff line change
@@ -81,14 +81,5 @@ export default function computed(validator: Validator, prop: Node) {
8181
message: `Computed properties must take a single argument`
8282
});
8383
}
84-
85-
const param = params[0];
86-
if (param.type !== 'ObjectPattern') {
87-
// TODO post-v2, allow the entire object to be passed in
88-
validator.error(computation.value, {
89-
code: `invalid-computed-argument`,
90-
message: `Computed property argument must be a destructured object pattern`
91-
});
92-
}
9384
});
9485
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
export default {
2+
data: { a: 1 },
3+
4+
html: `
5+
<p>a: 1</p>
6+
<p>x: 2</p>
7+
<p>y: 4</p>
8+
<p>z: 8</p>
9+
`,
10+
11+
test(assert, component, target) {
12+
component.set({ a: 2 });
13+
14+
assert.htmlEqual(target.innerHTML, `
15+
<p>a: 2</p>
16+
<p>x: 4</p>
17+
<p>y: 8</p>
18+
<p>z: 16</p>
19+
`)
20+
},
21+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<p>a: {a}</p>
2+
<p>x: {x}</p>
3+
<p>y: {y}</p>
4+
<p>z: {z}</p>
5+
6+
<script>
7+
export default {
8+
computed: {
9+
y: state => state.x * 2,
10+
z: state => state.y * 2,
11+
x: ({ a }) => a * 2
12+
}
13+
};
14+
</script>

0 commit comments

Comments
 (0)