support once modifier on component events, fail on others (#2987)

* support once modifier on component events, fail on others. fixes #2654

* appease the gods of typescript
pull/2992/head
Rich Harris 5 years ago committed by GitHub
parent 9754f2a817
commit 1102ff6426
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -100,6 +100,17 @@ export default class InlineComponent extends Node {
this.scope = scope;
}
this.handlers.forEach(handler => {
handler.modifiers.forEach(modifier => {
if (modifier !== 'once') {
component.error(handler, {
code: 'invalid-event-modifier',
message: `Event modifiers other than 'once' can only be used on DOM elements`
});
}
});
});
this.children = map_children(component, this, this.scope, info.children);
}
}

@ -363,7 +363,9 @@ export default class InlineComponentWrapper extends Wrapper {
});
const munged_handlers = this.node.handlers.map(handler => {
const snippet = handler.render(block);
let snippet = handler.render(block);
if (handler.modifiers.has('once')) snippet = `@once(${snippet})`;
return `${name}.$on("${handler.name}", ${snippet});`;
});

@ -81,6 +81,15 @@ export function exclude_internal_props(props) {
return result;
}
export function once(fn) {
let ran = false;
return function(this: any, ...args) {
if (ran) return;
ran = true;
fn.call(this, ...args);
}
}
const is_client = typeof window !== 'undefined';
export let now: () => number = is_client

@ -0,0 +1,16 @@
export default {
html: `
<button>0</button>
`,
async test({ assert, component, target, window }) {
const button = target.querySelector('button');
const event = new window.MouseEvent('click');
await button.dispatchEvent(event);
assert.equal(component.count, 1);
await button.dispatchEvent(event);
assert.equal(component.count, 1);
}
};

@ -0,0 +1,6 @@
<script>
import Button from './Button.svelte';
export let count = 0;
</script>
<Button on:click|once="{() => count += 1}">{count}</Button>

@ -0,0 +1,15 @@
[{
"message": "Event modifiers other than 'once' can only be used on DOM elements",
"code": "invalid-event-modifier",
"start": {
"line": 6,
"column": 8,
"character": 93
},
"end": {
"line": 6,
"column": 40,
"character": 125
},
"pos": 93
}]

@ -0,0 +1,6 @@
<script>
import Button from './Button.svelte';
const doThat = () => {};
</script>
<Button on:click|preventDefault={doThat}></Button>
Loading…
Cancel
Save