diff --git a/.changeset/tiny-meals-deliver.md b/.changeset/tiny-meals-deliver.md new file mode 100644 index 0000000000..94969362d0 --- /dev/null +++ b/.changeset/tiny-meals-deliver.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: mark `accessors` and `immutable` as deprecated diff --git a/packages/svelte/messages/compile-warnings/legacy.md b/packages/svelte/messages/compile-warnings/legacy.md index 88c5ea9670..c0cc85359e 100644 --- a/packages/svelte/messages/compile-warnings/legacy.md +++ b/packages/svelte/messages/compile-warnings/legacy.md @@ -16,4 +16,4 @@ ## deprecated_event_handler -> Using on:%name% to listen to the %name% event is is deprecated. Use the event attribute on%name% instead. \ No newline at end of file +> Using on:%name% to listen to the %name% event is is deprecated. Use the event attribute on%name% instead. diff --git a/packages/svelte/messages/compile-warnings/options.md b/packages/svelte/messages/compile-warnings/options.md index 584900923c..5513f05f6e 100644 --- a/packages/svelte/messages/compile-warnings/options.md +++ b/packages/svelte/messages/compile-warnings/options.md @@ -1,3 +1,7 @@ +## options_deprecated_accessors + +The `accessors` option has been deprecated. It will have no effect in runes mode + ## options_deprecated_immutable > The `immutable` option has been deprecated. It will have no effect in runes mode diff --git a/packages/svelte/scripts/process-messages/index.js b/packages/svelte/scripts/process-messages/index.js index 84a0b25d5c..ace3a5e66c 100644 --- a/packages/svelte/scripts/process-messages/index.js +++ b/packages/svelte/scripts/process-messages/index.js @@ -13,7 +13,9 @@ for (const category of fs.readdirSync('messages')) { for (const file of fs.readdirSync(`messages/${category}`)) { if (!file.endsWith('.md')) continue; - const markdown = fs.readFileSync(`messages/${category}/${file}`, 'utf-8'); + const markdown = fs + .readFileSync(`messages/${category}/${file}`, 'utf-8') + .replace(/\r\n/g, '\n'); for (const match of markdown.matchAll(/## ([\w]+)\n\n([^]+?)(?=$|\n\n## )/g)) { const [_, code, text] = match; @@ -33,7 +35,9 @@ for (const category of fs.readdirSync('messages')) { } function transform(name, dest) { - const source = fs.readFileSync(new URL(`./templates/${name}.js`, import.meta.url), 'utf-8'); + const source = fs + .readFileSync(new URL(`./templates/${name}.js`, import.meta.url), 'utf-8') + .replace(/\r\n/g, '\n'); const comments = []; @@ -217,7 +221,8 @@ function transform(name, dest) { fs.writeFileSync( dest, - `/* This file is generated by scripts/process-messages.js. Do not edit! */\n\n` + module.code, + `/* This file is generated by scripts/process-messages/index.js. Do not edit! */\n\n` + + module.code, 'utf-8' ); } diff --git a/packages/svelte/src/compiler/errors.js b/packages/svelte/src/compiler/errors.js index 761478c24c..096a2ef97c 100644 --- a/packages/svelte/src/compiler/errors.js +++ b/packages/svelte/src/compiler/errors.js @@ -1,4 +1,4 @@ -/* This file is generated by scripts/process-messages.js. Do not edit! */ +/* This file is generated by scripts/process-messages/index.js. Do not edit! */ /** @typedef {{ start?: number, end?: number }} NodeLike */ // interface is duplicated between here (used internally) and ./interfaces.js diff --git a/packages/svelte/src/compiler/phases/2-analyze/index.js b/packages/svelte/src/compiler/phases/2-analyze/index.js index 5811f130b9..bac63eab45 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/index.js +++ b/packages/svelte/src/compiler/phases/2-analyze/index.js @@ -374,7 +374,7 @@ export function analyze_component(root, source, options) { inject_styles: options.css === 'injected' || options.customElement, accessors: options.customElement ? true - : !!options.accessors || + : (runes ? false : !!options.accessors) || // because $set method needs accessors !!options.legacy?.componentApi, reactive_statements: new Map(), @@ -395,8 +395,20 @@ export function analyze_component(root, source, options) { source }; - if (!options.customElement && root.options?.customElement) { - w.options_missing_custom_element(root.options); + if (root.options) { + for (const attribute of root.options.attributes) { + if (attribute.name === 'accessors') { + w.options_deprecated_accessors(attribute); + } + + if (attribute.name === 'customElement' && !options.customElement) { + w.options_missing_custom_element(attribute); + } + + if (attribute.name === 'immutable') { + w.options_deprecated_immutable(attribute); + } + } } if (analysis.runes) { diff --git a/packages/svelte/src/compiler/types/index.d.ts b/packages/svelte/src/compiler/types/index.d.ts index d94a80a77c..1b4a09d989 100644 --- a/packages/svelte/src/compiler/types/index.d.ts +++ b/packages/svelte/src/compiler/types/index.d.ts @@ -94,6 +94,7 @@ export interface CompileOptions extends ModuleCompileOptions { * If `true`, getters and setters will be created for the component's props. If `false`, they will only be created for readonly exported values (i.e. those declared with `const`, `class` and `function`). If compiling with `customElement: true` this option defaults to `true`. * * @default false + * @deprecated This will have no effect in runes mode */ accessors?: boolean; /** @@ -107,6 +108,7 @@ export interface CompileOptions extends ModuleCompileOptions { * This allows it to be less conservative about checking whether values have changed. * * @default false + * @deprecated This will have no effect in runes mode */ immutable?: boolean; /** diff --git a/packages/svelte/src/compiler/validate-options.js b/packages/svelte/src/compiler/validate-options.js index 157ea6fd35..4d3880c52c 100644 --- a/packages/svelte/src/compiler/validate-options.js +++ b/packages/svelte/src/compiler/validate-options.js @@ -39,7 +39,7 @@ export const validate_component_options = object({ ...common, - accessors: boolean(false), + accessors: deprecate(w.options_deprecated_accessors, boolean(false)), css: validator('external', (input) => { if (input === true || input === false) { diff --git a/packages/svelte/src/compiler/warnings.js b/packages/svelte/src/compiler/warnings.js index d4a41de1a1..2d1d80c403 100644 --- a/packages/svelte/src/compiler/warnings.js +++ b/packages/svelte/src/compiler/warnings.js @@ -1,4 +1,4 @@ -/* This file is generated by scripts/process-messages.js. Do not edit! */ +/* This file is generated by scripts/process-messages/index.js. Do not edit! */ import { getLocator } from 'locate-character'; @@ -544,6 +544,14 @@ export function invalid_self_closing_tag(node, name) { w(node, "invalid_self_closing_tag", `Self-closing HTML tags for non-void elements are ambiguous — use <${name} ...> rather than <${name} ... />`); } +/** + * e `accessors` option has been deprecated. It will have no effect in runes mode + * @param {null | NodeLike} node + */ +export function options_deprecated_accessors(node) { + w(node, "options_deprecated_accessors", "e `accessors` option has been deprecated. It will have no effect in runes mode"); +} + /** * The `immutable` option has been deprecated. It will have no effect in runes mode * @param {null | NodeLike} node diff --git a/packages/svelte/src/internal/client/errors.js b/packages/svelte/src/internal/client/errors.js index a3bbc71b65..1666e30ff5 100644 --- a/packages/svelte/src/internal/client/errors.js +++ b/packages/svelte/src/internal/client/errors.js @@ -1,4 +1,4 @@ -/* This file is generated by scripts/process-messages.js. Do not edit! */ +/* This file is generated by scripts/process-messages/index.js. Do not edit! */ import { DEV } from 'esm-env'; diff --git a/packages/svelte/src/internal/client/render.js b/packages/svelte/src/internal/client/render.js index 698935ff44..17933b3559 100644 --- a/packages/svelte/src/internal/client/render.js +++ b/packages/svelte/src/internal/client/render.js @@ -119,7 +119,7 @@ export function mount(component, options) { * events?: { [Property in keyof Events]: (e: Events[Property]) => any }; * context?: Map; * intro?: boolean; - * recover?: false; + * recover?: boolean; * }} options * @returns {Exports} */ diff --git a/packages/svelte/src/internal/client/warnings.js b/packages/svelte/src/internal/client/warnings.js index 6cf03e5d98..66d72758bf 100644 --- a/packages/svelte/src/internal/client/warnings.js +++ b/packages/svelte/src/internal/client/warnings.js @@ -1,4 +1,4 @@ -/* This file is generated by scripts/process-messages.js. Do not edit! */ +/* This file is generated by scripts/process-messages/index.js. Do not edit! */ import { DEV } from 'esm-env'; diff --git a/packages/svelte/src/internal/shared/warnings.js b/packages/svelte/src/internal/shared/warnings.js index 7d85dcf154..a3b4876a74 100644 --- a/packages/svelte/src/internal/shared/warnings.js +++ b/packages/svelte/src/internal/shared/warnings.js @@ -1,4 +1,4 @@ -/* This file is generated by scripts/process-messages.js. Do not edit! */ +/* This file is generated by scripts/process-messages/index.js. Do not edit! */ import { DEV } from 'esm-env'; diff --git a/packages/svelte/tests/runtime-browser/test.ts b/packages/svelte/tests/runtime-browser/test.ts index d58f7e78cd..1b97988fda 100644 --- a/packages/svelte/tests/runtime-browser/test.ts +++ b/packages/svelte/tests/runtime-browser/test.ts @@ -94,7 +94,10 @@ async function run_test( write(`${test_dir}/_output/client/${path.basename(args.path)}.js`, compiled.js.code); - compiled.warnings.forEach((warning) => warnings.push(warning)); + compiled.warnings.forEach((warning) => { + if (warning.code === 'options_deprecated_accessors') return; + warnings.push(warning); + }); if (compiled.css !== null) { compiled.js.code += `document.head.innerHTML += \`\``; @@ -179,6 +182,7 @@ async function run_test( ); } else if (warnings.length) { /* eslint-disable no-unsafe-finally */ + console.warn(warnings); throw new Error('Received unexpected warnings'); } } diff --git a/packages/svelte/tests/runtime-legacy/shared.ts b/packages/svelte/tests/runtime-legacy/shared.ts index 029b9e4cef..21012a8f5a 100644 --- a/packages/svelte/tests/runtime-legacy/shared.ts +++ b/packages/svelte/tests/runtime-legacy/shared.ts @@ -2,7 +2,8 @@ import * as fs from 'node:fs'; import { setImmediate } from 'node:timers/promises'; import glob from 'tiny-glob/sync.js'; import { createClassComponent } from 'svelte/legacy'; -import { flushSync } from 'svelte'; +import { proxy } from 'svelte/internal/client'; +import { flushSync, hydrate, mount, unmount } from 'svelte'; import { render } from 'svelte/server'; import { afterAll, assert, beforeAll } from 'vitest'; import { compile_directory } from '../helpers.js'; @@ -43,6 +44,7 @@ export interface RuntimeTest = Record; mod: any; ok: typeof ok; raf: { @@ -120,7 +122,7 @@ export function runtime_suite(runes: boolean) { return common_setup(cwd, runes, config); }, async (config, cwd, variant, common) => { - await run_test_variant(cwd, config, variant, common); + await run_test_variant(cwd, config, variant, common, runes); } ); } @@ -148,7 +150,8 @@ async function run_test_variant( cwd: string, config: RuntimeTest, variant: 'dom' | 'hydrate' | 'ssr', - compileOptions: CompileOptions + compileOptions: CompileOptions, + runes: boolean ) { let unintended_error = false; @@ -289,15 +292,30 @@ async function run_test_variant( } }; - const instance = createClassComponent({ - component: mod.default, - props: config.props, - target, - immutable: config.immutable, - intro: config.intro, - recover: config.recover ?? false, - hydrate: variant === 'hydrate' - }); + let instance: any; + let props: any; + + if (runes) { + props = proxy({ ...(config.props || {}) }); + + const render = variant === 'hydrate' ? hydrate : mount; + instance = render(mod.default, { + target, + props, + intro: config.intro, + recover: config.recover ?? false + }); + } else { + instance = createClassComponent({ + component: mod.default, + props: config.props, + target, + immutable: config.immutable, + intro: config.intro, + recover: config.recover ?? false, + hydrate: variant === 'hydrate' + }); + } // eslint-disable-next-line no-console console.error = error; @@ -327,7 +345,8 @@ async function run_test_variant( htmlEqualWithOptions: assert_html_equal_with_options }, variant, - component: instance, + component: runes ? props : instance, + instance, mod, target, snapshot, @@ -344,7 +363,11 @@ async function run_test_variant( assert.fail('Expected a runtime error'); } } finally { - instance.$destroy(); + if (runes) { + unmount(instance); + } else { + instance.$destroy(); + } if (config.warnings) { assert.deepEqual(warnings, config.warnings); diff --git a/packages/svelte/tests/runtime-runes/samples/each-bind-this-member/_config.js b/packages/svelte/tests/runtime-runes/samples/each-bind-this-member/_config.js index 4b5596cb3a..51458e901d 100644 --- a/packages/svelte/tests/runtime-runes/samples/each-bind-this-member/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/each-bind-this-member/_config.js @@ -1,6 +1,12 @@ import { test } from '../../test'; export default test({ + get props() { + return { + items: [{ src: 'https://ds' }] + }; + }, + async test({ assert, target, component }) { assert.equal(target.querySelector('img'), component.items[0].img); } diff --git a/packages/svelte/tests/runtime-runes/samples/each-bind-this-member/main.svelte b/packages/svelte/tests/runtime-runes/samples/each-bind-this-member/main.svelte index 7d46ea90f0..2926ba615b 100644 --- a/packages/svelte/tests/runtime-runes/samples/each-bind-this-member/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/each-bind-this-member/main.svelte @@ -1,5 +1,5 @@ {#each items as item, i} diff --git a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-2/_config.js b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-2/_config.js index b0271da3f1..1066d9a2df 100644 --- a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-2/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-2/_config.js @@ -1,3 +1,4 @@ +import { flushSync } from 'svelte'; import { test } from '../../test'; export default test({ @@ -27,7 +28,7 @@ export default test({ logs.length = 0; - component.n += 1; + flushSync(() => (component.n += 1)); assert.deepEqual(logs, [ 'parent: $effect.pre 1', diff --git a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-3/_config.js b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-3/_config.js index 04cfa4b0d5..55847c35a2 100644 --- a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-3/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-3/_config.js @@ -1,3 +1,4 @@ +import { flushSync } from 'svelte'; import { test } from '../../test'; export default test({ @@ -22,7 +23,7 @@ export default test({ logs.length = 0; - component.n += 1; + flushSync(() => (component.n += 1)); assert.deepEqual(logs, [ 'parent: render 1', diff --git a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-4/_config.js b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-4/_config.js index d0e27957c5..0cd7e15a37 100644 --- a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-4/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-4/_config.js @@ -1,3 +1,4 @@ +import { flushSync } from 'svelte'; import { test } from '../../test'; export default test({ @@ -27,7 +28,7 @@ export default test({ logs.length = 0; - component.n += 1; + flushSync(() => (component.n += 1)); assert.deepEqual(logs, [ 'parent: $effect.pre 1', diff --git a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-5/_config.js b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-5/_config.js index 54212a580a..1cea16963f 100644 --- a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-5/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-5/_config.js @@ -1,3 +1,4 @@ +import { flushSync } from 'svelte'; import { test } from '../../test'; export default test({ @@ -9,7 +10,7 @@ export default test({ assert.deepEqual(logs, ['$effect.pre 0', 'another $effect.pre 1', 'render n0', 'render i1']); logs.length = 0; - component.n += 1; + flushSync(() => (component.n += 1)); assert.deepEqual(logs, ['$effect.pre 1', 'another $effect.pre 2', 'render n1', 'render i2']); } diff --git a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children/_config.js b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children/_config.js index affe03c344..19b8fb3938 100644 --- a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children/_config.js @@ -1,3 +1,4 @@ +import { flushSync } from 'svelte'; import { test } from '../../test'; export default test({ @@ -23,7 +24,7 @@ export default test({ logs.length = 0; - component.n += 1; + flushSync(() => (component.n += 1)); assert.deepEqual(logs, [ 'parent: $effect.pre 1', diff --git a/packages/svelte/tests/runtime-runes/samples/props-default-value-lazy-accessors/_config.js b/packages/svelte/tests/runtime-runes/samples/props-default-value-lazy-accessors/_config.js index 0919bdfca9..68402956d5 100644 --- a/packages/svelte/tests/runtime-runes/samples/props-default-value-lazy-accessors/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/props-default-value-lazy-accessors/_config.js @@ -1,3 +1,4 @@ +import { flushSync } from '../../../../src/index-client.js'; import { test } from '../../test'; // Tests that default values only fire lazily when the prop is undefined, and every time @@ -8,22 +9,32 @@ export default test({ p2: 0, p3: 0 }, + html: `

