From 35a5d8f53726c3dc18f9940db86a25fedfc9497e Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Sun, 22 Apr 2018 12:06:04 -0400 Subject: [PATCH] prevent stale state in component event handlers - fixes #1353 --- src/generators/nodes/Component.ts | 7 ++++- .../component-event-not-stale/Button.html | 1 + .../component-event-not-stale/_config.js | 30 +++++++++++++++++++ .../component-event-not-stale/main.html | 20 +++++++++++++ 4 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 test/runtime/samples/component-event-not-stale/Button.html create mode 100644 test/runtime/samples/component-event-not-stale/_config.js create mode 100644 test/runtime/samples/component-event-not-stale/main.html diff --git a/src/generators/nodes/Component.ts b/src/generators/nodes/Component.ts index cc82981928..a1861664eb 100644 --- a/src/generators/nodes/Component.ts +++ b/src/generators/nodes/Component.ts @@ -10,6 +10,7 @@ import mungeAttribute from './shared/mungeAttribute'; import Node from './shared/Node'; import Block from '../dom/Block'; import Attribute from './Attribute'; +import usesThisOrArguments from '../../validate/js/utils/usesThisOrArguments'; export default class Component extends Node { type: 'Component'; @@ -494,8 +495,11 @@ function mungeEventHandler(generator: DomGenerator, node: Node, handler: Node, b ); } + let usesState = false; + handler.expression.arguments.forEach((arg: Node) => { const { contexts } = block.contextualise(arg, null, true); + if (contexts.has('state')) usesState = true; contexts.forEach(context => { allContexts.add(context); @@ -503,11 +507,12 @@ function mungeEventHandler(generator: DomGenerator, node: Node, handler: Node, b }); body = deindent` + ${usesState && `const state = #component.get();`} [✂${handler.expression.start}-${handler.expression.end}✂]; `; } else { body = deindent` - ${block.alias('component')}.fire('${handler.name}', event); + #component.fire('${handler.name}', event); `; } diff --git a/test/runtime/samples/component-event-not-stale/Button.html b/test/runtime/samples/component-event-not-stale/Button.html new file mode 100644 index 0000000000..f2decc7386 --- /dev/null +++ b/test/runtime/samples/component-event-not-stale/Button.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/test/runtime/samples/component-event-not-stale/_config.js b/test/runtime/samples/component-event-not-stale/_config.js new file mode 100644 index 0000000000..3d6dd936ea --- /dev/null +++ b/test/runtime/samples/component-event-not-stale/_config.js @@ -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 } + ]); + }, +}; diff --git a/test/runtime/samples/component-event-not-stale/main.html b/test/runtime/samples/component-event-not-stale/main.html new file mode 100644 index 0000000000..e244f596ad --- /dev/null +++ b/test/runtime/samples/component-event-not-stale/main.html @@ -0,0 +1,20 @@ + + + + \ No newline at end of file