From 2768653a47201b1ade5e0e1a9afebacf116df8d3 Mon Sep 17 00:00:00 2001 From: Rich-Harris Date: Fri, 9 Dec 2016 09:00:02 -0500 Subject: [PATCH 1/2] =?UTF-8?q?allow=20event=20handlers=20to=20call=20even?= =?UTF-8?q?t=20methods=20e.g.=20stopPropagation=20=E2=80=93=20closes=20#16?= =?UTF-8?q?2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../attributes/addElementAttributes.js | 8 +++++++- .../event-handler-event-methods/_config.js | 15 +++++++++++++++ .../event-handler-event-methods/main.html | 18 ++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 test/generator/event-handler-event-methods/_config.js create mode 100644 test/generator/event-handler-event-methods/main.html diff --git a/src/generate/visitors/attributes/addElementAttributes.js b/src/generate/visitors/attributes/addElementAttributes.js index 532835732c..c4c2d7e8de 100644 --- a/src/generate/visitors/attributes/addElementAttributes.js +++ b/src/generate/visitors/attributes/addElementAttributes.js @@ -1,6 +1,7 @@ import attributeLookup from './lookup.js'; import createBinding from './binding/index.js'; import deindent from '../../../utils/deindent.js'; +import flattenReference from '../../../utils/flattenReference.js'; export default function addElementAttributes ( generator, node, local ) { node.attributes.forEach( attribute => { @@ -114,7 +115,12 @@ export default function addElementAttributes ( generator, node, local ) { else if ( attribute.type === 'EventHandler' ) { // TODO verify that it's a valid callee (i.e. built-in or declared method) generator.addSourcemapLocations( attribute.expression ); - generator.code.prependRight( attribute.expression.start, 'component.' ); + + const flattened = flattenReference( attribute.expression.callee ); + if ( flattened.name !== 'event' ) { + // allow event.stopPropagation() etc + generator.code.prependRight( attribute.expression.start, 'component.' ); + } const usedContexts = new Set(); attribute.expression.arguments.forEach( arg => { diff --git a/test/generator/event-handler-event-methods/_config.js b/test/generator/event-handler-event-methods/_config.js new file mode 100644 index 0000000000..2b8ddd4f50 --- /dev/null +++ b/test/generator/event-handler-event-methods/_config.js @@ -0,0 +1,15 @@ +export default { + solo: true, + show: true, + + test ( assert, component, target, window ) { + const allow = target.querySelector( '.allow-propagation' ); + const stop = target.querySelector( '.stop-propagation' ); + + allow.dispatchEvent( new window.MouseEvent( 'click', { bubbles: true }) ); + stop.dispatchEvent( new window.MouseEvent( 'click', { bubbles: true }) ); + + assert.equal( component.get( 'foo' ), true ); + assert.equal( component.get( 'bar' ), false ); + } +}; diff --git a/test/generator/event-handler-event-methods/main.html b/test/generator/event-handler-event-methods/main.html new file mode 100644 index 0000000000..0aa130e449 --- /dev/null +++ b/test/generator/event-handler-event-methods/main.html @@ -0,0 +1,18 @@ +
+ +
+ +
+ +
+ + From 4f4a967fd6a097b484a80f376c5443ecb92cbd07 Mon Sep 17 00:00:00 2001 From: Rich-Harris Date: Fri, 9 Dec 2016 09:10:42 -0500 Subject: [PATCH 2/2] support node methods in event handlers (#162) --- .../visitors/attributes/addElementAttributes.js | 4 ++-- src/utils/flattenReference.js | 6 +++--- .../event-handler-event-methods/_config.js | 3 --- .../event-handler-this-methods/_config.js | 16 ++++++++++++++++ .../event-handler-this-methods/main.html | 2 ++ 5 files changed, 23 insertions(+), 8 deletions(-) create mode 100644 test/generator/event-handler-this-methods/_config.js create mode 100644 test/generator/event-handler-this-methods/main.html diff --git a/src/generate/visitors/attributes/addElementAttributes.js b/src/generate/visitors/attributes/addElementAttributes.js index c4c2d7e8de..4873d2d637 100644 --- a/src/generate/visitors/attributes/addElementAttributes.js +++ b/src/generate/visitors/attributes/addElementAttributes.js @@ -117,8 +117,8 @@ export default function addElementAttributes ( generator, node, local ) { generator.addSourcemapLocations( attribute.expression ); const flattened = flattenReference( attribute.expression.callee ); - if ( flattened.name !== 'event' ) { - // allow event.stopPropagation() etc + if ( flattened.name !== 'event' && flattened.name !== 'this' ) { + // allow event.stopPropagation(), this.select() etc generator.code.prependRight( attribute.expression.start, 'component.' ); } diff --git a/src/utils/flattenReference.js b/src/utils/flattenReference.js index 2000c8941a..c975c65095 100644 --- a/src/utils/flattenReference.js +++ b/src/utils/flattenReference.js @@ -7,10 +7,10 @@ export default function flatten ( node ) { node = node.object; } - if ( node.type !== 'Identifier' ) return null; + const name = node.type === 'Identifier' ? node.name : node.type === 'ThisExpression' ? 'this' : null; - const name = node.name; - parts.unshift( name ); + if ( !name ) return null; + parts.unshift( name ); return { name, keypath: parts.join( '.' ) }; } diff --git a/test/generator/event-handler-event-methods/_config.js b/test/generator/event-handler-event-methods/_config.js index 2b8ddd4f50..8b701e9825 100644 --- a/test/generator/event-handler-event-methods/_config.js +++ b/test/generator/event-handler-event-methods/_config.js @@ -1,7 +1,4 @@ export default { - solo: true, - show: true, - test ( assert, component, target, window ) { const allow = target.querySelector( '.allow-propagation' ); const stop = target.querySelector( '.stop-propagation' ); diff --git a/test/generator/event-handler-this-methods/_config.js b/test/generator/event-handler-this-methods/_config.js new file mode 100644 index 0000000000..170ce46b0f --- /dev/null +++ b/test/generator/event-handler-this-methods/_config.js @@ -0,0 +1,16 @@ +export default { + test ( assert, component, target, window ) { + // Click events don't focus elements in JSDOM – obviously they would + // in real browsers. More realistically, you'd use this for e.g. + // this.select(), but that's harder to test than this.focus() + + const wont = target.querySelector( '.wont-focus' ); + const will = target.querySelector( '.will-focus' ); + + wont.dispatchEvent( new window.MouseEvent( 'click' ) ); + assert.equal( window.document.activeElement, window.document.body ); + + will.dispatchEvent( new window.MouseEvent( 'click' ) ); + assert.equal( window.document.activeElement, will ); + } +}; diff --git a/test/generator/event-handler-this-methods/main.html b/test/generator/event-handler-this-methods/main.html new file mode 100644 index 0000000000..a9f8282c9e --- /dev/null +++ b/test/generator/event-handler-this-methods/main.html @@ -0,0 +1,2 @@ + +