diff --git a/src/generators/dom/index.ts b/src/generators/dom/index.ts index 2bf0c21c4b..c6d9e94df2 100644 --- a/src/generators/dom/index.ts +++ b/src/generators/dom/index.ts @@ -227,7 +227,7 @@ export default function dom( ${(templateProperties.ondestroy || storeProps.length) && ( `this._handlers.destroy = [${ [templateProperties.ondestroy && `%ondestroy`, storeProps.length && `@removeFromStore`].filter(Boolean).join(', ') - }]` + }];` )} ${generator.slots.size && `this._slotted = options.slots || {};`} diff --git a/src/generators/dom/visitors/Element/addBindings.ts b/src/generators/dom/visitors/Element/addBindings.ts index a2433abf93..2e41cd1b19 100644 --- a/src/generators/dom/visitors/Element/addBindings.ts +++ b/src/generators/dom/visitors/Element/addBindings.ts @@ -195,13 +195,19 @@ export default function addBindings( const usesContext = group.bindings.some(binding => binding.handler.usesContext); const usesState = group.bindings.some(binding => binding.handler.usesState); + const usesStore = group.bindings.some(binding => binding.handler.usesStore); const mutations = group.bindings.map(binding => binding.handler.mutation).filter(Boolean).join('\n'); const props = new Set(); + const storeProps = new Set(); group.bindings.forEach(binding => { binding.handler.props.forEach(prop => { props.add(prop); }); + + binding.handler.storeProps.forEach(prop => { + storeProps.add(prop); + }); }); // TODO use stringifyProps here, once indenting is fixed // media bindings — awkward special case. The native timeupdate events @@ -222,9 +228,11 @@ export default function addBindings( } ${usesContext && `var context = ${node.var}._svelte;`} ${usesState && `var state = #component.get();`} + ${usesStore && `var $ = #component.store.get();`} ${needsLock && `${lock} = true;`} ${mutations.length > 0 && mutations} - #component.set({ ${Array.from(props).join(', ')} }); + ${props.size > 0 && `#component.set({ ${Array.from(props).join(', ')} });`} + ${storeProps.size > 0 && `#component.store.set({ ${Array.from(storeProps).join(', ')} });`} ${needsLock && `${lock} = false;`} } `); @@ -307,6 +315,13 @@ function getEventHandler( dependencies: string[], value: string, ) { + let storeDependencies = []; + + if (generator.options.store) { + storeDependencies = dependencies.filter(prop => prop[0] === '$').map(prop => prop.slice(1)); + dependencies = dependencies.filter(prop => prop[0] !== '$'); + } + if (block.contexts.has(name)) { const tail = attribute.value.type === 'MemberExpression' ? getTailSnippet(attribute.value) @@ -318,8 +333,10 @@ function getEventHandler( return { usesContext: true, usesState: true, + usesStore: storeDependencies.length > 0, mutation: `${list}[${index}]${tail} = ${value};`, - props: dependencies.map(prop => `${prop}: state.${prop}`) + props: dependencies.map(prop => `${prop}: state.${prop}`), + storeProps: storeDependencies.map(prop => `${prop}: $.${prop}`) }; } @@ -336,16 +353,31 @@ function getEventHandler( return { usesContext: false, usesState: true, + usesStore: storeDependencies.length > 0, mutation: `${snippet} = ${value}`, - props: dependencies.map((prop: string) => `${prop}: state.${prop}`) + props: dependencies.map((prop: string) => `${prop}: state.${prop}`), + storeProps: storeDependencies.map(prop => `${prop}: $.${prop}`) }; } + let props; + let storeProps; + + if (generator.options.store && name[0] === '$') { + props = []; + storeProps = [`${name.slice(1)}: ${value}`]; + } else { + props = [`${name}: ${value}`]; + storeProps = []; + } + return { usesContext: false, usesState: false, + usesStore: false, mutation: null, - props: [`${name}: ${value}`] + props, + storeProps }; } @@ -393,4 +425,4 @@ function isComputed(node: Node) { } return false; -} +} \ No newline at end of file diff --git a/test/js/samples/onrender-onteardown-rewritten/expected.js b/test/js/samples/onrender-onteardown-rewritten/expected.js index 19b85a62e0..ae6046dddb 100644 --- a/test/js/samples/onrender-onteardown-rewritten/expected.js +++ b/test/js/samples/onrender-onteardown-rewritten/expected.js @@ -24,7 +24,7 @@ function SvelteComponent(options) { init(this, options); this._state = assign({}, options.data); - this._handlers.destroy = [ondestroy] + this._handlers.destroy = [ondestroy]; var _oncreate = oncreate.bind(this); diff --git a/test/runtime/samples/store-binding/NameInput.html b/test/runtime/samples/store-binding/NameInput.html new file mode 100644 index 0000000000..a5e4f5e48c --- /dev/null +++ b/test/runtime/samples/store-binding/NameInput.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/test/runtime/samples/store-binding/_config.js b/test/runtime/samples/store-binding/_config.js new file mode 100644 index 0000000000..c9ae020777 --- /dev/null +++ b/test/runtime/samples/store-binding/_config.js @@ -0,0 +1,28 @@ +import Store from '../../../../store.js'; + +const store = new Store({ + name: 'world' +}); + +export default { + store, + + html: ` +