From b80d9bd65428d1426a7b20f20b4f0037788ae43a Mon Sep 17 00:00:00 2001 From: Simon H <5968653+dummdidumm@users.noreply.github.com> Date: Tue, 20 Feb 2024 11:37:09 +0100 Subject: [PATCH] fix: wire up `events` in `mount` correctly and fix its types (#10553) fixes #10551 --- .changeset/shaggy-cameras-live.md | 5 +++++ packages/svelte/src/internal/client/render.js | 18 +++++++++++----- .../samples/manual-mount/_config.js | 21 +++++++++++++++++++ .../samples/manual-mount/inner.svelte | 11 ++++++++++ .../samples/manual-mount/main.svelte | 20 ++++++++++++++++++ packages/svelte/tests/types/component.ts | 6 ++++-- packages/svelte/types/index.d.ts | 4 ++-- 7 files changed, 76 insertions(+), 9 deletions(-) create mode 100644 .changeset/shaggy-cameras-live.md create mode 100644 packages/svelte/tests/runtime-runes/samples/manual-mount/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/manual-mount/inner.svelte create mode 100644 packages/svelte/tests/runtime-runes/samples/manual-mount/main.svelte diff --git a/.changeset/shaggy-cameras-live.md b/.changeset/shaggy-cameras-live.md new file mode 100644 index 0000000000..230154b652 --- /dev/null +++ b/.changeset/shaggy-cameras-live.md @@ -0,0 +1,5 @@ +--- +"svelte": patch +--- + +fix: wire up `events` in `mount` correctly and fix its types diff --git a/packages/svelte/src/internal/client/render.js b/packages/svelte/src/internal/client/render.js index 74a41ccc9a..0da5bf690a 100644 --- a/packages/svelte/src/internal/client/render.js +++ b/packages/svelte/src/internal/client/render.js @@ -2432,7 +2432,7 @@ export function createRoot() { * @param {{ * target: Node; * props?: Props; - * events?: Events; + * events?: { [Property in keyof Events]: (e: Events[Property]) => any }; * context?: Map; * intro?: boolean; * }} options @@ -2456,7 +2456,7 @@ export function mount(component, options) { * @param {{ * target: Node; * props?: Props; - * events?: Events; + * events?: { [Property in keyof Events]: (e: Events[Property]) => any }; * context?: Map; * intro?: boolean; * recover?: false; @@ -2524,7 +2524,7 @@ export function hydrate(component, options) { * target: Node; * anchor: null | Text; * props?: Props; - * events?: Events; + * events?: { [Property in keyof Events]: (e: Events[Property]) => any }; * context?: Map; * intro?: boolean; * recover?: false; @@ -2547,8 +2547,16 @@ function _mount(Component, options) { /** @type {import('../client/types.js').ComponentContext} */ (current_component_context).c = options.context; } - // @ts-expect-error the public typings are not what the actual function looks like - component = Component(options.anchor, options.props || {}) || {}; + if (!options.props) { + options.props = /** @type {Props} */ ({}); + } + if (options.events) { + // We can't spread the object or else we'd lose the state proxy stuff, if it is one + /** @type {any} */ (options.props).$$events = options.events; + } + component = + // @ts-expect-error the public typings are not what the actual function looks like + Component(options.anchor, options.props) || {}; if (options.context) { pop(); } diff --git a/packages/svelte/tests/runtime-runes/samples/manual-mount/_config.js b/packages/svelte/tests/runtime-runes/samples/manual-mount/_config.js new file mode 100644 index 0000000000..2166618553 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/manual-mount/_config.js @@ -0,0 +1,21 @@ +import { tick } from 'svelte'; +import { test } from '../../test'; + +export default test({ + html: `
`, + async test({ assert, target }) { + const button = target.querySelector('button'); + + await button?.click(); + assert.htmlEqual(target.innerHTML, `
`); + + const inner_button = target.querySelector('div')?.querySelector('button'); + + inner_button?.click(); + await tick(); + assert.htmlEqual(target.innerHTML, `
`); + + await button?.click(); + assert.htmlEqual(target.innerHTML, `
`); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/manual-mount/inner.svelte b/packages/svelte/tests/runtime-runes/samples/manual-mount/inner.svelte new file mode 100644 index 0000000000..25246b4b2a --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/manual-mount/inner.svelte @@ -0,0 +1,11 @@ + + + diff --git a/packages/svelte/tests/runtime-runes/samples/manual-mount/main.svelte b/packages/svelte/tests/runtime-runes/samples/manual-mount/main.svelte new file mode 100644 index 0000000000..e03f0c8394 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/manual-mount/main.svelte @@ -0,0 +1,20 @@ + + + +
diff --git a/packages/svelte/tests/types/component.ts b/packages/svelte/tests/types/component.ts index 153f453d2a..e2fc094bab 100644 --- a/packages/svelte/tests/types/component.ts +++ b/packages/svelte/tests/types/component.ts @@ -112,7 +112,7 @@ mount(NewComponent, { x: '' }, events: { - event: new MouseEvent('click') + event: (e) => e.offsetX }, immutable: true, intro: false, @@ -127,7 +127,9 @@ hydrate(NewComponent, { x: '' }, events: { - event: new MouseEvent('click') + event: (e) => + // @ts-expect-error + e.doesNotExist }, immutable: true, intro: false, diff --git a/packages/svelte/types/index.d.ts b/packages/svelte/types/index.d.ts index db6efb9fb4..d3fb1f340d 100644 --- a/packages/svelte/types/index.d.ts +++ b/packages/svelte/types/index.d.ts @@ -334,7 +334,7 @@ declare module 'svelte' { export function mount, Exports extends Record, Events extends Record>(component: ComponentType>, options: { target: Node; props?: Props | undefined; - events?: Events | undefined; + events?: { [Property in keyof Events]: (e: Events[Property]) => any; } | undefined; context?: Map | undefined; intro?: boolean | undefined; }): Exports; @@ -345,7 +345,7 @@ declare module 'svelte' { export function hydrate, Exports extends Record, Events extends Record>(component: ComponentType>, options: { target: Node; props?: Props | undefined; - events?: Events | undefined; + events?: { [Property in keyof Events]: (e: Events[Property]) => any; } | undefined; context?: Map | undefined; intro?: boolean | undefined; recover?: false | undefined;