diff --git a/compiler/generate/index.js b/compiler/generate/index.js index 57cc64bbec..5af327eb3f 100644 --- a/compiler/generate/index.js +++ b/compiler/generate/index.js @@ -272,12 +272,13 @@ export default function generate ( parsed, template, options = {} ) { }; this.on = function on ( eventName, handler ) { - callbacks[ eventName ] || ( callbacks[ eventName ] = [] ).push( handler ); + const handlers = callbacks[ eventName ] || ( callbacks[ eventName ] = [] ); + handlers.push( handler ); return { cancel: function () { - const index = callbacks.indexOf( handler ); - if ( ~index ) callbacks.splice( index, 1 ); + const index = handlers.indexOf( handler ); + if ( ~index ) handlers.splice( index, 1 ); } }; }; diff --git a/compiler/generate/visitors/attributes/addComponentAttributes.js b/compiler/generate/visitors/attributes/addComponentAttributes.js index df98c4804d..782dedfeef 100644 --- a/compiler/generate/visitors/attributes/addComponentAttributes.js +++ b/compiler/generate/visitors/attributes/addComponentAttributes.js @@ -57,7 +57,7 @@ export default function addComponentAttributes ( generator, node, local ) { const usedContexts = new Set(); attribute.expression.arguments.forEach( arg => { - const contexts = generator.contextualise( arg, true ); + const contexts = generator.contextualise( arg, true, true ); contexts.forEach( context => { usedContexts.add( context ); @@ -75,32 +75,13 @@ export default function addComponentAttributes ( generator, node, local ) { return `var ${listName} = this.__svelte.${listName}, ${indexName} = this.__svelte.${indexName}, ${name} = ${listName}[${indexName}]`; }); - const handlerName = generator.current.counter( `${attribute.name}Handler` ); const handlerBody = ( declarations.length ? declarations.join( '\n' ) + '\n\n' : '' ) + `[✂${attribute.expression.start}-${attribute.expression.end}✂];`; - if ( attribute.name in generator.events ) { - local.init.push( deindent` - const ${handlerName} = template.events.${attribute.name}( ${local.name}, function ( event ) { - ${handlerBody} - }); - ` ); - - local.teardown.push( deindent` - ${handlerName}.teardown(); - ` ); - } else { - local.init.push( deindent` - function ${handlerName} ( event ) { - ${handlerBody} - } - - ${local.name}.addEventListener( '${attribute.name}', ${handlerName}, false ); - ` ); - - local.teardown.push( deindent` - ${local.name}.removeEventListener( '${attribute.name}', ${handlerName}, false ); - ` ); - } + local.init.push( deindent` + ${local.name}.on( '${attribute.name}', function ( event ) { + ${handlerBody} + }); + ` ); } else if ( attribute.type === 'Binding' ) { diff --git a/test/compiler/component-events-data/Widget.html b/test/compiler/component-events-data/Widget.html new file mode 100644 index 0000000000..5087ccc68e --- /dev/null +++ b/test/compiler/component-events-data/Widget.html @@ -0,0 +1,3 @@ + + + diff --git a/test/compiler/component-events-data/_config.js b/test/compiler/component-events-data/_config.js new file mode 100644 index 0000000000..9235660a98 --- /dev/null +++ b/test/compiler/component-events-data/_config.js @@ -0,0 +1,26 @@ +import * as assert from 'assert'; + +export default { + test ( component, target, window ) { + const buttons = target.querySelectorAll( 'button' ); + const click = new window.MouseEvent( 'click' ); + + const selected = []; + + component.on( 'select', selection => { + selected.push( selection ); + }); + + buttons[1].dispatchEvent( click ); + buttons[2].dispatchEvent( click ); + buttons[1].dispatchEvent( click ); + buttons[0].dispatchEvent( click ); + + assert.deepEqual( selected, [ + 'bar', + 'baz', + 'bar', + 'foo' + ]); + } +}; diff --git a/test/compiler/component-events-data/main.html b/test/compiler/component-events-data/main.html new file mode 100644 index 0000000000..75d457ee24 --- /dev/null +++ b/test/compiler/component-events-data/main.html @@ -0,0 +1,11 @@ +
+ +
+ + diff --git a/test/compiler/component-events/Widget.html b/test/compiler/component-events/Widget.html new file mode 100644 index 0000000000..460a2a1c01 --- /dev/null +++ b/test/compiler/component-events/Widget.html @@ -0,0 +1 @@ +

i am a widget

diff --git a/test/compiler/component-events/_config.js b/test/compiler/component-events/_config.js new file mode 100644 index 0000000000..af5345aafa --- /dev/null +++ b/test/compiler/component-events/_config.js @@ -0,0 +1,23 @@ +import * as assert from 'assert'; + +export default { + data: { + visible: true + }, + html: '

i am a widget

', // TODO comment should follow component... + test ( component ) { + let count = 0; + + component.on( 'widgetTornDown', function () { + assert.equal( this, component ); + count += 1; + }); + + component.set({ visible: false }); + assert.equal( count, 1 ); + + component.set({ visible: true }); + component.set({ visible: false }); + assert.equal( count, 2 ); + } +}; diff --git a/test/compiler/component-events/main.html b/test/compiler/component-events/main.html new file mode 100644 index 0000000000..12c5f78472 --- /dev/null +++ b/test/compiler/component-events/main.html @@ -0,0 +1,13 @@ +
+ {{#if visible}} + + {{/if}} +
+ +