feat: fix accessors and support migration of accessors (#13456)

* feat: fix accessors and support migration of accessors

* fix: exclude slots

* fix: remove call to proxy for accessors props

Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>

* chore: add test for accessors

* chore: fix lint

---------

Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
pull/13485/head
Paolo Ricciuti 12 months ago committed by GitHub
parent dfe0138e0d
commit c716329806
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
feat: fix accessors and support migration of accessors

@ -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(/(<svelte:options\s.*?\s?)accessors\s?/g, (_, $1) => $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</script>\n\n');
}

@ -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))])];

@ -0,0 +1,14 @@
<script lang="ts">
type $$Props = {
test: string;
}
export let count = 0;
export let stuff;
</script>
<button>
<slot name="cool" />
</button>
<svelte:options accessors immutable/>

@ -0,0 +1,29 @@
<script lang="ts">
interface Props {
test: string;
count?: number;
stuff: any;
cool?: import('svelte').Snippet;
}
let {
test,
count = 0,
stuff,
cool
}: Props = $props();
export {
test,
count,
stuff,
}
</script>
<button>
{@render cool?.()}
</button>
<svelte:options immutable/>

@ -0,0 +1,15 @@
import { ok, test } from '../../test';
import { flushSync } from 'svelte';
export default test({
html: `<p>0</p>`,
async test({ assert, target, instance }) {
const p = target.querySelector('p');
ok(p);
flushSync(() => {
instance.count++;
});
assert.equal(p.innerHTML, '1');
}
});

@ -0,0 +1,9 @@
<script>
let { count=0 } = $props();
export {
count
}
</script>
<p>{count}</p>
Loading…
Cancel
Save