prevent stale state in component event handlers - fixes #1353

pull/1366/head
Rich Harris 7 years ago
parent a6262cee4d
commit 35a5d8f537

@ -10,6 +10,7 @@ import mungeAttribute from './shared/mungeAttribute';
import Node from './shared/Node'; import Node from './shared/Node';
import Block from '../dom/Block'; import Block from '../dom/Block';
import Attribute from './Attribute'; import Attribute from './Attribute';
import usesThisOrArguments from '../../validate/js/utils/usesThisOrArguments';
export default class Component extends Node { export default class Component extends Node {
type: 'Component'; type: 'Component';
@ -494,8 +495,11 @@ function mungeEventHandler(generator: DomGenerator, node: Node, handler: Node, b
); );
} }
let usesState = false;
handler.expression.arguments.forEach((arg: Node) => { handler.expression.arguments.forEach((arg: Node) => {
const { contexts } = block.contextualise(arg, null, true); const { contexts } = block.contextualise(arg, null, true);
if (contexts.has('state')) usesState = true;
contexts.forEach(context => { contexts.forEach(context => {
allContexts.add(context); allContexts.add(context);
@ -503,11 +507,12 @@ function mungeEventHandler(generator: DomGenerator, node: Node, handler: Node, b
}); });
body = deindent` body = deindent`
${usesState && `const state = #component.get();`}
[${handler.expression.start}-${handler.expression.end}]; [${handler.expression.start}-${handler.expression.end}];
`; `;
} else { } else {
body = deindent` body = deindent`
${block.alias('component')}.fire('${handler.name}', event); #component.fire('${handler.name}', event);
`; `;
} }

@ -0,0 +1,30 @@
export default {
data: {
value: 1,
},
test(assert, component, target, window) {
const buttons = target.querySelectorAll('button');
const click = new window.MouseEvent('click');
const events = [];
component.on('value', event => {
events.push(event);
});
buttons[0].dispatchEvent(click);
buttons[1].dispatchEvent(click);
component.set({ value: 2 });
buttons[0].dispatchEvent(click);
buttons[1].dispatchEvent(click);
assert.deepEqual(events, [
{ value: 1 },
{ value: 1 },
{ value: 2 },
{ value: 2 }
]);
},
};

@ -0,0 +1,20 @@
<Button on:click="handleClick()">one</Button>
<Button on:click="fire('value', {value})">two</Button>
<script>
import Button from './Button.html';
export default {
components: {
Button
},
methods: {
handleClick() {
const { value } = this.get();
this.fire('value', { value });
}
}
}
</script>
Loading…
Cancel
Save