diff --git a/.changeset/fast-parser-hotpaths.md b/.changeset/fast-parser-hotpaths.md new file mode 100644 index 0000000000..f442e2435f --- /dev/null +++ b/.changeset/fast-parser-hotpaths.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +perf: optimize parser hot paths for faster compilation diff --git a/.changeset/rotten-taxes-float.md b/.changeset/rotten-taxes-float.md new file mode 100644 index 0000000000..4c04f78324 --- /dev/null +++ b/.changeset/rotten-taxes-float.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +chore: more efficient effect scheduling diff --git a/.changeset/vast-ties-wash.md b/.changeset/vast-ties-wash.md new file mode 100644 index 0000000000..39c14b4a17 --- /dev/null +++ b/.changeset/vast-ties-wash.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +chore: null out current_batch before committing branches diff --git a/.github/workflows/pkg.pr.new.yml b/.github/workflows/pkg.pr.new.yml index e7cc1facad..cd3df32064 100644 --- a/.github/workflows/pkg.pr.new.yml +++ b/.github/workflows/pkg.pr.new.yml @@ -10,6 +10,10 @@ on: description: 'Commit SHA to build' required: true type: string + pr: + description: 'PR number to comment on' + required: true + type: number permissions: {} @@ -127,26 +131,16 @@ jobs: return; } - const { data: pulls } = await github.rest.repos.listPullRequestsAssociatedWithCommit({ - owner: context.repo.owner, - repo: context.repo.repo, - commit_sha: '${{ inputs.sha }}', - }); - - const open = pulls.filter(p => p.state === 'open'); - - if (open.length === 0) { - core.setFailed(`No open PR found for commit ${{ inputs.sha }}`); - return; - } - - if (open.length > 1) { - const nums = open.map(p => `#${p.number}`).join(', '); - core.setFailed(`Multiple open PRs found for commit ${{ inputs.sha }}: ${nums}`); + // For workflow_dispatch, use the explicitly provided PR number. + // We can't use listPullRequestsAssociatedWithCommit because fork + // commits don't exist in the base repo, so the API returns nothing. + const pr = Number('${{ inputs.pr }}'); + if (!pr || isNaN(pr)) { + core.setFailed('workflow_dispatch requires a valid pr input'); return; } - core.setOutput('number', open[0].number); + core.setOutput('number', pr); - name: Post or update comment uses: actions/github-script@v8 diff --git a/documentation/docs/05-special-elements/01-svelte-boundary.md b/documentation/docs/05-special-elements/01-svelte-boundary.md index 40e8d144e1..e1ad00a50b 100644 --- a/documentation/docs/05-special-elements/01-svelte-boundary.md +++ b/documentation/docs/05-special-elements/01-svelte-boundary.md @@ -102,3 +102,40 @@ If an `onerror` function is provided, it will be called with the same two `error ``` If an error occurs inside the `onerror` function (or if you rethrow the error), it will be handled by a parent boundary if such exists. + +## Using `transformError` + +By default, error boundaries have no effect on the server — if an error occurs during rendering, the render as a whole will fail. + +Since 5.51 you can control this behaviour for boundaries with a `failed` snippet, by calling [`render(...)`](imperative-component-api#render) with a `transformError` function. + +> [!NOTE] If you're using Svelte via a framework such as SvelteKit, you most likely don't have direct access to the `render(...)` call — the framework must configure `transformError` on your behalf. SvelteKit will add support for this in the near future, via the [`handleError`](../kit/hooks#Shared-hooks-handleError) hook. + +The `transformError` function must return a JSON-stringifiable object which will be used to render the `failed` snippet. This object will be serialized and used to hydrate the snippet in the browser: + +```js +// @errors: 1005 +import { render } from 'svelte/server'; +import App from './App.svelte'; + +const { head, body } = await render(App, { + transformError: (error) => { + // log the original error, with the stack trace... + console.error(error); + + // ...and return a sanitized user-friendly error + // to display in the `failed` snippet + return { + message: 'An error occurred!' + }; + }; +}); +``` + +If `transformError` throws (or rethrows) an error, `render(...)` as a whole will fail with that error. + +> [!NOTE] Errors that occur during server-side rendering can contain sensitive information in the `message` and `stack`. It's recommended to redact these rather than sending them unaltered to the browser. + +If the boundary has an `onerror` handler, it will be called upon hydration with the deserialized error object. + +The [`mount`](imperative-component-api#mount) and [`hydrate`](imperative-component-api#hydrate) functions also accept a `transformError` option, which defaults to the identity function. As with `render`, this function transforms a render-time error before it is passed to a `failed` snippet or `onerror` handler. diff --git a/documentation/docs/05-special-elements/03-svelte-document.md b/documentation/docs/05-special-elements/03-svelte-document.md index 43f02865e6..47c382ee56 100644 --- a/documentation/docs/05-special-elements/03-svelte-document.md +++ b/documentation/docs/05-special-elements/03-svelte-document.md @@ -10,12 +10,12 @@ title: ``` -Similarly to ``, this element allows you to add listeners to events on `document`, such as `visibilitychange`, which don't fire on `window`. It also lets you use [actions](use) on `document`. +Similarly to ``, this element allows you to add listeners to events on `document`, such as `visibilitychange`, which don't fire on `window`. It also lets you use [attachments](@attach) on `document`. As with ``, this element may only appear the top level of your component and must never be inside a block or element. ```svelte - + ``` You can also bind to the following properties: diff --git a/documentation/docs/07-misc/03-typescript.md b/documentation/docs/07-misc/03-typescript.md index 49ecd8adb5..899849473c 100644 --- a/documentation/docs/07-misc/03-typescript.md +++ b/documentation/docs/07-misc/03-typescript.md @@ -75,7 +75,7 @@ In both cases, a `svelte.config.js` with `vitePreprocess` will be added. Vite/Sv ### Other build tools -If you're using tools like Rollup or Webpack instead, install their respective Svelte plugins. For Rollup that's [rollup-plugin-svelte](https://github.com/sveltejs/rollup-plugin-svelte) and for Webpack that's [svelte-loader](https://github.com/sveltejs/svelte-loader). For both, you need to install `typescript` and `svelte-preprocess` and add the preprocessor to the plugin config (see the respective READMEs for more info). If you're starting a new project, you can also use the [rollup](https://github.com/sveltejs/template) or [webpack](https://github.com/sveltejs/template-webpack) template to scaffold the setup from a script. +If you're using tools like Rollup or Webpack instead, install their respective Svelte plugins. For Rollup that's [rollup-plugin-svelte](https://github.com/sveltejs/rollup-plugin-svelte) and for Webpack that's [svelte-loader](https://github.com/sveltejs/svelte-loader). For both, you need to install `typescript` and `svelte-preprocess` and add the preprocessor to the plugin config (see the respective READMEs for more info). > [!NOTE] If you're starting a new project, we recommend using SvelteKit or Vite instead diff --git a/documentation/docs/07-misc/07-v5-migration-guide.md b/documentation/docs/07-misc/07-v5-migration-guide.md index 5a80734b7a..564c707fd2 100644 --- a/documentation/docs/07-misc/07-v5-migration-guide.md +++ b/documentation/docs/07-misc/07-v5-migration-guide.md @@ -682,6 +682,24 @@ Previously, Svelte employed a very complicated algorithm to determine if whitesp - Whitespace between nodes is collapsed to one whitespace - Whitespace at the start and end of a tag is removed completely + + This new behavior is slightly different from native HTML rendering. For example, `

foo - bar

` will render: + + - `foo - bar` in HTML + - `foo- bar` in Svelte 5 + + You can reintroduce the missing space by moving it outside the ``... + + ```svelte +

foo - bar

+ ``` + +...or, if necessary for styling reasons, including it as an expression: + +```svelte +

foo{' '}- bar

+``` + - Certain exceptions apply such as keeping whitespace inside `pre` tags As before, you can disable whitespace trimming by setting the `preserveWhitespace` option in your compiler settings or on a per-component basis in ``. diff --git a/documentation/docs/98-reference/.generated/client-errors.md b/documentation/docs/98-reference/.generated/client-errors.md index 8601a728a7..7fccac5808 100644 --- a/documentation/docs/98-reference/.generated/client-errors.md +++ b/documentation/docs/98-reference/.generated/client-errors.md @@ -62,6 +62,14 @@ Keyed each block has duplicate key at indexes %a% and %b% Keyed each block has duplicate key `%value%` at indexes %a% and %b% ``` +### each_key_volatile + +``` +Keyed each block has key that is not idempotent — the key for item at index %index% was `%a%` but is now `%b%`. Keys must be the same each time for a given item +``` + +The key expression in a keyed each block must return the same value when called multiple times for the same item. Using expressions like `[item.a, item.b]` creates a new array each time, which will never be equal to itself. Instead, use a primitive value or create a stable key like `item.a + '-' + item.b`. + ### effect_in_teardown ``` diff --git a/documentation/docs/98-reference/.generated/server-errors.md b/documentation/docs/98-reference/.generated/server-errors.md index c98756afec..0ee6fd0614 100644 --- a/documentation/docs/98-reference/.generated/server-errors.md +++ b/documentation/docs/98-reference/.generated/server-errors.md @@ -16,6 +16,14 @@ Encountered asynchronous work while rendering synchronously. You (or the framework you're using) called [`render(...)`](svelte-server#render) with a component containing an `await` expression. Either `await` the result of `render` or wrap the `await` (or the component containing it) in a [``](svelte-boundary) with a `pending` snippet. +### dynamic_element_invalid_tag + +``` +`` is not a valid element name — the element will not be rendered +``` + +The value passed to the `this` prop of `` must be a valid HTML element, SVG element, MathML element, or custom element name. A value containing invalid characters (such as whitespace or special characters) was provided, which could be a security risk. Ensure only valid tag names are passed. + ### html_deprecated ``` diff --git a/package.json b/package.json index b305ce9cd1..34079f43cf 100644 --- a/package.json +++ b/package.json @@ -27,12 +27,12 @@ }, "devDependencies": { "@changesets/cli": "^2.29.8", - "@sveltejs/eslint-config": "^8.3.5", + "@eslint/js": "^10.0.0", + "@sveltejs/eslint-config": "^9.0.0", "@svitejs/changesets-changelog-github-compact": "^1.1.0", "@types/node": "^20.11.5", "@types/picomatch": "^4.0.2", "@vitest/coverage-v8": "^2.1.9", - "@eslint/js": "^10.0.0", "eslint": "^10.0.0", "eslint-plugin-lube": "^0.5.1", "eslint-plugin-svelte": "^3.15.0", @@ -42,15 +42,8 @@ "prettier-plugin-svelte": "^3.4.0", "svelte": "workspace:^", "typescript": "^5.5.4", - "typescript-eslint": "^8.55.0", + "typescript-eslint": "^8.56.0", "v8-natives": "^1.2.5", "vitest": "^2.1.9" - }, - "pnpm": { - "peerDependencyRules": { - "allowedVersions": { - "eslint": "10" - } - } } } diff --git a/packages/svelte/CHANGELOG.md b/packages/svelte/CHANGELOG.md index 4e4f4f6088..c7b7ea7f58 100644 --- a/packages/svelte/CHANGELOG.md +++ b/packages/svelte/CHANGELOG.md @@ -1,5 +1,101 @@ # svelte +## 5.53.5 + +### Patch Changes + +- fix: escape `innerText` and `textContent` bindings of `contenteditable` ([`0df5abcae223058ceb95491470372065fb87951d`](https://github.com/sveltejs/svelte/commit/0df5abcae223058ceb95491470372065fb87951d)) + +- fix: sanitize `transformError` values prior to embedding in HTML comments ([`0298e979371bb583855c9810db79a70a551d22b9`](https://github.com/sveltejs/svelte/commit/0298e979371bb583855c9810db79a70a551d22b9)) + +## 5.53.4 + +### Patch Changes + +- fix: set server context after async transformError ([#17799](https://github.com/sveltejs/svelte/pull/17799)) + +- fix: hydrate if blocks correctly ([#17784](https://github.com/sveltejs/svelte/pull/17784)) + +- fix: handle default parameters scope leaks ([#17788](https://github.com/sveltejs/svelte/pull/17788)) + +- fix: prevent flushed effects from running again ([#17787](https://github.com/sveltejs/svelte/pull/17787)) + +## 5.53.3 + +### Patch Changes + +- fix: render `:catch` of `#await` block with correct key ([#17769](https://github.com/sveltejs/svelte/pull/17769)) + +- chore: pin aria-query@5.3.1 ([#17772](https://github.com/sveltejs/svelte/pull/17772)) + +- fix: make string coercion consistent to `toString` ([#17774](https://github.com/sveltejs/svelte/pull/17774)) + +## 5.53.2 + +### Patch Changes + +- fix: update expressions on server deriveds ([#17767](https://github.com/sveltejs/svelte/pull/17767)) + +- fix: further obfuscate `node:crypto` import from overzealous static analysis ([#17763](https://github.com/sveltejs/svelte/pull/17763)) + +## 5.53.1 + +### Patch Changes + +- fix: handle shadowed function names correctly ([#17753](https://github.com/sveltejs/svelte/pull/17753)) + +## 5.53.0 + +### Minor Changes + +- feat: allow comments in tags ([#17671](https://github.com/sveltejs/svelte/pull/17671)) + +- feat: allow error boundaries to work on the server ([#17672](https://github.com/sveltejs/svelte/pull/17672)) + +### Patch Changes + +- fix: use TrustedHTML to test for customizable `