Skip to content

Commit

Permalink
handle rest elements in computed properties - fixes #1540
Browse files Browse the repository at this point in the history
  • Loading branch information
Rich-Harris committed Aug 4, 2018
1 parent 814a323 commit 7d55a57
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 9 deletions.
17 changes: 11 additions & 6 deletions src/compile/Compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ import { Node, GenerateOptions, ShorthandImport, Ast, CompileOptions, CustomElem

interface Computation {
key: string;
deps: string[]
deps: string[];
hasRestParam: boolean;
}

function detectIndentation(str: string) {
Expand Down Expand Up @@ -436,7 +437,6 @@ export default class Compiler {
code,
source,
computations,
methods,
templateProperties,
imports
} = this;
Expand Down Expand Up @@ -588,15 +588,20 @@ export default class Compiler {

const param = value.params[0];

if (param.type === 'ObjectPattern') {
const hasRestParam = (
param.properties &&
param.properties.some(prop => prop.type === 'RestElement')
);

if (param.type !== 'ObjectPattern' || hasRestParam) {
fullStateComputations.push({ key, deps: null, hasRestParam });
} else {
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 })
}
});

Expand All @@ -611,7 +616,7 @@ export default class Compiler {
const deps = dependencies.get(key);
deps.forEach(visit);

computations.push({ key, deps });
computations.push({ key, deps, hasRestParam: false });

const prop = templateProperties.computed.value.properties.find((prop: Node) => getName(prop.key) === key);
};
Expand Down
6 changes: 4 additions & 2 deletions src/compile/dom/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export default function dom(
const computationDeps = new Set();

if (computations.length) {
computations.forEach(({ key, deps }) => {
computations.forEach(({ key, deps, hasRestParam }) => {
if (target.readonly.has(key)) {
// <svelte:window> bindings
throw new Error(
Expand All @@ -89,8 +89,10 @@ export default function dom(
} else {
// computed property depends on entire state object —
// these must go at the end
const arg = hasRestParam ? `@exclude(state, "${key}")` : `state`;

computationBuilder.addLine(
`if (this._differs(state.${key}, (state.${key} = %computed-${key}(state)))) changed.${key} = true;`
`if (this._differs(state.${key}, (state.${key} = %computed-${key}(${arg})))) changed.${key} = true;`
);
}
});
Expand Down
6 changes: 6 additions & 0 deletions src/shared/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,10 @@ export function addLoc(element, file, line, column, char) {
element.__svelte_meta = {
loc: { file, line, column, char }
};
}

export function exclude(src, prop) {
const tar = {};
for (const k in src) k === prop || (tar[k] = src[k]);
return tar;
}
6 changes: 5 additions & 1 deletion src/utils/annotateWithScopes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,11 @@ const extractors = {

ObjectPattern(names: string[], param: Node) {
param.properties.forEach((prop: Node) => {
extractors[prop.value.type](names, prop.value);
if (prop.type === 'RestElement') {
names.push(prop.argument.name);
} else {
extractors[prop.value.type](names, prop.value);
}
});
},

Expand Down
27 changes: 27 additions & 0 deletions test/runtime/samples/object-rest/_config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
export default {
skip: +/v(\d+)/.exec(process.version)[1] < 8,

html: `
<pre>{"wanted":2}</pre>
`,

test(assert, component, target) {
component.set({
unwanted: 3,
wanted: 4
});

assert.htmlEqual(target.innerHTML, `
<pre>{"wanted":4}</pre>
`);

component.set({
unwanted: 5,
wanted: 6
});

assert.htmlEqual(target.innerHTML, `
<pre>{"wanted":6}</pre>
`);
}
};
18 changes: 18 additions & 0 deletions test/runtime/samples/object-rest/main.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<pre>{JSON.stringify(props)}</pre>
<script>
export default {
data: () => ({
unwanted: 1,
wanted: 2
}),

helpers: {
// prevent this being mixed in with data
JSON
},

computed: {
props: ({ unwanted, ...x }) => x
}
};
</script>

0 comments on commit 7d55a57

Please sign in to comment.