diff --git a/src/generators/Generator.ts b/src/generators/Generator.ts index 6d49faf906d8..6072d4dad083 100644 --- a/src/generators/Generator.ts +++ b/src/generators/Generator.ts @@ -84,6 +84,7 @@ export default class Generator { source: string; name: string; options: CompileOptions; + v2: boolean; customElement: CustomElementOptions; tag: string; @@ -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; @@ -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); }); diff --git a/src/generators/dom/index.ts b/src/generators/dom/index.ts index 51f4664ae7c0..eac5655fe35d 100644 --- a/src/generators/dom/index.ts +++ b/src/generators/dom/index.ts @@ -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); }); diff --git a/src/validate/index.ts b/src/validate/index.ts index 96bc3823757e..f5bb2d30ef7b 100644 --- a/src/validate/index.ts +++ b/src/validate/index.ts @@ -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; @@ -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; @@ -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)) { @@ -119,7 +121,8 @@ export default function validate( name, filename, store, - dev + dev, + parser }); if (parsed.js) { diff --git a/src/validate/js/propValidators/computed.ts b/src/validate/js/propValidators/computed.ts index 4b1a5ff06171..e81341fab8d6 100644 --- a/src/validate/js/propValidators/computed.ts +++ b/src/validate/js/propValidators/computed.ts @@ -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', @@ -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` + }); + } + }); + } }); } diff --git a/test/js/samples/dev-warning-missing-data-computed/_actual-bundle-v2.js b/test/js/samples/dev-warning-missing-data-computed/_actual-bundle-v2.js index 84a148c901d5..f7346d0d2f1b 100644 --- a/test/js/samples/dev-warning-missing-data-computed/_actual-bundle-v2.js +++ b/test/js/samples/dev-warning-missing-data-computed/_actual-bundle-v2.js @@ -226,7 +226,7 @@ var protoDev = { /* generated by Svelte vX.Y.Z */ -function bar(foo) { +function bar({ foo }) { return foo * 2; } @@ -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; } }; diff --git a/test/js/samples/dev-warning-missing-data-computed/expected-bundle-v2.js b/test/js/samples/dev-warning-missing-data-computed/expected-bundle-v2.js index 84a148c901d5..f7346d0d2f1b 100644 --- a/test/js/samples/dev-warning-missing-data-computed/expected-bundle-v2.js +++ b/test/js/samples/dev-warning-missing-data-computed/expected-bundle-v2.js @@ -226,7 +226,7 @@ var protoDev = { /* generated by Svelte vX.Y.Z */ -function bar(foo) { +function bar({ foo }) { return foo * 2; } @@ -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; } }; diff --git a/test/js/samples/dev-warning-missing-data-computed/expected-v2.js b/test/js/samples/dev-warning-missing-data-computed/expected-v2.js index edf4331457b6..52dee37250c4 100644 --- a/test/js/samples/dev-warning-missing-data-computed/expected-v2.js +++ b/test/js/samples/dev-warning-missing-data-computed/expected-v2.js @@ -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; } @@ -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; \ No newline at end of file diff --git a/test/js/samples/dev-warning-missing-data-computed/input-v2.html b/test/js/samples/dev-warning-missing-data-computed/input-v2.html index 3fbf45860e7a..06eb210493b0 100644 --- a/test/js/samples/dev-warning-missing-data-computed/input-v2.html +++ b/test/js/samples/dev-warning-missing-data-computed/input-v2.html @@ -6,7 +6,7 @@ \ No newline at end of file diff --git a/test/runtime/samples/computed-function/main-v2.html b/test/runtime/samples/computed-function/main-v2.html new file mode 100644 index 000000000000..a43225216687 --- /dev/null +++ b/test/runtime/samples/computed-function/main-v2.html @@ -0,0 +1,20 @@ +
{scale(x)}
+ + diff --git a/test/runtime/samples/computed-values-deconflicted/main-v2.html b/test/runtime/samples/computed-values-deconflicted/main-v2.html new file mode 100644 index 000000000000..e5a016084cad --- /dev/null +++ b/test/runtime/samples/computed-values-deconflicted/main-v2.html @@ -0,0 +1,14 @@ +{state} + + \ No newline at end of file diff --git a/test/runtime/samples/computed-values-default/main-v2.html b/test/runtime/samples/computed-values-default/main-v2.html new file mode 100644 index 000000000000..b26762f3d826 --- /dev/null +++ b/test/runtime/samples/computed-values-default/main-v2.html @@ -0,0 +1,9 @@ +{foo}
+ + diff --git a/test/runtime/samples/computed-values-function-dependency/main-v2.html b/test/runtime/samples/computed-values-function-dependency/main-v2.html new file mode 100644 index 000000000000..adf66137fa8a --- /dev/null +++ b/test/runtime/samples/computed-values-function-dependency/main-v2.html @@ -0,0 +1,28 @@ +{x}
+ + \ No newline at end of file diff --git a/test/runtime/samples/computed-values/main-v2.html b/test/runtime/samples/computed-values/main-v2.html new file mode 100644 index 000000000000..7e4f8d772853 --- /dev/null +++ b/test/runtime/samples/computed-values/main-v2.html @@ -0,0 +1,16 @@ +{a} + {b} = {c}
+{c} * {c} = {cSquared}
+ +