From facf528cb8a7289c8b3eaf036949a515f5ad2108 Mon Sep 17 00:00:00 2001 From: brunnerh Date: Wed, 25 Jun 2025 20:35:48 +0200 Subject: [PATCH 1/8] docs: Simplify TS config docs (#16236) * Simplify TypeScript config requirements Assignments are allowed in the constructor from 5.31.0 onward, so retaining the classes via ES2015 should be enough. * Add back a little bit of detail. --- documentation/docs/07-misc/03-typescript.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/docs/07-misc/03-typescript.md b/documentation/docs/07-misc/03-typescript.md index fbf8817069..ff33885fb8 100644 --- a/documentation/docs/07-misc/03-typescript.md +++ b/documentation/docs/07-misc/03-typescript.md @@ -83,7 +83,7 @@ If you're using tools like Rollup or Webpack instead, install their respective S When using TypeScript, make sure your `tsconfig.json` is setup correctly. -- Use a [`target`](https://www.typescriptlang.org/tsconfig/#target) of at least `ES2022`, or a `target` of at least `ES2015` alongside [`useDefineForClassFields`](https://www.typescriptlang.org/tsconfig/#useDefineForClassFields). This ensures that rune declarations on class fields are not messed with, which would break the Svelte compiler +- Use a [`target`](https://www.typescriptlang.org/tsconfig/#target) of at least `ES2015` so classes are not compiled to functions - Set [`verbatimModuleSyntax`](https://www.typescriptlang.org/tsconfig/#verbatimModuleSyntax) to `true` so that imports are left as-is - Set [`isolatedModules`](https://www.typescriptlang.org/tsconfig/#isolatedModules) to `true` so that each file is looked at in isolation. TypeScript has a few features which require cross-file analysis and compilation, which the Svelte compiler and tooling like Vite don't do. From 0b2b9c724fef657af9371089e468d5c49c209e36 Mon Sep 17 00:00:00 2001 From: 7nik Date: Wed, 25 Jun 2025 21:38:26 +0300 Subject: [PATCH 2/8] chore: adjust linting (#16231) * chore: adjust linting * more nice treeshaking failure message * lint --- .prettierignore | 4 +- eslint.config.js | 1 + .../svelte/scripts/check-treeshakeability.js | 50 ++++++++++--------- 3 files changed, 30 insertions(+), 25 deletions(-) diff --git a/.prettierignore b/.prettierignore index d5c124353c..72cd10aca8 100644 --- a/.prettierignore +++ b/.prettierignore @@ -7,6 +7,7 @@ packages/**/config/*.js # packages/svelte packages/svelte/messages/**/*.md +packages/svelte/scripts/_bundle.js packages/svelte/src/compiler/errors.js packages/svelte/src/compiler/warnings.js packages/svelte/src/internal/client/errors.js @@ -25,8 +26,7 @@ packages/svelte/tests/hydration/samples/*/_expected.html packages/svelte/tests/hydration/samples/*/_override.html packages/svelte/types packages/svelte/compiler/index.js -playgrounds/sandbox/input/**.svelte -playgrounds/sandbox/output +playgrounds/sandbox/src/* # sites/svelte.dev sites/svelte.dev/static/svelte-app.json diff --git a/eslint.config.js b/eslint.config.js index d6c977a36a..d7044fc9f1 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -87,6 +87,7 @@ export default [ '**/*.d.ts', '**/tests', 'packages/svelte/scripts/process-messages/templates/*.js', + 'packages/svelte/scripts/_bundle.js', 'packages/svelte/src/compiler/errors.js', 'packages/svelte/src/internal/client/errors.js', 'packages/svelte/src/internal/client/warnings.js', diff --git a/packages/svelte/scripts/check-treeshakeability.js b/packages/svelte/scripts/check-treeshakeability.js index 1501ee6954..e883496fe2 100644 --- a/packages/svelte/scripts/check-treeshakeability.js +++ b/packages/svelte/scripts/check-treeshakeability.js @@ -118,36 +118,40 @@ const bundle = await bundle_code( ).js.code ); -if (!bundle.includes('hydrate_node') && !bundle.includes('hydrate_next')) { - // eslint-disable-next-line no-console - console.error(`✅ Hydration code treeshakeable`); -} else { - failed = true; - // eslint-disable-next-line no-console - console.error(`❌ Hydration code not treeshakeable`); -} +/** + * @param {string} case_name + * @param {string[]} strings + */ +function check_bundle(case_name, ...strings) { + for (const string of strings) { + const index = bundle.indexOf(string); + if (index >= 0) { + // eslint-disable-next-line no-console + console.error(`❌ ${case_name} not treeshakeable`); + failed = true; -if (!bundle.includes('component_context.l')) { - // eslint-disable-next-line no-console - console.error(`✅ Legacy code treeshakeable`); -} else { - failed = true; + let lines = bundle.slice(index - 500, index + 500).split('\n'); + const target_line = lines.findIndex((line) => line.includes(string)); + // mark the failed line + lines = lines + .map((line, i) => (i === target_line ? `> ${line}` : `| ${line}`)) + .slice(target_line - 5, target_line + 6); + // eslint-disable-next-line no-console + console.error('The first failed line:\n' + lines.join('\n')); + return; + } + } // eslint-disable-next-line no-console - console.error(`❌ Legacy code not treeshakeable`); + console.error(`✅ ${case_name} treeshakeable`); } -if (!bundle.includes(`'CreatedAt'`)) { - // eslint-disable-next-line no-console - console.error(`✅ $inspect.trace code treeshakeable`); -} else { - failed = true; - // eslint-disable-next-line no-console - console.error(`❌ $inspect.trace code not treeshakeable`); -} +check_bundle('Hydration code', 'hydrate_node', 'hydrate_next'); +check_bundle('Legacy code', 'component_context.l'); +check_bundle('$inspect.trace', `'CreatedAt'`); if (failed) { // eslint-disable-next-line no-console - console.error(bundle); + console.error('Full bundle at', path.resolve('scripts/_bundle.js')); fs.writeFileSync('scripts/_bundle.js', bundle); } From da2feafe6765d2278ff053f62e6603a60b06833e Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Wed, 25 Jun 2025 14:40:52 -0400 Subject: [PATCH 3/8] chore: silence some pesky logs (#16241) --- .../samples/inspect-state-unsafe-mutation/_config.js | 6 +++++- .../legacy-runes-ambiguous-export-labeled/_config.js | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/svelte/tests/runtime-runes/samples/inspect-state-unsafe-mutation/_config.js b/packages/svelte/tests/runtime-runes/samples/inspect-state-unsafe-mutation/_config.js index 7e8fcd2d48..dcf3a8bc3d 100644 --- a/packages/svelte/tests/runtime-runes/samples/inspect-state-unsafe-mutation/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/inspect-state-unsafe-mutation/_config.js @@ -5,5 +5,9 @@ export default test({ compileOptions: { dev: true }, - error: 'state_unsafe_mutation' + + error: 'state_unsafe_mutation', + + // silence the logs + test({ logs }) {} }); diff --git a/packages/svelte/tests/runtime-runes/samples/legacy-runes-ambiguous-export-labeled/_config.js b/packages/svelte/tests/runtime-runes/samples/legacy-runes-ambiguous-export-labeled/_config.js index 904fea3f65..c4cff665d2 100644 --- a/packages/svelte/tests/runtime-runes/samples/legacy-runes-ambiguous-export-labeled/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/legacy-runes-ambiguous-export-labeled/_config.js @@ -6,7 +6,7 @@ export default test({ compileOptions: { runes: undefined }, - async test({ assert, target }) { + async test({ assert, target, logs }) { const p = target.querySelector('p'); const btn = target.querySelector('button'); flushSync(() => { From 213274a75ecc71dd86a31ba2dab4f594fc2cd265 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 26 Jun 2025 18:23:10 -0400 Subject: [PATCH 4/8] chore: reduce some select.value indirection (#16250) --- .../client/visitors/RegularElement.js | 21 ++++++++----------- .../client/visitors/shared/utils.js | 14 ------------- 2 files changed, 9 insertions(+), 26 deletions(-) diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/RegularElement.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/RegularElement.js index 1aefff0db0..b0f285eb41 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/RegularElement.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/RegularElement.js @@ -25,7 +25,6 @@ import { process_children } from './shared/fragment.js'; import { build_render_statement, build_template_chunk, - build_update_assignment, get_expression_id, memoize_expression } from './shared/utils.js'; @@ -657,17 +656,15 @@ function build_element_special_value_attribute(element, node_id, attribute, cont } if (has_state) { - const id = state.scope.generate(`${node_id.name}_value`); - build_update_assignment( - state, - id, - // `