props: 0 0 0 0 1 1 1 1

log: nested.fallback_value,fallback_fn`, + async test({ assert, target, component }) { - component.p0 = undefined; - component.p1 = undefined; - component.p2 = undefined; - component.p3 = undefined; - // Nuance: these are already undefined in the props, but we're setting them to undefined again, - // which calls the fallback value again, even if it will result in the same value. There's no way - // to prevent this, and in practise it won't matter - and you shouldn't use accessors in runes mode anyway. - component.p4 = undefined; - component.p5 = undefined; - component.p6 = undefined; - component.p7 = undefined; + flushSync(() => { + component.p0 = undefined; + component.p1 = undefined; + component.p2 = undefined; + component.p3 = undefined; + }); + + assert.htmlEqual( + target.innerHTML, + `

props: 1 1 1 1 1 1 1 1

log: nested.fallback_value,fallback_fn,nested.fallback_value,fallback_fn` + ); + + flushSync(() => { + component.p4 = undefined; + component.p5 = undefined; + component.p6 = undefined; + component.p7 = undefined; + }); + assert.htmlEqual( target.innerHTML, - `

props: 1 1 1 1 1 1 1 1

log: nested.fallback_value,fallback_fn,nested.fallback_value,fallback_fn,nested.fallback_value,fallback_fn` + `

