diff --git a/.changeset/large-rules-hang.md b/.changeset/large-rules-hang.md new file mode 100644 index 0000000000..f018f44cd8 --- /dev/null +++ b/.changeset/large-rules-hang.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +feat: fix accessors and support migration of accessors diff --git a/packages/svelte/src/compiler/migrate/index.js b/packages/svelte/src/compiler/migrate/index.js index 109059f583..1ae100c656 100644 --- a/packages/svelte/src/compiler/migrate/index.js +++ b/packages/svelte/src/compiler/migrate/index.js @@ -12,7 +12,6 @@ import { get_rune } from '../phases/scope.js'; import { reset, reset_warning_filter } from '../state.js'; import { extract_identifiers } from '../utils/ast.js'; import { migrate_svelte_ignore } from '../utils/extract_svelte_ignore.js'; -import { determine_slot } from '../utils/slot.js'; import { validate_component_options } from '../validate-options.js'; import { is_svg, is_void } from '../../utils.js'; @@ -55,6 +54,8 @@ export function migrate(source) { const analysis = analyze_component(parsed, source, combined_options); const indent = guess_indent(source); + str.replaceAll(/( $1); + for (const content of style_contents) { str.overwrite(content[0], content[0] + style_placeholder.length, content[1]); } @@ -269,6 +270,13 @@ export function migrate(source) { ); } + if (state.props.length > 0 && state.analysis.accessors) { + str.appendRight( + insertion_point, + `\n${indent}export {${state.props.reduce((acc, prop) => (prop.slot_name ? acc : `${acc}\n${indent}\t${prop.local},`), '')}\n${indent}}\n` + ); + } + if (!parsed.instance && need_script) { str.appendRight(insertion_point, '\n\n\n'); } diff --git a/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js b/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js index d0e6efc6d8..c98135f8e1 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js @@ -276,6 +276,10 @@ export function client_component(analysis, options) { } } + if (binding?.kind === 'prop' || binding?.kind === 'bindable_prop') { + return [getter, b.set(alias ?? name, [b.stmt(b.call(name, b.id('$$value')))])]; + } + if (binding?.kind === 'state' || binding?.kind === 'raw_state') { const value = binding.kind === 'state' ? b.call('$.proxy', b.id('$$value')) : b.id('$$value'); return [getter, b.set(alias ?? name, [b.stmt(b.call('$.set', b.id(name), value))])]; diff --git a/packages/svelte/tests/migrate/samples/accessors/input.svelte b/packages/svelte/tests/migrate/samples/accessors/input.svelte new file mode 100644 index 0000000000..d987aeddad --- /dev/null +++ b/packages/svelte/tests/migrate/samples/accessors/input.svelte @@ -0,0 +1,14 @@ + + + + + \ No newline at end of file diff --git a/packages/svelte/tests/migrate/samples/accessors/output.svelte b/packages/svelte/tests/migrate/samples/accessors/output.svelte new file mode 100644 index 0000000000..67b0737d0e --- /dev/null +++ b/packages/svelte/tests/migrate/samples/accessors/output.svelte @@ -0,0 +1,29 @@ + + + + + \ No newline at end of file diff --git a/packages/svelte/tests/runtime-runes/samples/accessors-props/_config.js b/packages/svelte/tests/runtime-runes/samples/accessors-props/_config.js new file mode 100644 index 0000000000..27b5113307 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/accessors-props/_config.js @@ -0,0 +1,15 @@ +import { ok, test } from '../../test'; +import { flushSync } from 'svelte'; + +export default test({ + html: `

0

`, + + async test({ assert, target, instance }) { + const p = target.querySelector('p'); + ok(p); + flushSync(() => { + instance.count++; + }); + assert.equal(p.innerHTML, '1'); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/accessors-props/main.svelte b/packages/svelte/tests/runtime-runes/samples/accessors-props/main.svelte new file mode 100644 index 0000000000..faeca3cd8c --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/accessors-props/main.svelte @@ -0,0 +1,9 @@ + + +

{count}