Skip to content

Commit

Permalink
use destructuring syntax for computed props in v2 mode - fixes #1069
Browse files Browse the repository at this point in the history
  • Loading branch information
Rich-Harris committed Apr 15, 2018
1 parent 7fe139f commit 99ea753
Show file tree
Hide file tree
Showing 13 changed files with 141 additions and 27 deletions.
11 changes: 7 additions & 4 deletions src/generators/Generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ export default class Generator {
source: string;
name: string;
options: CompileOptions;
v2: boolean;

customElement: CustomElementOptions;
tag: string;
Expand Down Expand Up @@ -132,6 +133,8 @@ export default class Generator {
stats.start('compile');
this.stats = stats;

this.v2 = options.parser === 'v2';

this.ast = clone(parsed);

this.parsed = parsed;
Expand Down Expand Up @@ -575,10 +578,10 @@ export default class Generator {
const key = getName(prop.key);
const value = prop.value;

const deps = value.params.map(
(param: Node) =>
param.type === 'AssignmentPattern' ? param.left.name : param.name
);
const deps = this.v2
? value.params[0].properties.map(prop => prop.key.name)
: value.params.map(param => param.type === 'AssignmentPattern' ? param.left.name : param.name);

deps.forEach(dep => {
this.expectedProperties.add(dep);
});
Expand Down
8 changes: 5 additions & 3 deletions src/generators/dom/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,11 @@ export default function dom(

const condition = `${deps.map(dep => `changed.${dep}`).join(' || ')}`;

const statement = `if (this._differs(state.${key}, (state.${key} = %computed-${key}(${deps
.map(dep => `state.${dep}`)
.join(', ')})))) changed.${key} = true;`;
const call = generator.v2
? `%computed-${key}(state)`
: `%computed-${key}(${deps.map(dep => `state.${dep}`).join(', ')})`;

const statement = `if (this._differs(state.${key}, (state.${key} = ${call}))) changed.${key} = true;`;

computationBuilder.addConditional(condition, statement);
});
Expand Down
7 changes: 5 additions & 2 deletions src/validate/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { Node, Parsed, CompileOptions, Warning } from '../interfaces';
export class Validator {
readonly source: string;
readonly filename: string;
readonly v2: boolean;

options: CompileOptions;
onwarn: ({}) => void;
Expand Down Expand Up @@ -38,6 +39,7 @@ export class Validator {
this.filename = options.filename;
this.onwarn = options.onwarn;
this.options = options;
this.v2 = options.parser === 'v2';

this.namespace = null;
this.defaultExport = null;
Expand Down Expand Up @@ -96,7 +98,7 @@ export default function validate(
stylesheet: Stylesheet,
options: CompileOptions
) {
const { onwarn, onerror, name, filename, store, dev } = options;
const { onwarn, onerror, name, filename, store, dev, parser } = options;

try {
if (name && !/^[a-zA-Z_$][a-zA-Z_$0-9]*$/.test(name)) {
Expand All @@ -119,7 +121,8 @@ export default function validate(
name,
filename,
store,
dev
dev,
parser
});

if (parsed.js) {
Expand Down
41 changes: 30 additions & 11 deletions src/validate/js/propValidators/computed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Validator } from '../../index';
import { Node } from '../../../interfaces';
import walkThroughTopFunctionScope from '../../../utils/walkThroughTopFunctionScope';
import isThisGetCallExpression from '../../../utils/isThisGetCallExpression';
import validCalleeObjects from '../../../utils/validCalleeObjects';

const isFunctionExpression = new Set([
'FunctionExpression',
Expand Down Expand Up @@ -74,19 +75,37 @@ export default function computed(validator: Validator, prop: Node) {
});
}

params.forEach((param: Node) => {
const valid =
param.type === 'Identifier' ||
(param.type === 'AssignmentPattern' &&
param.left.type === 'Identifier');

if (!valid) {
// TODO change this for v2
validator.error(param, {
if (validator.v2) {
if (params.length > 1) {
validator.error(computation.value, {
code: `invalid-computed-arguments`,
message: `Computed properties cannot use destructuring in function parameters`
message: `Computed properties must take a single argument`
});
}
});

const param = params[0];
if (param.type !== 'ObjectPattern') {
// TODO in 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`
});
}
} else {
params.forEach((param: Node) => {
const valid =
param.type === 'Identifier' ||
(param.type === 'AssignmentPattern' &&
param.left.type === 'Identifier');

if (!valid) {
// TODO change this for v2
validator.error(param, {
code: `invalid-computed-arguments`,
message: `Computed properties cannot use destructuring in function parameters`
});
}
});
}
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ var protoDev = {

/* generated by Svelte vX.Y.Z */

function bar(foo) {
function bar({ foo }) {
return foo * 2;
}

Expand Down Expand Up @@ -291,7 +291,7 @@ SvelteComponent.prototype._checkReadOnly = function _checkReadOnly(newState) {

SvelteComponent.prototype._recompute = function _recompute(changed, state) {
if (changed.foo) {
if (this._differs(state.bar, (state.bar = bar(state.foo)))) changed.bar = true;
if (this._differs(state.bar, (state.bar = bar(state)))) changed.bar = true;
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ var protoDev = {

/* generated by Svelte vX.Y.Z */

function bar(foo) {
function bar({ foo }) {
return foo * 2;
}

Expand Down Expand Up @@ -291,7 +291,7 @@ SvelteComponent.prototype._checkReadOnly = function _checkReadOnly(newState) {

SvelteComponent.prototype._recompute = function _recompute(changed, state) {
if (changed.foo) {
if (this._differs(state.bar, (state.bar = bar(state.foo)))) changed.bar = true;
if (this._differs(state.bar, (state.bar = bar(state)))) changed.bar = true;
}
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* generated by Svelte vX.Y.Z */
import { appendNode, assign, createElement, createText, detachNode, init, insertNode, noop, protoDev } from "svelte/shared.js";

function bar(foo) {
function bar({ foo }) {
return foo * 2;
}

Expand Down Expand Up @@ -66,7 +66,7 @@ SvelteComponent.prototype._checkReadOnly = function _checkReadOnly(newState) {

SvelteComponent.prototype._recompute = function _recompute(changed, state) {
if (changed.foo) {
if (this._differs(state.bar, (state.bar = bar(state.foo)))) changed.bar = true;
if (this._differs(state.bar, (state.bar = bar(state)))) changed.bar = true;
}
}
export default SvelteComponent;
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<script>
export default {
computed: {
bar: foo => foo * 2
bar: ({ foo }) => foo * 2
}
};
</script>
20 changes: 20 additions & 0 deletions test/runtime/samples/computed-function/main-v2.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<p>{scale(x)}</p>

<script>
export default {
data: () => ({
x: 5,
domain: [ 0, 10 ],
range: [ 0, 100 ]
}),

computed: {
scale: ({ domain, range }) => {
return num => {
const t = domain[0] + ( num - domain[0] ) / ( domain[1] - domain[0] );
return range[0] + t * ( range[1] - range[0] );
}
}
}
};
</script>
14 changes: 14 additions & 0 deletions test/runtime/samples/computed-values-deconflicted/main-v2.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<span>{state}</span>

<script>
export default {
data() {
return {
x: 'waiting'
};
},
computed: {
state: ({ x }) => x
}
};
</script>
9 changes: 9 additions & 0 deletions test/runtime/samples/computed-values-default/main-v2.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<p>{foo}</p>

<script>
export default {
computed: {
foo: ({ a = 1 }) => a * 2
}
};
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<p>{x}</p>

<script>
let _x;

function getX () {
return _x;
}

export default {
data () {
return {
y: 1
};
},

computed: {
xGetter ({ y }) {
_x = y * 2;
return getX;
},

x ({ xGetter }) {
return xGetter();
}
}
};
</script>
16 changes: 16 additions & 0 deletions test/runtime/samples/computed-values/main-v2.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<p>{a} + {b} = {c}</p>
<p>{c} * {c} = {cSquared}</p>

<script>
export default {
data: () => ({
a: 1,
b: 2
}),

computed: {
c: ({ a, b }) => a + b,
cSquared: ({ c }) => c * c
}
};
</script>

0 comments on commit 99ea753

Please sign in to comment.