From a7471cfc904882d597b00f65f7e83c8f42529cba Mon Sep 17 00:00:00 2001 From: Conduitry Date: Fri, 17 Jan 2020 07:22:40 -0500 Subject: [PATCH] apply event modifiers to events (#4279) --- CHANGELOG.md | 1 + .../compile/render_dom/wrappers/Body.ts | 25 ++++++++----------- .../wrappers/Element/EventHandler.ts | 3 ++- .../wrappers/shared/add_event_handlers.ts | 5 ++-- .../_config.js | 11 ++++++++ .../main.svelte | 5 ++++ 6 files changed, 33 insertions(+), 17 deletions(-) create mode 100644 test/runtime/samples/event-handler-modifier-body-once/_config.js create mode 100644 test/runtime/samples/event-handler-modifier-body-once/main.svelte diff --git a/CHANGELOG.md b/CHANGELOG.md index bc6cf3610910..9b2c8f5b0757 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * Disallow two-way binding to a variable declared by an `{#await}` block ([#4012](https://github.com/sveltejs/svelte/issues/4012)) * Allow access to `let:` variables in sibling attributes on slot root ([#4173](https://github.com/sveltejs/svelte/issues/4173)) * Add some more known globals ([#4276](https://github.com/sveltejs/svelte/pull/4276)) +* Correctly apply event modifiers to `` events ([#4278](https://github.com/sveltejs/svelte/issues/4278)) ## 3.17.1 diff --git a/src/compiler/compile/render_dom/wrappers/Body.ts b/src/compiler/compile/render_dom/wrappers/Body.ts index e16ebc25bd26..d80ef6c4a092 100644 --- a/src/compiler/compile/render_dom/wrappers/Body.ts +++ b/src/compiler/compile/render_dom/wrappers/Body.ts @@ -1,26 +1,23 @@ import Block from '../Block'; import Wrapper from './shared/Wrapper'; -import { b } from 'code-red'; +import { x } from 'code-red'; import Body from '../../nodes/Body'; import { Identifier } from 'estree'; import EventHandler from './Element/EventHandler'; +import add_event_handlers from './shared/add_event_handlers'; +import { TemplateNode } from '../../../interfaces'; +import Renderer from '../Renderer'; export default class BodyWrapper extends Wrapper { node: Body; + handlers: EventHandler[]; - render(block: Block, _parent_node: Identifier, _parent_nodes: Identifier) { - this.node.handlers - .map(handler => new EventHandler(handler, this)) - .forEach(handler => { - const snippet = handler.get_snippet(block); - - block.chunks.init.push(b` - @_document.body.addEventListener("${handler.node.name}", ${snippet}); - `); + constructor(renderer: Renderer, block: Block, parent: Wrapper, node: TemplateNode) { + super(renderer, block, parent, node); + this.handlers = this.node.handlers.map(handler => new EventHandler(handler, this)); + } - block.chunks.destroy.push(b` - @_document.body.removeEventListener("${handler.node.name}", ${snippet}); - `); - }); + render(block: Block, _parent_node: Identifier, _parent_nodes: Identifier) { + add_event_handlers(block, x`@_document.body`, this.handlers); } } diff --git a/src/compiler/compile/render_dom/wrappers/Element/EventHandler.ts b/src/compiler/compile/render_dom/wrappers/Element/EventHandler.ts index 03183ee5767b..157e186ea6eb 100644 --- a/src/compiler/compile/render_dom/wrappers/Element/EventHandler.ts +++ b/src/compiler/compile/render_dom/wrappers/Element/EventHandler.ts @@ -2,6 +2,7 @@ import EventHandler from '../../../nodes/EventHandler'; import Wrapper from '../shared/Wrapper'; import Block from '../../Block'; import { b, x, p } from 'code-red'; +import { Expression } from 'estree'; const TRUE = x`true`; const FALSE = x`false`; @@ -35,7 +36,7 @@ export default class EventHandlerWrapper { return snippet; } - render(block: Block, target: string) { + render(block: Block, target: string | Expression) { let snippet = this.get_snippet(block); if (this.node.modifiers.has('preventDefault')) snippet = x`@prevent_default(${snippet})`; diff --git a/src/compiler/compile/render_dom/wrappers/shared/add_event_handlers.ts b/src/compiler/compile/render_dom/wrappers/shared/add_event_handlers.ts index 23a37715ccce..99b8080b17ee 100644 --- a/src/compiler/compile/render_dom/wrappers/shared/add_event_handlers.ts +++ b/src/compiler/compile/render_dom/wrappers/shared/add_event_handlers.ts @@ -1,9 +1,10 @@ import Block from '../../Block'; import EventHandler from '../Element/EventHandler'; +import { Expression } from 'estree'; export default function add_event_handlers( block: Block, - target: string, + target: string | Expression, handlers: EventHandler[] ) { handlers.forEach(handler => add_event_handler(block, target, handler)); @@ -11,7 +12,7 @@ export default function add_event_handlers( export function add_event_handler( block: Block, - target: string, + target: string | Expression, handler: EventHandler ) { handler.render(block, target); diff --git a/test/runtime/samples/event-handler-modifier-body-once/_config.js b/test/runtime/samples/event-handler-modifier-body-once/_config.js new file mode 100644 index 000000000000..412703401098 --- /dev/null +++ b/test/runtime/samples/event-handler-modifier-body-once/_config.js @@ -0,0 +1,11 @@ +export default { + async test({ assert, component, window }) { + const event = new window.MouseEvent('click'); + + await window.document.body.dispatchEvent(event); + assert.equal(component.count, 1); + + await window.document.body.dispatchEvent(event); + assert.equal(component.count, 1); + } +}; diff --git a/test/runtime/samples/event-handler-modifier-body-once/main.svelte b/test/runtime/samples/event-handler-modifier-body-once/main.svelte new file mode 100644 index 000000000000..423a75d1f056 --- /dev/null +++ b/test/runtime/samples/event-handler-modifier-body-once/main.svelte @@ -0,0 +1,5 @@ + + + \ No newline at end of file