props: 1 1 1 1 1 1 1 1

log: nested.fallback_value,fallback_fn,nested.fallback_value,fallback_fn` ); } }); diff --git a/packages/svelte/tests/runtime-runes/samples/props-quoted/_config.js b/packages/svelte/tests/runtime-runes/samples/props-quoted/_config.js index c2cc143e5c..7058097317 100644 --- a/packages/svelte/tests/runtime-runes/samples/props-quoted/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/props-quoted/_config.js @@ -1,3 +1,4 @@ +import { flushSync } from 'svelte'; import { test } from '../../test'; export default test({ @@ -8,7 +9,7 @@ export default test({ html: `hello`, async test({ assert, target, component }) { - component['kebab-case'] = 'goodbye'; + flushSync(() => (component['kebab-case'] = 'goodbye')); assert.htmlEqual(target.innerHTML, `goodbye`); } }); diff --git a/packages/svelte/tests/runtime-runes/samples/props/_config.js b/packages/svelte/tests/runtime-runes/samples/props/_config.js index 751d89e35b..f8c3efb534 100644 --- a/packages/svelte/tests/runtime-runes/samples/props/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/props/_config.js @@ -1,3 +1,4 @@ +import { flushSync } from 'svelte'; import { test } from '../../test'; export default test({ @@ -9,14 +10,14 @@ export default test({ default2: undefined }; }, + html: `x 1 2 3 z`, async test({ assert, target, component }) { - component.foo = 'y'; + flushSync(() => (component.foo = 'y')); assert.htmlEqual(target.innerHTML, `y 1 2 3 z`); - // rest props don't generate accessors, so we need to use $set - await component.$set({ bar: 'w' }); + flushSync(() => (component.bar = 'w')); assert.htmlEqual(target.innerHTML, `y 1 2 3 w`); } }); diff --git a/packages/svelte/tests/runtime-runes/samples/transition-evaluation/_config.js b/packages/svelte/tests/runtime-runes/samples/transition-evaluation/_config.js index f07ed3e0a6..982cd3a9eb 100644 --- a/packages/svelte/tests/runtime-runes/samples/transition-evaluation/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/transition-evaluation/_config.js @@ -1,3 +1,4 @@ +import { flushSync } from '../../../../src/index-client.js'; import { test } from '../../test'; export default test({ @@ -5,8 +6,10 @@ export default test({ const div = /** @type {HTMLDivElement & { foo?: number }} */ (target.querySelector('div')); assert.equal(div.foo, undefined); - component.foo = 2; - component.visible = false; + flushSync(() => { + component.foo = 2; + component.visible = false; + }); assert.equal(div.foo, 2); } }); diff --git a/packages/svelte/tests/validator/samples/tag-custom-element-options-missing/warnings.json b/packages/svelte/tests/validator/samples/tag-custom-element-options-missing/warnings.json index bdc1d737b8..b3b8054008 100644 --- a/packages/svelte/tests/validator/samples/tag-custom-element-options-missing/warnings.json +++ b/packages/svelte/tests/validator/samples/tag-custom-element-options-missing/warnings.json @@ -4,11 +4,11 @@ "message": "The `customElement` option is used when generating a custom element. Did you forget the `customElement: true` compile option?", "start": { "line": 1, - "column": 0 + "column": 16 }, "end": { "line": 1, - "column": 49 + "column": 46 } } ] diff --git a/packages/svelte/types/index.d.ts b/packages/svelte/types/index.d.ts index c5c91e67cc..9540b52e57 100644 --- a/packages/svelte/types/index.d.ts +++ b/packages/svelte/types/index.d.ts @@ -345,7 +345,7 @@ declare module 'svelte' { events?: { [Property in keyof Events]: (e: Events[Property]) => any; } | undefined; context?: Map | undefined; intro?: boolean | undefined; - recover?: false | undefined; + recover?: boolean | undefined; }): Exports; /** * Unmounts a component that was previously mounted using `mount` or `hydrate`. @@ -623,6 +623,7 @@ declare module 'svelte/compiler' { * If `true`, getters and setters will be created for the component's props. If `false`, they will only be created for readonly exported values (i.e. those declared with `const`, `class` and `function`). If compiling with `customElement: true` this option defaults to `true`. * * @default false + * @deprecated This will have no effect in runes mode */ accessors?: boolean; /** @@ -636,6 +637,7 @@ declare module 'svelte/compiler' { * This allows it to be less conservative about checking whether values have changed. * * @default false + * @deprecated This will have no effect in runes mode */ immutable?: boolean; /** @@ -2419,6 +2421,7 @@ declare module 'svelte/types/compiler/interfaces' { * If `true`, getters and setters will be created for the component's props. If `false`, they will only be created for readonly exported values (i.e. those declared with `const`, `class` and `function`). If compiling with `customElement: true` this option defaults to `true`. * * @default false + * @deprecated This will have no effect in runes mode */ accessors?: boolean; /** @@ -2432,6 +2435,7 @@ declare module 'svelte/types/compiler/interfaces' { * This allows it to be less conservative about checking whether values have changed. * * @default false + * @deprecated This will have no effect in runes mode */ immutable?: boolean; /** diff --git a/sites/svelte-5-preview/src/routes/docs/content/03-appendix/02-breaking-changes.md b/sites/svelte-5-preview/src/routes/docs/content/03-appendix/02-breaking-changes.md index 43a5c7134c..c5b35e2423 100644 --- a/sites/svelte-5-preview/src/routes/docs/content/03-appendix/02-breaking-changes.md +++ b/sites/svelte-5-preview/src/routes/docs/content/03-appendix/02-breaking-changes.md @@ -129,6 +129,10 @@ Exports from runes mode components cannot be bound to directly. For example, hav In Svelte 4 syntax, every property (declared via `export let`) is bindable, meaning you can `bind:` to it. In runes mode, properties are not bindable by default: you need to denote bindable props with the [`$bindable`](/docs/runes#$bindable) rune. +### `accessors` option is ignored + +Setting the `accessors` option to `true` makes properties of a component directly accessible on the component instance. In runes mode, properties are never accessible on the component instance. You can use component exports instead if you need to expose them. + ## Other breaking changes ### Stricter `@const` assignment validation