merge conflict

log-rune
Dominic Gannaway 7 months ago
commit d89d54d189

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: add children to element typings

@ -38,6 +38,7 @@
"itchy-lions-wash",
"khaki-mails-draw",
"kind-deers-lay",
"kind-eagles-join",
"lazy-spiders-think",
"light-pens-watch",
"long-crews-return",
@ -76,6 +77,7 @@
"thirty-impalas-repair",
"thirty-wombats-relax",
"tiny-kings-whisper",
"twelve-onions-juggle",
"two-falcons-buy",
"wet-games-fly",
"wicked-clouds-exercise",

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: handle ts expressions when dealing with runes

@ -43,7 +43,7 @@ The maintainers meet on the final Saturday of each month. While these meetings a
### Prioritization
We do our best to review PRs and RFCs as they are sent, but it is difficult to keep up. We welcome help in reviewing PRs, RFC, and issues. If an item aligns with the current priority on our [roadmap](https://svelte.dev/roadmap), it is more likely to be reviewed quickly. PRs to the most important and active ones repositories get reviewed more quickly while PRs to smaller inactive repos may sit for a bit before we periodically come by and review the pending PRs in a batch.
We do our best to review PRs and RFCs as they are sent, but it is difficult to keep up. We welcome help in reviewing PRs, RFCs, and issues. If an item aligns with the current priority on our [roadmap](https://svelte.dev/roadmap), it is more likely to be reviewed quickly. PRs to the most important and active ones repositories get reviewed more quickly while PRs to smaller inactive repos may sit for a bit before we periodically come by and review the pending PRs in a batch.
## Bugs
@ -74,10 +74,11 @@ Small pull requests are much easier to review and more likely to get merged.
### Installation
1. Ensure you have [pnpm](https://pnpm.io/installation) installed
1. After cloning the repository, run `pnpm install`. You can do this in the root directory or in the `svelte` project
1. Move into the `svelte` directory with `cd packages/svelte`
1. To compile in watch mode, run `pnpm dev`
Ensure you have [pnpm](https://pnpm.io/installation) installed. After cloning the repository, run `pnpm install`.
### Developing
To build the UMD version of `svelte/compiler` (this is only necessary for CommonJS consumers, or in-browser use), run `pnpm build` inside `packages/svelte`. To rebuild whenever source files change, run `pnpm dev`.
### Creating a branch
@ -100,18 +101,28 @@ Test samples are kept in `/test/xxx/samples` folder.
> PREREQUISITE: Install chromium via playwright by running `pnpm playwright install chromium`
1. To run test, run `pnpm test`.
1. To run test for a specific feature, you can use the `-g` (aka `--grep`) option. For example, to only run test involving transitions, run `pnpm test -- -g transition`.
1. To run a particular test suite, use `pnpm test <suite-name>`, for example:
```bash
pnpm test validator
```
##### Running solo test
1. To filter tests _within_ a test suite, use `pnpm test <suite-name> -- -t <test-name>`, for example:
1. To run only one test, rename the test sample folder to end with `.solo`. For example, to run the `test/js/samples/action` only, rename it to `test/js/samples/action.solo`.
1. To run only one test suite, rename the test suite folder to end with `.solo`. For example, to run the `test/js` test suite only, rename it to `test/js.solo`.
1. Remember to rename the test folder back. The CI will fail if there's a solo test.
```bash
pnpm test validator -- -t a11y-alt-text
```
(You can also do `FILTER=<test-name> pnpm test <suite-name>` which removes other tests rather than simply skipping them — this will result in faster and more compact test results, but it's non-idiomatic. Choose your fighter.)
##### Updating `.expected` files
1. Tests suites like `css`, `js`, `server-side-rendering` asserts that the generated output has to match the content in the `.expected` file. For example, in the `js` test suites, the generated js code is compared against the content in `expected.js`.
1. To update the content of the `.expected` file, run the test with `--update` flag. (`pnpm test --update`)
1. Tests suites like `snapshot` and `parser` assert that the generated output matches the existing snapshot.
1. To update these snapshots, run `UPDATE_SNAPSHOTS=true pnpm test`.
### Typechecking
To typecheck the codebase, run `pnpm check` inside `packages/svelte`. To typecheck in watch mode, run `pnpm check:watch`.
### Style guide

@ -22,47 +22,7 @@ You may view [our roadmap](https://svelte.dev/roadmap) if you'd like to see what
## Contributing
Please see the [Contributing Guide](CONTRIBUTING.md) and [svelte package](packages/svelte) for contributing to Svelte.
### Development
Pull requests are encouraged and always welcome. [Pick an issue](https://github.com/sveltejs/svelte/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc) and help us out!
To install and work on Svelte locally:
```bash
git clone https://github.com/sveltejs/svelte.git
cd svelte
pnpm install
```
> Do not use Yarn to install the dependencies, as the specific package versions in `pnpm-lock.json` are used to build and test Svelte.
To build the compiler and all the other modules included in the package:
```bash
pnpm build
```
To watch for changes and continually rebuild the package (this is useful if you're using [`pnpm link`](https://pnpm.io/cli/link) to test out changes in a project locally):
```bash
pnpm dev
```
The compiler is written in JavaScript and uses [JSDoc](https://jsdoc.app/index.html) comments for type-checking.
### Running Tests
```bash
pnpm test
```
To filter tests, use `-g` (aka `--grep`). For example, to only run tests involving transitions:
```bash
pnpm test -- -g transition
```
Please see the [Contributing Guide](CONTRIBUTING.md) and the [`svelte`](packages/svelte) package for information on contributing to Svelte.
### svelte.dev

@ -1,5 +1,13 @@
# svelte
## 5.0.0-next.15
### Patch Changes
- fix: add children to element typings ([#9679](https://github.com/sveltejs/svelte/pull/9679))
- fix: handle ts expressions when dealing with runes ([#9681](https://github.com/sveltejs/svelte/pull/9681))
## 5.0.0-next.14
### Patch Changes

@ -64,6 +64,10 @@ export type MessageEventHandler<T extends EventTarget> = EventHandler<MessageEve
// ----------------------------------------------------------------------
export interface DOMAttributes<T extends EventTarget> {
// Implicit children prop every element has
// Add this here so that libraries doing `$props<HTMLButtonAttributes>()` don't need a separate interface
children?: import('svelte').Snippet<any>;
// Clipboard Events
'on:copy'?: ClipboardEventHandler<T> | undefined | null;
oncopy?: ClipboardEventHandler<T> | undefined | null;

@ -2,7 +2,7 @@
"name": "svelte",
"description": "Cybernetically enhanced web apps",
"license": "MIT",
"version": "5.0.0-next.14",
"version": "5.0.0-next.15",
"type": "module",
"types": "./types/index.d.ts",
"engines": {
@ -91,7 +91,7 @@
],
"scripts": {
"build": "rollup -c && node scripts/build.js && node scripts/check-treeshakeability.js",
"watch": "rollup -cw",
"dev": "rollup -cw",
"check": "tsc && cd ./tests/types && tsc",
"check:watch": "tsc --watch",
"generate:version": "node ./scripts/generate-version.js",

@ -7,7 +7,8 @@ import {
extract_paths,
is_event_attribute,
is_text_attribute,
object
object,
unwrap_ts_expression
} from '../../utils/ast.js';
import * as b from '../../utils/builders.js';
import { ReservedKeywords, Runes, SVGElements } from '../constants.js';
@ -668,10 +669,11 @@ const runes_scope_tweaker = {
}
},
VariableDeclarator(node, { state }) {
if (node.init?.type !== 'CallExpression') return;
if (get_rune(node.init, state.scope) === null) return;
const init = unwrap_ts_expression(node.init);
if (!init || init.type !== 'CallExpression') return;
if (get_rune(init, state.scope) === null) return;
const callee = node.init.callee;
const callee = init.callee;
if (callee.type !== 'Identifier') return;
const name = callee.name;

@ -1,5 +1,10 @@
import { error } from '../../errors.js';
import { extract_identifiers, is_text_attribute } from '../../utils/ast.js';
import {
extract_identifiers,
get_parent,
is_text_attribute,
unwrap_ts_expression
} from '../../utils/ast.js';
import { warn } from '../../warnings.js';
import fuzzymatch from '../1-parse/utils/fuzzymatch.js';
import { binding_properties } from '../bindings.js';
@ -491,7 +496,7 @@ function validate_call_expression(node, scope, path) {
const rune = get_rune(node, scope);
if (rune === null) return;
const parent = /** @type {import('#compiler').SvelteNode} */ (path.at(-1));
const parent = /** @type {import('#compiler').SvelteNode} */ (get_parent(path, -1));
if (rune === '$props') {
if (parent.type === 'VariableDeclarator') return;
@ -703,7 +708,7 @@ export const validation_runes = merge(validation, a11y_validators, {
next({ ...state });
},
VariableDeclarator(node, { state }) {
const init = node.init;
const init = unwrap_ts_expression(node.init);
const rune = get_rune(init, state.scope);
if (rune === null) return;

@ -3,6 +3,7 @@ import { is_hoistable_function } from '../../utils.js';
import * as b from '../../../../utils/builders.js';
import * as assert from '../../../../utils/assert.js';
import { create_state_declarators, get_props_method } from '../utils.js';
import { unwrap_ts_expression } from '../../../../utils/ast.js';
/** @type {import('../types.js').ComponentVisitors} */
export const javascript_visitors_runes = {
@ -133,7 +134,7 @@ export const javascript_visitors_runes = {
const declarations = [];
for (const declarator of node.declarations) {
const init = declarator.init;
const init = unwrap_ts_expression(declarator.init);
const rune = get_rune(init, state.scope);
if (
!rune ||
@ -213,7 +214,8 @@ export const javascript_visitors_runes = {
// TODO
continue;
}
const args = /** @type {import('estree').CallExpression} */ (declarator.init).arguments;
const args = /** @type {import('estree').CallExpression} */ (init).arguments;
const value =
args.length === 0
? b.id('undefined')

@ -1,6 +1,11 @@
import { walk } from 'zimmerframe';
import { set_scope, get_rune } from '../../scope.js';
import { extract_identifiers, extract_paths, is_event_attribute } from '../../../utils/ast.js';
import {
extract_identifiers,
extract_paths,
is_event_attribute,
unwrap_ts_expression
} from '../../../utils/ast.js';
import * as b from '../../../utils/builders.js';
import is_reference from 'is-reference';
import {
@ -568,7 +573,8 @@ const javascript_visitors_runes = {
const declarations = [];
for (const declarator of node.declarations) {
const rune = get_rune(declarator.init, state.scope);
const init = unwrap_ts_expression(declarator.init);
const rune = get_rune(init, state.scope);
if (!rune || rune === '$effect.active' || rune.startsWith('$log')) {
declarations.push(/** @type {import('estree').VariableDeclarator} */ (visit(declarator)));
continue;
@ -579,7 +585,7 @@ const javascript_visitors_runes = {
continue;
}
const args = /** @type {import('estree').CallExpression} */ (declarator.init).arguments;
const args = /** @type {import('estree').CallExpression} */ (init).arguments;
const value =
args.length === 0
? b.id('undefined')

@ -265,3 +265,42 @@ function _extract_paths(assignments = [], param, expression, update_expression)
return assignments;
}
/**
* The Acorn TS plugin defines `foo!` as a `TSNonNullExpression` node, and
* `foo as Bar` as a `TSAsExpression` node. This function unwraps those.
*
* @template {import('#compiler').SvelteNode | undefined | null} T
* @param {T} node
* @returns {T}
*/
export function unwrap_ts_expression(node) {
if (!node) {
return node;
}
// @ts-expect-error these types don't exist on the base estree types
if (node.type === 'TSNonNullExpression' || node.type === 'TSAsExpression') {
// @ts-expect-error
return node.expression;
}
return node;
}
/**
* Like `path.at(x)`, but skips over `TSNonNullExpression` and `TSAsExpression` nodes and eases assertions a bit
* by removing the `| undefined` from the resulting type.
*
* @template {import('#compiler').SvelteNode} T
* @param {T[]} path
* @param {number} at
*/
export function get_parent(path, at) {
let node = path.at(at);
// @ts-expect-error
if (node.type === 'TSNonNullExpression' || node.type === 'TSAsExpression') {
return /** @type {T} */ (path.at(at < 0 ? at - 1 : at + 1));
}
return /** @type {T} */ (node);
}

@ -2918,6 +2918,7 @@ export function unwrap(value) {
* @param {{
* target: Node;
* props?: Props;
* events?: Events;
* context?: Map<any, any>;
* intro?: boolean;
* immutable?: boolean;

@ -6,5 +6,5 @@
* https://svelte.dev/docs/svelte-compiler#svelte-version
* @type {string}
*/
export const VERSION = '5.0.0-next.14';
export const VERSION = '5.0.0-next.15';
export const PUBLIC_VERSION = '5';

@ -0,0 +1,5 @@
import { test } from '../../test';
export default test({
html: '1 2'
});

@ -0,0 +1,6 @@
<script lang="ts">
let count = $state(1) as number;
let double = $derived(count as number * 2) as number;
</script>
{count as number} {double as number}

@ -0,0 +1,5 @@
import { test } from '../../test';
export default test({
html: '1 2'
});

@ -0,0 +1,6 @@
<script lang="ts">
let count = $state(1)!;
let double = $derived(count! * 2)!;
</script>
{count!} {double!}

@ -357,11 +357,11 @@ importers:
specifier: ^9.0.0
version: 9.1.6
prettier:
specifier: ^3.0.3
version: 3.0.3
specifier: ^3.1.0
version: 3.1.0
prettier-plugin-svelte:
specifier: ^3.0.3
version: 3.1.0(prettier@3.0.3)(svelte@4.2.3)
specifier: ^3.1.2
version: 3.1.2(prettier@3.1.0)(svelte@4.2.3)
sass:
specifier: ^1.67.0
version: 1.69.5
@ -6073,24 +6073,24 @@ packages:
engines: {node: '>= 0.8.0'}
dev: true
/prettier-plugin-svelte@3.1.0(prettier@3.0.3)(svelte@4.2.3):
/prettier-plugin-svelte@3.1.0(prettier@3.0.3)(svelte@packages+svelte):
resolution: {integrity: sha512-96+AZxs2ESqIFA9j+o+DHqY+BsUglezfl553LQd6VOtTyJq5GPuBEb3ElxF2cerFzKlYKttlH/VcVmRNj5oc3A==}
peerDependencies:
prettier: ^3.0.0
svelte: ^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0
dependencies:
prettier: 3.0.3
svelte: 4.2.3
svelte: link:packages/svelte
dev: true
/prettier-plugin-svelte@3.1.0(prettier@3.0.3)(svelte@packages+svelte):
resolution: {integrity: sha512-96+AZxs2ESqIFA9j+o+DHqY+BsUglezfl553LQd6VOtTyJq5GPuBEb3ElxF2cerFzKlYKttlH/VcVmRNj5oc3A==}
/prettier-plugin-svelte@3.1.2(prettier@3.1.0)(svelte@4.2.3):
resolution: {integrity: sha512-7xfMZtwgAWHMT0iZc8jN4o65zgbAQ3+O32V6W7pXrqNvKnHnkoyQCGCbKeUyXKZLbYE0YhFRnamfxfkEGxm8qA==}
peerDependencies:
prettier: ^3.0.0
svelte: ^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0
dependencies:
prettier: 3.0.3
svelte: link:packages/svelte
prettier: 3.1.0
svelte: 4.2.3
dev: true
/prettier@2.8.8:
@ -6105,6 +6105,12 @@ packages:
hasBin: true
dev: true
/prettier@3.1.0:
resolution: {integrity: sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw==}
engines: {node: '>=14'}
hasBin: true
dev: true
/pretty-format@29.7.0:
resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}

@ -9,17 +9,23 @@ While Svelte 5 is a complete rewrite, we have done our best to ensure that most
In Svelte 3 and 4, components are classes. In Svelte 5 they are functions and should be instantiated differently. If you need to manually instantiate components, you should use `mount` or `createRoot` (imported from `svelte`) instead. If you see this error using SvelteKit, try updating to the latest version of SvelteKit first, which adds support for Svelte 5. If you're using Svelte without SvelteKit, you'll likely have a `main.js` file (or similar) which you need to adjust:
```diff
+ import { mount } from 'svelte';
+ import { createRoot } from 'svelte';
import App from './App.svelte'
- const app = new App({ target: document.getElementById("app") });
+ const app = mount(App, { target: document.getElementById("app") });
+ const app = createRoot(App, { target: document.getElementById("app") });
export default app;
```
`createRoot` returns an object with a `$set` and `$destroy` method on it. It does not come with an `$on` method you may know from the class component API. Instead, pass them via the `events` property on the options argument. If you don't need to interact with the component instance after creating it, you can use `mount` instead, which saves some bytes.
> Note that using `events` is discouraged — instead, [use callbacks](https://svelte-5-preview.vercel.app/docs/event-handlers)
As a stop-gap-solution, you can also use `createClassComponent` or `asClassComponent` (imported from `svelte/legacy`) instead to keep the same API after instantiating. If this component is not under your control, you can use the `legacy.componentApi` compiler option for auto-applied backwards compatibility (note that this adds a bit of overhead to each component).
### Server API changes
Similarly, components no longer have a `render` method when compiled for server side rendering. Instead, pass the function to `render` from `svelte/server`:
```diff
@ -32,6 +38,10 @@ import App from './App.svelte';
`render` also no longer returns CSS; it should be served separately from a CSS file.
### bind:this changes
Because components are no longer classes, using `bind:this` no longer returns a class instance with `$set`, `$on` and `$destroy` methods on it. It only returns the instance exports (`export function/const`) and, if you're using the `accessors` option, a getter/setter-pair for each property.
## Whitespace handling changed
Previously, Svelte employed a very complicated algorithm to determine if whitespace should be kept or not. Svelte 5 simplifies this which makes it easier to reason about as a developer. The rules are:

@ -13,8 +13,8 @@
"start": "node build",
"check": "node scripts/update.js && pnpm generate && svelte-kit sync && svelte-check",
"check:watch": "svelte-kit sync && svelte-check --watch",
"format": "prettier --check . --ignore-path .gitignore --plugin-search-dir=. --write",
"check:format": "prettier --check . --ignore-path .gitignore --plugin-search-dir=."
"format": "prettier --check . --write",
"check:format": "prettier --check ."
},
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.15",
@ -41,8 +41,8 @@
"lightningcss": "^1.21.8",
"magic-string": "^0.30.3",
"marked": "^9.0.0",
"prettier": "^3.0.3",
"prettier-plugin-svelte": "^3.0.3",
"prettier": "^3.1.0",
"prettier-plugin-svelte": "^3.1.2",
"sass": "^1.67.0",
"satori": "^0.10.4",
"satori-html": "^0.3.2",

@ -32,11 +32,7 @@
</svelte:head>
<div style:display={$page.url.pathname !== '/docs' ? 'contents' : 'none'}>
<Shell
nav_visible={$page.url.pathname !== '/repl/embed'}
bind:snapshot={shell_snapshot}
banner_bottom_height="42px"
>
<Shell nav_visible={$page.url.pathname !== '/repl/embed'} bind:snapshot={shell_snapshot}>
<Nav slot="top-nav" title={data.nav_title} links={data.nav_links}>
<svelte:fragment slot="home-large">
<strong>svelte</strong>.dev
@ -72,12 +68,6 @@
</Nav>
<slot />
<div slot="banner-bottom" class="banner-bottom">
<a href="https://www.sveltesummit.com/2023/fall" class="banner-bottom"
>Join us at Svelte Summit on Nov 11</a
>
</div>
</Shell>
</div>
@ -94,12 +84,4 @@
height: 100%;
width: 100%;
}
.banner-bottom {
text-align: center;
background: var(--sk-theme-1-variant);
color: white;
text-decoration: underline;
padding: 8px;
}
</style>

Loading…
Cancel
Save