diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 83e0b253b3..49d60aecaa 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,3 +1,6 @@ +## Svelte compiler rewrite + +Please note that [the Svelte codebase is currently being rewritten](https://svelte.dev/blog/runes). Thus, it's best to hold off on new features or refactorings for the time being. ### Before submitting the PR, please make sure you do the following diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8c66b30ebf..beb9e912c3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -147,7 +147,7 @@ When adding a new breaking change, follow this template in your pull request: ## License -By contributing to Svelte, you agree that your contributions will be licensed under its [MIT license](https://github.com/sveltejs/svelte/blob/master/LICENSE). +By contributing to Svelte, you agree that your contributions will be licensed under its [MIT license](https://github.com/sveltejs/svelte/blob/master/LICENSE.md). ## Questions diff --git a/documentation/blog/2023-08-01-whats-new-in-svelte-august-2023.md b/documentation/blog/2023-08-01-whats-new-in-svelte-august-2023.md index d14e1a7a08..e7b27d65f7 100644 --- a/documentation/blog/2023-08-01-whats-new-in-svelte-august-2023.md +++ b/documentation/blog/2023-08-01-whats-new-in-svelte-august-2023.md @@ -46,7 +46,7 @@ For all the patches and performance updates from this month, check out the [Svel **Learning Resources** _Featuring Svelte Contributors and Ambassadors_ - [Exploring Svelte 4 w/ Kevin AK: Performance, Compatibility, & Web Component Support | Modern Web Pod](https://www.youtube.com/watch?v=YOL0HGGVib4) by This Dot Media -- [Svelte Sirens Stream Design Systems: Lessons Learned](https://www.youtube.com/live/YHZaiIGSqsE?feature=share) featuring Eric Liu creator of Carbon Components Svelte and Svelde the docgen library +- [Svelte Sirens Stream Design Systems: Lessons Learned](https://www.youtube.com/live/YHZaiIGSqsE?feature=share) featuring Eric Liu, creator of Carbon Components Svelte and the `sveld` docgen library - This Week in Svelte: - [2023 June 30](https://www.youtube.com/watch?v=sDz4_BLoYQ4) - Svelte 4.0.1, SK 1.21, lists, screen readers, loading - [2023 July 7](https://www.youtube.com/watch?v=0tq1ph4DDFA) - Svelte 4.0.5, Kit 1.22.1, Svelte 5, local storage and markdown diff --git a/documentation/blog/2023-08-31-view-transitions.md b/documentation/blog/2023-08-31-view-transitions.md new file mode 100644 index 0000000000..11d0dc6e5e --- /dev/null +++ b/documentation/blog/2023-08-31-view-transitions.md @@ -0,0 +1,264 @@ +--- +title: Unlocking view transitions in SvelteKit 1.24 +description: Streamlined page transitions with onNavigate +author: Geoff Rich +authorURL: https://geoffrich.net +--- + +The [view transitions API](https://developer.chrome.com/docs/web-platform/view-transitions/) has been sweeping the web development world lately, and for good reason. It streamlines the process of animating between two page states, which is especially useful for page transitions. + +However, until now, you couldn’t easily use this API in a SvelteKit app, since it was difficult to slot into the right place in the navigation lifecycle. SvelteKit 1.24 brought a new [`onNavigate`](https://kit.svelte.dev/docs/modules#$app-navigation-onnavigate) lifecycle hook to make view transitions integration much easier – let’s dive in. + +## How view transitions work + +You can trigger a view transition by calling `document.startViewTransition` and passing a callback that updates the DOM somehow. For our purposes today, SvelteKit will update the DOM as the user navigates. Once the callback finishes, the browser will transition to the new page state — by default, it does a crossfade between the old and the new states. + +```js +// @errors: 2339 +const domUpdate = async () => {}; +// ---cut--- +document.startViewTransition(async () => { + await domUpdate(); // mock function for demonstration purposes +}); +``` + +Behind the scenes, the browser does something really clever. When the transition starts, it captures the current state of the page and takes a screenshot. It then holds that screenshot in place while the DOM is updating. Once the DOM has finished updating, it captures the new state, and animates between the two states. + +While it’s only implemented in Chrome (and other Chromium-based browsers) for now, [WebKit is also in favor](https://github.com/WebKit/standards-positions/issues/48#issuecomment-1679760489) of it. Even if you’re on an unsupported browser, it’s a perfect candidate for progressive enhancement since we can always fall back to a non-animated navigation. + +It’s important to note that view transitions is a browser API, not a SvelteKit one. `onNavigate` is the only SvelteKit-specific API we’ll use today. Everything else can be used wherever you write for the web! For more on the view transitions API, I highly recommend the [Chrome explainer](https://developer.chrome.com/docs/web-platform/view-transitions/) by Jake Archibald. + +## How `onNavigate` works + +Before learning how to write view transitions, let's highlight the function that makes it all possible: [`onNavigate`](https://kit.svelte.dev/docs/modules#$app-navigation-onnavigate). + +Until recently, SvelteKit had two navigation lifecycle functions: [`beforeNavigate`](https://kit.svelte.dev/docs/modules#$app-navigation-beforenavigate), which fires before a navigation starts, and [`afterNavigate`](https://kit.svelte.dev/docs/modules#$app-navigation-afternavigate), which fires after the page has been updated following a navigation. SvelteKit 1.24 introduces a third: `onNavigate`, which will fire on every navigation, immediately before the new page is rendered. Importantly, it will run _after_ any data loading for the page has completed – since starting a view transition prevents any interaction with the page, we want to start it as late as possible. + +You can also return a promise from `onNavigate`, which will suspend the navigation until it resolves. This will let us wait to complete the navigation until the view transition has started. + +```js +// @errors: 2304 7006 +function delayNavigation() { + return new Promise((res) => setTimeout(res, 100)); +} + +onNavigate(async (navigation) => { + // do some work immediately before the navigation completes + + // optionally return a promise to delay navigation until it resolves + return delayNavigation(); +}); +``` + +With that out of the way, let's see how you can use view transitions in your SvelteKit app. + +## Getting started with view transitions + +The best way to see view transitions in action is to try it yourself. You can spin up the SvelteKit demo app by running `npm create svelte@latest` in your local terminal, or in your browser on [StackBlitz](https://sveltekit.new). Make sure to use a browser that supports the view transitions API. Once you have the app running, add the following to the script block in `src/routes/+layout.svelte`. + +```js +// @errors: 2305 7006 2339 2810 +import { onNavigate } from '$app/navigation'; + +onNavigate((navigation) => { + if (!document.startViewTransition) return; + + return new Promise((resolve) => { + document.startViewTransition(async () => { + resolve(); + await navigation.complete; + }); + }); +}); +``` + +With that, every navigation that occurs will trigger a view transition. You can already see this in action – by default, the browser will crossfade between the old and new pages. + + + +
+How the code works + +This code may look a bit intimidating – if you're curious, I can break it down line-by-line, but for now it’s enough to know that adding it will allow you to interact with the view transitions API during navigation. + +As mentioned above, the `onNavigate` callback will run immediately before the new page is rendered after a navigation. Inside the callback, we check if `document.startViewTransition` exists. If it doesn’t (i.e. the browser doesn’t support it), we exit early. + +We then return a promise to delay completing the navigation until the view transition has started. We use a [promise constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/Promise) so that we can control when the promise resolves. + +```js +// @errors: 1108 +return new Promise((resolve) => { + document.startViewTransition(async () => { + resolve(); + await navigation.complete; + }); +}); +``` + +Inside the promise constructor, we start the view transition. Inside the view transition callback we resolve the promise we just returned, which indicates to SvelteKit that it should finish the navigation. It’s important that the navigation waits to finish until _after_ we start the view transition – the browser needs to snapshot the old state so it can transition to the new state. + +Finally, inside the view transition callback we wait for SvelteKit to finish the navigation by awaiting `navigation.complete`. Once `navigation.complete` resolves, the new page has been loaded into the DOM and the browser can animate between the two states. + +It’s a bit of a mouthful, but by not abstracting it we allow you to interact with the view transition directly and make any customizations you require. + +
+ +## Customizing the transition with CSS + +We can also customize this page transition using CSS animation. In the style block of your `+layout.svelte`, add the following CSS rules. + +```css +@keyframes fade-in { + from { + opacity: 0; + } +} + +@keyframes fade-out { + to { + opacity: 0; + } +} + +@keyframes slide-from-right { + from { + transform: translateX(30px); + } +} + +@keyframes slide-to-left { + to { + transform: translateX(-30px); + } +} + +:root::view-transition-old(root) { + animation: 90ms cubic-bezier(0.4, 0, 1, 1) both fade-out, 300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left; +} + +:root::view-transition-new(root) { + animation: 210ms cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in, 300ms cubic-bezier(0.4, 0, 0.2, 1) both + slide-from-right; +} +``` + +Now when you navigate between pages, the old page will fade out and slide to the left, and the new page will fade in and slide from the right. These particular animation styles come from Jake Archibald’s excellent [Chrome Developers article on view transitions](https://developer.chrome.com/docs/web-platform/view-transitions/), which is well worth a read if you want to understand everything you can do with this API. + +Note that we have to add `:root` before the `::view-transition` pseudoelements – these elements are only on the root of the document, so we don’t want Svelte to [scope them](/docs/svelte-components#style) to the component. + +You might have noticed that the entire page slides in and out, even though the header is the same on both the old and new page. To make for a smoother transition, we can give the header a unique `view-transition-name` so that it is animated separately from the rest of the page. In `src/routes/Header.svelte`, find the `header` CSS selector in the style block and add a view transition name. + +```css +header { + display: flex; + justify-content: space-between; + view-transition-name: header; +} +``` + +Now, the header will not transition in and out on navigation, but the rest of the page will. + + + +
+Fixing the types + +Since `startViewTransition` is not supported by all browsers, your IDE may not know that it exists. To make the errors go away and get the correct typings, add the following to your `app.d.ts`: + +```ts +declare global { + // preserve any customizations you have here + namespace App { + // interface Error {} + // interface Locals {} + // interface PageData {} + // interface Platform {} + } + + // add these lines + interface ViewTransition { + updateCallbackDone: Promise; + ready: Promise; + finished: Promise; + skipTransition: () => void; + } + + interface Document { + startViewTransition(updateCallback: () => Promise): ViewTransition; + } +} + +export {}; +``` + +
+ +## Transitioning individual elements + +We just saw how giving an element a `view-transition-name` separates it out from the rest of the page's animation. Setting a `view-transition-name` also instructs the browser to smoothly animate it to its new position after the transition completes. The `view-transition-name` acts as a unique identifier so the browser can identify matching elements from the old and new states. + +Let’s see what that looks like – our demo app’s navigation has a small triangle indicating the active page. Right now, it abruptly appears in the new position after we navigate. Let’s give it a `view-transition-name` so the browser animates it to its new position instead. + +Inside `src/routes/Header.svelte`, find the CSS rule creating the active page indicator and give it a `view-transition-name`: + +```css +li[aria-current='page']::before { + /* other existing rules */ + view-transition-name: active-page; +} +``` + +By adding that single line, the indicator will now smoothly slide to its new position instead of jumping. + + + +(It might be easy to miss the difference – look at the small moving triangle indicator at the top of the screen!) + +## Reduced motion + +It’s important to respect our users’ [motion preferences](https://web.dev/prefers-reduced-motion/) while implementing animation on the web. Just because you can implement an extreme page transition doesn’t mean you should. To disable all page transitions for users who prefer reduced motion, you can add the following to the global `styles.css`: + +```css +@media (prefers-reduced-motion) { + ::view-transition-group(*), + ::view-transition-old(*), + ::view-transition-new(*) { + animation: none !important; + } +} +``` + +While this may be the safest option, reduced motion does not necessarily mean no animation. Instead, you could consider your view transitions on a case-by-case basis. For instance, maybe we disable the sliding animation, but leave the default crossfade (which doesn’t involve motion). You can do so by wrapping the `::view-transition` rules you want to disable in a `prefers-reduced-motion: no-preference` media-query: + +```css +@media (prefers-reduced-motion: no-preference) { + :root::view-transition-old(root) { + animation: 90ms cubic-bezier(0.4, 0, 1, 1) both fade-out, 300ms cubic-bezier(0.4, 0, 0.2, 1) both + slide-to-left; + } + + :root::view-transition-new(root) { + animation: 210ms cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in, 300ms cubic-bezier( + 0.4, + 0, + 0.2, + 1 + ) both slide-from-right; + } +} +``` + +## What’s next? + +As you can see, SvelteKit doesn’t abstract a whole lot about _how_ view transitions work – you’re interacting directly with the browser’s built-in `document.startViewTransition` and `::view-transition` APIs, rather than framework abstractions like those found in Nuxt and Astro. We’re eager to see how people end up using view transitions in SvelteKit apps, and whether it makes sense to add higher level abstractions of our own in future. + +## Resources + +You can find the demo code from this post [on GitHub](https://github.com/geoffrich/sveltekit-onnavigate-demo) and the live version [deployed to Vercel](https://sveltekit-onnavigate-demo.vercel.app/). Here are some other view transitions resources you may find helpful: + +- [MDN view transitions docs](https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API) +- [Chrome view transitions API explainer](https://developer.chrome.com/docs/web-platform/view-transitions/) +- [Rich Harris demoing view transitions with onNavigate](https://www.youtube.com/shorts/weOCWOD2UIo) +- [My Svelte Summit video showing how to use view transitions for FLIP animations](https://youtu.be/K95TQ-Yh7Cw) +- [Fruit list demo](https://sveltekit-shared-element-transitions-codelab.vercel.app/fruits) ([source](https://github.com/geoffrich/sveltekit-view-transitions)) +- [Svelte Summit video list demo](https://http-203-svelte.vercel.app/) (based on a [Jake Archibald demo](https://http203-playlist.netlify.app/)) ([source](https://github.com/geoffrich/http-203-svelte)) diff --git a/documentation/blog/2023-09-01-whats-new-in-svelte-september-2023.md b/documentation/blog/2023-09-01-whats-new-in-svelte-september-2023.md new file mode 100644 index 0000000000..84d0e410d5 --- /dev/null +++ b/documentation/blog/2023-09-01-whats-new-in-svelte-september-2023.md @@ -0,0 +1,97 @@ +--- +title: "What's new in Svelte: September 2023" +description: "New parameters in SvelteKit's redirect and an onNavigate lifecycle function come to life" +author: Dani Sandoval +authorURL: https://dreamindani.com +--- + +Happy September y'all! With all the [sneak peeks at what's coming soon in Svelte 5](https://twitter.com/Rich_Harris/status/1688581184018583558), we thought it'd be best to look back at the last month to see what's shipped and what the community is building with Svelte. + +Before we jump in, a warm welcome to the new Svelte Ambassadors: [@cainux](https://github.com/cainux) and [@grischaerbe](https://github.com/grischaerbe)! Welcome to the crew ⛴️ + +## What's new in Svelte & Language Tools +- `svelteHTML` has moved from language-tools into Svelte core so that `svelte/element` types will now load correctly (**4.2.0** in Svelte, **107.10.0** in Language Tools) + +## What's new in SvelteKit +- `URL` is now accepted in the `redirect` function (**1.23.0**, [Docs](https://kit.svelte.dev/docs/modules#sveltejs-kit-redirect), [#10570](https://github.com/sveltejs/kit/pull/10570)) +- Mistyped route filenames will now throw a warning (**1.23.0**, [#10558](https://github.com/sveltejs/kit/pull/10558)) +- The new `onNavigate` lifecycle function enables view transitions - Check out the [blog post](https://svelte.dev/blog/view-transitions) for more info (**1.24.0**, [Docs](https://kit.svelte.dev/docs/modules#app-navigation-onnavigate), [#9605](https://github.com/sveltejs/kit/pull/9605)) + +But that's just the new features! For all the patches and performance updates from this month, check out the [SvelteKit CHANGELOG](https://github.com/sveltejs/kit/blob/master/packages/kit/CHANGELOG.md). You can also find adapter-specific CHANGELOGs in each of [the `adapter` directories](https://github.com/sveltejs/kit/tree/master/packages). + +--- + +## Community Showcase + +**Apps & Sites built with Svelte** +- [Planet Of The Bugs](https://planetofthebugs.xyz/) allows developers to practice and hone their skill-sets by exposing them to an endless supply of unique, curated issues and bugs from popular open-source projects on Github +- [Minesweeper](https://github.com/ProductionPanic/minesweeper/tree/main) is an Android game built with SvelteKit, Capacitor, TailwindCSS and DaisyUI (check it out on the [Google Play Store](https://play.google.com/store/apps/details?id=com.production.panic.minesweeper&pli=1)) +- [Pendor](https://www.pendor.ai/) is an AI component generator for Svelte +- [Avatars Pro](https://senja.io/testimonial-widgets/avatars-pro) is a social proof widget made for the web +- [Pomodoro Focus](https://github.com/con-dog/pomodoro-focus) is a pomodoro timer browser extension +- [memegen](https://github.com/bhupeshpr25/memegen) is a Firefox web extension that allows users to generate memes using various templates +- [Resgen](https://resgen.app/) is a Chrome extension that tailors resumes based on job descriptions and your experiences +- [Icono Search](https://www.icono-search.com) is an AI-powered video search engine +- [digital-paper](https://github.com/danferns/digital-paper) is a writing app with no backspace or undo +- [Ubuntu 22.04 in Svelte](https://github.com/manhhungpc/ubuntu2204-svelte) aims to replicate the Ubuntu 22.04 desktop experience on the web +- [My Queue](https://www.myqueue.so/) creates a playlist of written articles by turning them into audio stories + + + +**Learning Resources** +_Featuring Svelte Contributors and Ambassadors_ +- [Svelte Society - London August 2023](https://www.youtube.com/watch?v=90Psdk5rAnU) +- [Building a Blog using SvelteKit and Nostr as a CMS (Part 1](https://kevinak.se/blog/building-a-blog-using-sveltekit-and-nostr-as-a-cms-part-1-1690807337563)) by Kev +- [Mastering SvelteKit with Geoff Rich | JS Drops](https://www.youtube.com/watch?v=MaF8kRbHbi0) by This Dot Media +- [Using GitHub Contributions To Flex On The Normies](https://youtu.be/f9fd1L1FEts?si=3hbihW-X5-GKSJxN), [Learn Svelte By Making A Matching Game](https://www.youtube.com/watch?v=w2q9caYXgkg) and [Who Needs API Permission When You Can Use Web Scraping](https://www.youtube.com/watch?v=T-lBPpeokfY) by Joy of Code +- [The missing guide to understanding adapter-static in SvelteKit](https://khromov.se/the-missing-guide-to-understanding-adapter-static-in-sveltekit/) by Stanislav Khromov +- This Week in Svelte: + - [2023 July 28](https://www.youtube.com/watch?v=mvTEQ_C0qRQ) - Screen reader market share, Svelte to plain JS, Web Components + - [2023 Aug 4](https://www.youtube.com/watch?v=Ye8cCJyPZjg) - Svelte 4.1.2, SvelteKit 1.22.4, ES Modules, Types in markup + - [2023 August 11](https://www.youtube.com/watch?v=A8XUaiCVkCI) - Svelte 4.2.0, SvelteKit 1.22.5, How to create Toggle Switches + - [2023 August 18](https://www.youtube.com/watch?v=nJ5Wf3uL7dM) - SvelteKit 1.22.6, accessible form error summaries + - [2023 August 25](https://www.youtube.com/watch?v=JoPzvlBKXXE) - SvelteKit 1.23.0, Bun and SvelteKit, Enhanced search +- Svienna (Svelte Society Vienna) Sessions + - [Ermin Celikovic - You might not need a slider library](https://www.youtube.com/watch?v=dSUmtijkFOc) + - [Lukas Stracke - How to use sentry.io in your SvelteKit App](https://www.youtube.com/watch?v=u41-MtPGH04) + - [Jean-Yves Couet - SvelteKit & Remult... fullstack apps in minutes!](https://www.youtube.com/watch?v=N8d290fTzq8) +- Sirens Sessions + - [Prismic Slice Machines & SvelteKit](https://www.youtube.com/watch?v=19Meb-yMsAg) with Sam Littlefair + - [Medusa and SvelteKit E-Commerce Stack](https://www.youtube.com/watch?v=rVVHxows9dY) with Lacey Pevey + - [Design Systems: Lessons Learned](https://www.youtube.com/watch?v=YHZaiIGSqsE) with Eric Liu + + +_To Watch_ +- [Image optimization in SvelteKit with vite-imagetools](https://www.youtube.com/watch?v=285vSLe9LQ8) by hartenfellerdev +- [Building a Todo App with Rust and SvelteKit: Complete Tutorial](https://www.youtube.com/watch?v=w7is2bCTUg0) and [Stripe Payment In SvelteKit With Dynamic Pricing](https://www.youtube.com/watch?v=o8gvCLgz1vs) by SvelteRust +- [Leaflet maps in SvelteKit like it's 2023 (HowTo)](https://www.youtube.com/watch?v=JFctWXEzFZw) +ShipBit + + +_To Read_ +- [Internationalization in SvelteKit (Series)](https://blog.aakashgoplani.in/series/i18n-in-sveltekit) by Aakash Goplani +- [The easiest Chatbot you will ever build](https://simon-prammer.vercel.app/blog/post/sveltekit-langchain) and [Intro to LangSmith🦜️🛠️](https://simon-prammer.vercel.app/blog/post/langsmith) by Simon Prammer +- [SvelteKit: How to make code-based router, instead of file-based router [August 2023]](https://dev.to/maxcore/sveltekit-how-to-make-code-based-router-instead-of-file-based-router-august-2023-5f9) by Max Core +- [SvelteKit Hydration Gotcha](https://www.captaincodeman.com/sveltekit-hydration-gotcha) by Captain Codeman +- [Automatically generate sitemap.xml in SvelteKit](https://alex-schnabl.medium.com/automatically-generate-sitemap-xml-in-sveltekit-910bd09d17e7) by Alex Schnabl +- [Discovering Svelte: Things I Learned While Using Svelte](https://www.tronic247.com/discovering-svelte-things-i-learned-while-using-svelte/) by Posandu Mapa +- [Typed fetch with Sveltekit and Hono using RPC](https://dev.to/subhendupsingh/typed-fetch-with-sveltekit-and-hono-using-rpc-2clf) by Subhendu Pratap Singh +- [Svelte Context Module Scripts Explained](https://raqueebuddinaziz.com/blog/svelte-context-module-scripts-explained) by raqueebuddin aziz +- [Building with GPT4 and Svelte](https://kvak.io/meoweler) by levmiseri +- [Type-safe User Authentication in SvelteKit with Lucia, Planetscale, and Upstash Redis](https://upstash.com/blog/lucia-sveltekit) by Chris Jayden +- [Document Svelte Projects with HTML and JSDoc Comments](https://blog.robino.dev/posts/doc-comments-svelte) by Ross Robino + + + +**Libraries, Tools & Components** +- [Carta](https://github.com/BearToCode/carta-md) is a lightweight, fast and extensible Svelte Markdown editor and viewer, based on Marked +- [Threlte](https://threlte.xyz/), the 3D framework built from Svelte and Three.js has released version 6 +- [vite-plugin-web-extension](https://vite-plugin-web-extension.aklinker1.io/guide/frontend-frameworks.html#svelte-integration) works great with Svelte to make building browser extensions easier +- [Salvia-kit Svelte Dashboards](https://github.com/salvia-kit/svelte-dashboards) contains 10 free dashboard templates for SvelteKit +- [drab](https://github.com/rossrobino/drab) is an Unstyled Svelte component library +- [svelte-img-previewer](https://www.npmjs.com/package/svelte-img-previewer?activeTab=readme) is a tool for displaying images from input file types in Svelte +- [sveltekit-search-params](https://github.com/paoloricciuti/sveltekit-search-params) describes itself as the fastest way to read AND write from query search params in SvelteKit + +That's it for this month! Feel free to let us know if we missed anything on [Reddit](https://www.reddit.com/r/sveltejs/) or [Discord](https://discord.gg/svelte). + +Until next time 👋 diff --git a/documentation/blog/2023-09-20-runes.md b/documentation/blog/2023-09-20-runes.md new file mode 100644 index 0000000000..3e3448885e --- /dev/null +++ b/documentation/blog/2023-09-20-runes.md @@ -0,0 +1,224 @@ +--- +title: Introducing runes +description: "Rethinking 'rethinking reactivity'" +author: The Svelte team +authorURL: / +--- + +In 2019, Svelte 3 turned JavaScript into a [reactive language](/blog/svelte-3-rethinking-reactivity). Svelte is a web UI framework that uses a compiler to turn declarative component code like this... + +```svelte + + + +``` + +...into tightly optimized JavaScript that updates the document when state like `count` changes. Because the compiler can 'see' where `count` is referenced, the generated code is [highly efficient](/blog/virtual-dom-is-pure-overhead), and because we're hijacking syntax like `let` and `=` instead of using cumbersome APIs, you can [write less code](/blog/write-less-code). + +A common piece of feedback we get is 'I wish I could write all my JavaScript like this'. When you're used to things inside components magically updating, going back to boring old procedural code feels like going from colour to black-and-white. + +Svelte 5 changes all that with _runes_, which unlock _universal, fine-grained reactivity_. + +
+
+
+ +
+ +
Introducing runes
+
+
+ +## Before we begin + +Even though we're changing how things work under the hood, Svelte 5 should be a drop-in replacement for almost everyone. The new features are opt-in — your existing components will continue to work. + +We don't yet have a release date for Svelte 5. What we're showing you here is a work-in-progress that is likely to change! + +## What are runes? + +> **rune** /ro͞on/ _noun_ +> +> A letter or mark used as a mystical or magic symbol. + +Runes are symbols that influence the Svelte compiler. Whereas Svelte today uses `let`, `=`, the [`export`](https://learn.svelte.dev/tutorial/declaring-props) keyword and the [`$:`](https://learn.svelte.dev/tutorial/reactive-declarations) label to mean specific things, runes use _function syntax_ to achieve the same things and more. + +For example, to declare a piece of reactive state, we can use the `$state` rune: + +```diff + + + +``` + +At first glance, this might seem like a step back — perhaps even [un-Svelte-like](https://twitter.com/stolinski/status/1438173489479958536). Isn't it better if `let count` is reactive by default? + +Well, no. The reality is that as applications grow in complexity, figuring out which values are reactive and which aren't can get tricky. And the heuristic only works for `let` declarations at the top level of a component, which can cause confusion. Having code behave one way inside `.svelte` files and another inside `.js` can make it hard to refactor code, for example if you need to turn something into a [store](https://learn.svelte.dev/tutorial/writable-stores) so that you can use it in multiple places. + +## Beyond components + +With runes, reactivity extends beyond the boundaries of your `.svelte` files. Suppose we wanted to encapsulate our counter logic in a way that could be reused between components. Today, you would use a [custom store](https://learn.svelte.dev/tutorial/custom-stores) in a `.js` or `.ts` file: + +```js +import { writable } from 'svelte/store'; + +export function createCounter() { + const { subscribe, update } = writable(0); + + return { + subscribe, + increment: () => update((n) => n + 1) + }; +} +``` + +Because this implements the _store contract_ — the returned value has a `subscribe` method — we can reference the store value by prefixing the store name with `$`: + +```diff + + +- +``` + +This works, but it's pretty weird! We've found that the store API can get rather unwieldy when you start doing more complex things. + +With runes, things get much simpler: + +```diff +-import { writable } from 'svelte/store'; + +export function createCounter() { +- const { subscribe, update } = writable(0); ++ let count = $state(0); + + return { +- subscribe, +- increment: () => update((n) => n + 1) ++ get count() { return count }, ++ increment: () => count += 1 + }; +} +``` + +```diff + + + +``` + +Note that we're using a [get property](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get) in the returned object, so that `counter.count` always refers to the current value rather than the value at the time the function was called. + +## Runtime reactivity + +Today, Svelte uses _compile-time reactivity_. This means that if you have some code that uses the `$:` label to re-run automatically when dependencies change, those dependencies are determined when Svelte compiles your component: + +```svelte + +``` + +This works well... until it doesn't. Suppose we refactored the code above: + +```js +// @errors: 7006 2304 +const multiplyByHeight = (width) => width * height; +$: area = multiplyByHeight(width); +``` + +Because the `$: area = ...` declaration can only 'see' `width`, it won't be recalculated when `height` changes. As a result, code is hard to refactor, and understanding the intricacies of when Svelte chooses to update which values can become rather tricky beyond a certain level of complexity. + +Svelte 5 introduces the `$derived` and `$effect` runes, which instead determine the dependencies of their expressions when they are evaluated: + +```svelte + +``` + +As with `$state`, `$derived` and `$effect` can also be used in your `.js` and `.ts` files. + +## Signal boost + +Like every other framework, we've come to the realisation that [Knockout](https://knockoutjs.com/) was right all along. + +Svelte 5's reactivity is powered by _signals_, which are essentially [what Knockout was doing in 2010](https://dev.to/this-is-learning/the-evolution-of-signals-in-javascript-8ob). More recently, signals have been popularised by [Solid](https://www.solidjs.com/) and adopted by a multitude of other frameworks. + +We're doing things a bit differently though. In Svelte 5, signals are an under-the-hood implementation detail rather than something you interact with directly. As such, we don't have the same API design constraints, and can maximise both efficiency _and_ ergonomics. For example, we avoid the type narrowing issues that arise when values are accessed by function call, and when compiling in server-side rendering mode we can ditch the signals altogether, since on the server they're nothing but overhead. + +Signals unlock _fine-grained reactivity_, meaning that (for example) changes to a value inside a large list needn't invalidate all the _other_ members of the list. As such, Svelte 5 is ridonkulously fast. + +## Simpler times ahead + +Runes are an additive feature, but they make a whole bunch of existing concepts obsolete: + +- the difference between `let` at the top level of a component and everywhere else +- `export let` +- `$:`, with all its attendant quirks +- different behaviour between ` - + - + ``` Listening for component events looks the same as listening for DOM events: @@ -44,6 +40,7 @@ As with DOM events, if the `on:` directive is used without a value, the event wi ## --style-props ```svelte + --style-props="anycssvalue" ``` @@ -78,7 +75,6 @@ For SVG namespace, the example above desugars into using `` instead: Svelte's CSS Variables support allows for easily themeable components: ```svelte - diff --git a/packages/svelte/test/runtime-browser/custom-elements-samples/reflect-attributes-add-remove/test.js b/packages/svelte/test/runtime-browser/custom-elements-samples/reflect-attributes-add-remove/test.js new file mode 100644 index 0000000000..d973039983 --- /dev/null +++ b/packages/svelte/test/runtime-browser/custom-elements-samples/reflect-attributes-add-remove/test.js @@ -0,0 +1,19 @@ +import * as assert from 'assert.js'; +import { tick } from 'svelte'; +import './main.svelte'; + +export default async function (target) { + const element = document.createElement('custom-element'); + target.appendChild(element); + await tick(); + + const el = target.querySelector('custom-element'); + el.shadowRoot.querySelector('button').click(); + await tick(); + + assert.equal(el.getAttribute('aria-expanded'), ''); + el.shadowRoot.querySelector('button').click(); + await tick(); + + assert.equal(el.getAttribute('aria-expanded'), null); +} diff --git a/packages/svelte/test/runtime-browser/custom-elements-samples/reflect-attributes/test.js b/packages/svelte/test/runtime-browser/custom-elements-samples/reflect-attributes/test.js index c66f9f3b97..e869e7bff9 100644 --- a/packages/svelte/test/runtime-browser/custom-elements-samples/reflect-attributes/test.js +++ b/packages/svelte/test/runtime-browser/custom-elements-samples/reflect-attributes/test.js @@ -6,25 +6,25 @@ export default async function (target) { target.innerHTML = ''; await tick(); await tick(); - const ceRoot = target.querySelector('custom-element').shadowRoot; - const div = ceRoot.querySelector('div'); - const p = ceRoot.querySelector('p'); - const button = ceRoot.querySelector('button'); + const ce_root = target.querySelector('custom-element').shadowRoot; + const div = ce_root.querySelector('div'); + const p = ce_root.querySelector('p'); + const button = ce_root.querySelector('button'); assert.equal(getComputedStyle(div).color, 'rgb(255, 0, 0)'); assert.equal(getComputedStyle(p).color, 'rgb(255, 255, 255)'); - const innerRoot = ceRoot.querySelector('my-widget').shadowRoot; - const innerDiv = innerRoot.querySelector('div'); - const innerP = innerRoot.querySelector('p'); + const inner_root = ce_root.querySelector('my-widget').shadowRoot; + const inner_div = inner_root.querySelector('div'); + const inner_p = inner_root.querySelector('p'); - assert.equal(getComputedStyle(innerDiv).color, 'rgb(255, 0, 0)'); - assert.equal(getComputedStyle(innerP).color, 'rgb(255, 255, 255)'); + assert.equal(getComputedStyle(inner_div).color, 'rgb(255, 0, 0)'); + assert.equal(getComputedStyle(inner_p).color, 'rgb(255, 255, 255)'); button.click(); await tick(); await tick(); assert.equal(getComputedStyle(div).color, 'rgb(0, 0, 0)'); - assert.equal(getComputedStyle(innerDiv).color, 'rgb(0, 0, 0)'); + assert.equal(getComputedStyle(inner_div).color, 'rgb(0, 0, 0)'); } diff --git a/packages/svelte/test/runtime-browser/driver.js b/packages/svelte/test/runtime-browser/driver.js index 286ddbe62d..349181a2dc 100644 --- a/packages/svelte/test/runtime-browser/driver.js +++ b/packages/svelte/test/runtime-browser/driver.js @@ -30,7 +30,7 @@ export default async function (target) { const component = new SvelteComponent(options); - const waitUntil = async (fn, ms = 500) => { + const wait_until = async (fn, ms = 500) => { const start = new Date().getTime(); do { if (fn()) return; @@ -48,7 +48,7 @@ export default async function (target) { component, target, window, - waitUntil + waitUntil: wait_until }); component.$destroy(); diff --git a/packages/svelte/test/runtime-browser/samples/component-css-custom-properties-dynamic-svg/_config.js b/packages/svelte/test/runtime-browser/samples/component-css-custom-properties-dynamic-svg/_config.js index a17e6e939d..4b2c5b8c34 100644 --- a/packages/svelte/test/runtime-browser/samples/component-css-custom-properties-dynamic-svg/_config.js +++ b/packages/svelte/test/runtime-browser/samples/component-css-custom-properties-dynamic-svg/_config.js @@ -45,14 +45,14 @@ export default { ` ); - const circleColor1 = target.querySelector('#svg-1 circle'); - const rectColor1 = target.querySelector('#svg-1 rect'); - const circleColor2 = target.querySelector('#svg-2 circle'); - const rectColor2 = target.querySelector('#svg-2 rect'); + const circle_color1 = target.querySelector('#svg-1 circle'); + const rect_color1 = target.querySelector('#svg-1 rect'); + const circle_color2 = target.querySelector('#svg-2 circle'); + const rect_color2 = target.querySelector('#svg-2 rect'); - assert.htmlEqual(window.getComputedStyle(circleColor1).fill, 'rgb(255, 0, 0)'); - assert.htmlEqual(window.getComputedStyle(rectColor1).fill, 'rgb(255, 255, 0)'); - assert.htmlEqual(window.getComputedStyle(circleColor2).fill, 'rgb(0, 255, 255)'); - assert.htmlEqual(window.getComputedStyle(rectColor2).fill, 'rgb(0, 0, 0)'); + assert.htmlEqual(window.getComputedStyle(circle_color1).fill, 'rgb(255, 0, 0)'); + assert.htmlEqual(window.getComputedStyle(rect_color1).fill, 'rgb(255, 255, 0)'); + assert.htmlEqual(window.getComputedStyle(circle_color2).fill, 'rgb(0, 255, 255)'); + assert.htmlEqual(window.getComputedStyle(rect_color2).fill, 'rgb(0, 0, 0)'); } }; diff --git a/packages/svelte/test/runtime-browser/samples/component-css-custom-properties/_config.js b/packages/svelte/test/runtime-browser/samples/component-css-custom-properties/_config.js index 9c3b7cbdea..04c0f0a20b 100644 --- a/packages/svelte/test/runtime-browser/samples/component-css-custom-properties/_config.js +++ b/packages/svelte/test/runtime-browser/samples/component-css-custom-properties/_config.js @@ -14,14 +14,14 @@ export default { `, test({ target, window, assert }) { - const railColor1 = target.querySelector('#slider-1 p'); - const trackColor1 = target.querySelector('#slider-1 span'); - const railColor2 = target.querySelector('#slider-2 p'); - const trackColor2 = target.querySelector('#slider-2 span'); + const rail_color1 = target.querySelector('#slider-1 p'); + const track_color1 = target.querySelector('#slider-1 span'); + const rail_color2 = target.querySelector('#slider-2 p'); + const track_color2 = target.querySelector('#slider-2 span'); - assert.htmlEqual(window.getComputedStyle(railColor1).color, 'rgb(0, 0, 0)'); - assert.htmlEqual(window.getComputedStyle(trackColor1).color, 'rgb(255, 0, 0)'); - assert.htmlEqual(window.getComputedStyle(railColor2).color, 'rgb(0, 255, 0)'); - assert.htmlEqual(window.getComputedStyle(trackColor2).color, 'rgb(0, 0, 255)'); + assert.htmlEqual(window.getComputedStyle(rail_color1).color, 'rgb(0, 0, 0)'); + assert.htmlEqual(window.getComputedStyle(track_color1).color, 'rgb(255, 0, 0)'); + assert.htmlEqual(window.getComputedStyle(rail_color2).color, 'rgb(0, 255, 0)'); + assert.htmlEqual(window.getComputedStyle(track_color2).color, 'rgb(0, 0, 255)'); } }; diff --git a/packages/svelte/test/runtime-browser/samples/svelte-component-css-custom-properties/_config.js b/packages/svelte/test/runtime-browser/samples/svelte-component-css-custom-properties/_config.js index 8e423af308..53ff398e8f 100644 --- a/packages/svelte/test/runtime-browser/samples/svelte-component-css-custom-properties/_config.js +++ b/packages/svelte/test/runtime-browser/samples/svelte-component-css-custom-properties/_config.js @@ -18,31 +18,31 @@ export default { `, test({ target, window, assert, component }) { function assert_slider_1() { - const railColor1 = target.querySelector('#component1 p'); - const trackColor1 = target.querySelector('#component1 span'); - const railColor2 = target.querySelector('#component2 p'); - const trackColor2 = target.querySelector('#component2 span'); + const rail_color1 = target.querySelector('#component1 p'); + const track_color1 = target.querySelector('#component1 span'); + const rail_color2 = target.querySelector('#component2 p'); + const track_color2 = target.querySelector('#component2 span'); - assert.equal(window.getComputedStyle(railColor1).color, 'rgb(0, 0, 0)'); - assert.equal(window.getComputedStyle(trackColor1).color, 'rgb(255, 0, 0)'); - assert.equal(window.getComputedStyle(railColor2).color, 'rgb(0, 255, 0)'); - assert.equal(window.getComputedStyle(trackColor2).color, 'rgb(0, 0, 255)'); - assert.equal(railColor1.textContent, 'Slider1'); - assert.equal(railColor2.textContent, 'Slider1'); + assert.equal(window.getComputedStyle(rail_color1).color, 'rgb(0, 0, 0)'); + assert.equal(window.getComputedStyle(track_color1).color, 'rgb(255, 0, 0)'); + assert.equal(window.getComputedStyle(rail_color2).color, 'rgb(0, 255, 0)'); + assert.equal(window.getComputedStyle(track_color2).color, 'rgb(0, 0, 255)'); + assert.equal(rail_color1.textContent, 'Slider1'); + assert.equal(rail_color2.textContent, 'Slider1'); } function assert_slider_2() { - const railColor1 = target.querySelector('#component1 p'); - const trackColor1 = target.querySelector('#component1 span'); - const railColor2 = target.querySelector('#component2 p'); - const trackColor2 = target.querySelector('#component2 span'); + const rail_color1 = target.querySelector('#component1 p'); + const track_color1 = target.querySelector('#component1 span'); + const rail_color2 = target.querySelector('#component2 p'); + const track_color2 = target.querySelector('#component2 span'); - assert.equal(window.getComputedStyle(railColor1).color, 'rgb(0, 0, 0)'); - assert.equal(window.getComputedStyle(trackColor1).color, 'rgb(255, 0, 0)'); - assert.equal(window.getComputedStyle(railColor2).color, 'rgb(0, 255, 0)'); - assert.equal(window.getComputedStyle(trackColor2).color, 'rgb(0, 0, 255)'); - assert.equal(railColor1.textContent, 'Slider2'); - assert.equal(railColor2.textContent, 'Slider2'); + assert.equal(window.getComputedStyle(rail_color1).color, 'rgb(0, 0, 0)'); + assert.equal(window.getComputedStyle(track_color1).color, 'rgb(255, 0, 0)'); + assert.equal(window.getComputedStyle(rail_color2).color, 'rgb(0, 255, 0)'); + assert.equal(window.getComputedStyle(track_color2).color, 'rgb(0, 0, 255)'); + assert.equal(rail_color1.textContent, 'Slider2'); + assert.equal(rail_color2.textContent, 'Slider2'); } assert_slider_1(); diff --git a/packages/svelte/test/runtime-browser/samples/svelte-component-css-custom-properties2/_config.js b/packages/svelte/test/runtime-browser/samples/svelte-component-css-custom-properties2/_config.js index 6bc789035d..6c3656f630 100644 --- a/packages/svelte/test/runtime-browser/samples/svelte-component-css-custom-properties2/_config.js +++ b/packages/svelte/test/runtime-browser/samples/svelte-component-css-custom-properties2/_config.js @@ -20,31 +20,31 @@ export default { `, test({ target, window, assert, component }) { function assert_slider_1() { - const railColor1 = target.querySelector('#component1 p'); - const trackColor1 = target.querySelector('#component1 span'); - const railColor2 = target.querySelector('#component2 p'); - const trackColor2 = target.querySelector('#component2 span'); + const rail_color1 = target.querySelector('#component1 p'); + const track_color1 = target.querySelector('#component1 span'); + const rail_color2 = target.querySelector('#component2 p'); + const track_color2 = target.querySelector('#component2 span'); - assert.equal(window.getComputedStyle(railColor1).color, 'rgb(0, 0, 0)'); - assert.equal(window.getComputedStyle(trackColor1).color, 'rgb(255, 0, 0)'); - assert.equal(window.getComputedStyle(railColor2).color, 'rgb(0, 255, 0)'); - assert.equal(window.getComputedStyle(trackColor2).color, 'rgb(0, 0, 255)'); - assert.equal(railColor1.textContent, 'Slider1'); - assert.equal(railColor2.textContent, 'Slider1'); + assert.equal(window.getComputedStyle(rail_color1).color, 'rgb(0, 0, 0)'); + assert.equal(window.getComputedStyle(track_color1).color, 'rgb(255, 0, 0)'); + assert.equal(window.getComputedStyle(rail_color2).color, 'rgb(0, 255, 0)'); + assert.equal(window.getComputedStyle(track_color2).color, 'rgb(0, 0, 255)'); + assert.equal(rail_color1.textContent, 'Slider1'); + assert.equal(rail_color2.textContent, 'Slider1'); } function assert_slider_2() { - const railColor1 = target.querySelector('#component1 p'); - const trackColor1 = target.querySelector('#component1 span'); - const railColor2 = target.querySelector('#component2 p'); - const trackColor2 = target.querySelector('#component2 span'); + const rail_color1 = target.querySelector('#component1 p'); + const track_color1 = target.querySelector('#component1 span'); + const rail_color2 = target.querySelector('#component2 p'); + const track_color2 = target.querySelector('#component2 span'); - assert.equal(window.getComputedStyle(railColor1).color, 'rgb(0, 0, 0)'); - assert.equal(window.getComputedStyle(trackColor1).color, 'rgb(255, 0, 0)'); - assert.equal(window.getComputedStyle(railColor2).color, 'rgb(0, 255, 0)'); - assert.equal(window.getComputedStyle(trackColor2).color, 'rgb(0, 0, 255)'); - assert.equal(railColor1.textContent, 'Slider2'); - assert.equal(railColor2.textContent, 'Slider2'); + assert.equal(window.getComputedStyle(rail_color1).color, 'rgb(0, 0, 0)'); + assert.equal(window.getComputedStyle(track_color1).color, 'rgb(255, 0, 0)'); + assert.equal(window.getComputedStyle(rail_color2).color, 'rgb(0, 255, 0)'); + assert.equal(window.getComputedStyle(track_color2).color, 'rgb(0, 0, 255)'); + assert.equal(rail_color1.textContent, 'Slider2'); + assert.equal(rail_color2.textContent, 'Slider2'); } assert_slider_1(); diff --git a/packages/svelte/test/runtime-browser/samples/svelte-self-css-custom-properties/_config.js b/packages/svelte/test/runtime-browser/samples/svelte-self-css-custom-properties/_config.js index f3023db3c4..7350db32ca 100644 --- a/packages/svelte/test/runtime-browser/samples/svelte-self-css-custom-properties/_config.js +++ b/packages/svelte/test/runtime-browser/samples/svelte-self-css-custom-properties/_config.js @@ -22,26 +22,26 @@ export default { `, test({ target, window, assert }) { - const railColor1 = target.querySelector('#component1 p'); - const trackColor1 = target.querySelector('#component1 span'); - const railColor2 = target.querySelector('#component2 p'); - const trackColor2 = target.querySelector('#component2 span'); - const nestRailColor1 = target.querySelector('#nest-component1 p'); - const nestTrackColor1 = target.querySelector('#nest-component1 span'); - const nestRailColor2 = target.querySelector('#nest-component2 p'); - const nestTrackColor2 = target.querySelector('#nest-component2 span'); + const rail_color1 = target.querySelector('#component1 p'); + const track_color1 = target.querySelector('#component1 span'); + const rail_color2 = target.querySelector('#component2 p'); + const track_color2 = target.querySelector('#component2 span'); + const nest_rail_color1 = target.querySelector('#nest-component1 p'); + const nest_track_color1 = target.querySelector('#nest-component1 span'); + const nest_rail_color2 = target.querySelector('#nest-component2 p'); + const nest_track_color2 = target.querySelector('#nest-component2 span'); - assert.equal(window.getComputedStyle(railColor1).color, 'rgb(0, 0, 0)'); - assert.equal(window.getComputedStyle(trackColor1).color, 'rgb(255, 0, 0)'); - assert.equal(window.getComputedStyle(railColor2).color, 'rgb(0, 255, 0)'); - assert.equal(window.getComputedStyle(trackColor2).color, 'rgb(0, 0, 255)'); - assert.equal(window.getComputedStyle(nestRailColor1).color, 'rgb(255, 255, 0)'); - assert.equal(window.getComputedStyle(nestTrackColor1).color, 'rgb(255, 0, 255)'); - assert.equal(window.getComputedStyle(nestRailColor2).color, 'rgb(0, 255, 255)'); - assert.equal(window.getComputedStyle(nestTrackColor2).color, 'rgb(255, 255, 255)'); - assert.equal(railColor1.textContent, 'Slider1'); - assert.equal(railColor2.textContent, 'Slider2'); - assert.equal(nestRailColor1.textContent, 'Slider1'); - assert.equal(nestRailColor2.textContent, 'Slider2'); + assert.equal(window.getComputedStyle(rail_color1).color, 'rgb(0, 0, 0)'); + assert.equal(window.getComputedStyle(track_color1).color, 'rgb(255, 0, 0)'); + assert.equal(window.getComputedStyle(rail_color2).color, 'rgb(0, 255, 0)'); + assert.equal(window.getComputedStyle(track_color2).color, 'rgb(0, 0, 255)'); + assert.equal(window.getComputedStyle(nest_rail_color1).color, 'rgb(255, 255, 0)'); + assert.equal(window.getComputedStyle(nest_track_color1).color, 'rgb(255, 0, 255)'); + assert.equal(window.getComputedStyle(nest_rail_color2).color, 'rgb(0, 255, 255)'); + assert.equal(window.getComputedStyle(nest_track_color2).color, 'rgb(255, 255, 255)'); + assert.equal(rail_color1.textContent, 'Slider1'); + assert.equal(rail_color2.textContent, 'Slider2'); + assert.equal(nest_rail_color1.textContent, 'Slider1'); + assert.equal(nest_rail_color2.textContent, 'Slider2'); } }; diff --git a/packages/svelte/test/runtime-browser/samples/svelte-self-css-custom-properties2/_config.js b/packages/svelte/test/runtime-browser/samples/svelte-self-css-custom-properties2/_config.js index 6a976a141c..58ff163f9b 100644 --- a/packages/svelte/test/runtime-browser/samples/svelte-self-css-custom-properties2/_config.js +++ b/packages/svelte/test/runtime-browser/samples/svelte-self-css-custom-properties2/_config.js @@ -25,51 +25,51 @@ export default { `, test({ target, window, assert, component }) { function assert_slider_1() { - const railColor1 = target.querySelector('#component1 p'); - const trackColor1 = target.querySelector('#component1 span'); - const railColor2 = target.querySelector('#component2 p'); - const trackColor2 = target.querySelector('#component2 span'); - const nestRailColor1 = target.querySelector('#nest-component1 p'); - const nestTrackColor1 = target.querySelector('#nest-component1 span'); - const nestRailColor2 = target.querySelector('#nest-component2 p'); - const nestTrackColor2 = target.querySelector('#nest-component2 span'); + const rail_color1 = target.querySelector('#component1 p'); + const track_color1 = target.querySelector('#component1 span'); + const rail_color2 = target.querySelector('#component2 p'); + const track_color2 = target.querySelector('#component2 span'); + const nest_rail_color1 = target.querySelector('#nest-component1 p'); + const nest_track_color1 = target.querySelector('#nest-component1 span'); + const nest_rail_color2 = target.querySelector('#nest-component2 p'); + const nest_track_color2 = target.querySelector('#nest-component2 span'); - assert.equal(window.getComputedStyle(railColor1).color, 'rgb(0, 0, 0)'); - assert.equal(window.getComputedStyle(trackColor1).color, 'rgb(255, 0, 0)'); - assert.equal(window.getComputedStyle(railColor2).color, 'rgb(0, 255, 0)'); - assert.equal(window.getComputedStyle(trackColor2).color, 'rgb(0, 0, 255)'); - assert.equal(window.getComputedStyle(nestRailColor1).color, 'rgb(255, 255, 0)'); - assert.equal(window.getComputedStyle(nestTrackColor1).color, 'rgb(255, 0, 255)'); - assert.equal(window.getComputedStyle(nestRailColor2).color, 'rgb(255, 255, 0)'); - assert.equal(window.getComputedStyle(nestTrackColor2).color, 'rgb(255, 0, 255)'); - assert.equal(railColor1.textContent, 'Slider1'); - assert.equal(railColor2.textContent, 'Slider1'); - assert.equal(nestRailColor1.textContent, 'Slider1'); - assert.equal(nestRailColor2.textContent, 'Slider1'); + assert.equal(window.getComputedStyle(rail_color1).color, 'rgb(0, 0, 0)'); + assert.equal(window.getComputedStyle(track_color1).color, 'rgb(255, 0, 0)'); + assert.equal(window.getComputedStyle(rail_color2).color, 'rgb(0, 255, 0)'); + assert.equal(window.getComputedStyle(track_color2).color, 'rgb(0, 0, 255)'); + assert.equal(window.getComputedStyle(nest_rail_color1).color, 'rgb(255, 255, 0)'); + assert.equal(window.getComputedStyle(nest_track_color1).color, 'rgb(255, 0, 255)'); + assert.equal(window.getComputedStyle(nest_rail_color2).color, 'rgb(255, 255, 0)'); + assert.equal(window.getComputedStyle(nest_track_color2).color, 'rgb(255, 0, 255)'); + assert.equal(rail_color1.textContent, 'Slider1'); + assert.equal(rail_color2.textContent, 'Slider1'); + assert.equal(nest_rail_color1.textContent, 'Slider1'); + assert.equal(nest_rail_color2.textContent, 'Slider1'); } function assert_slider_2() { - const railColor1 = target.querySelector('#component1 p'); - const trackColor1 = target.querySelector('#component1 span'); - const railColor2 = target.querySelector('#component2 p'); - const trackColor2 = target.querySelector('#component2 span'); - const nestRailColor1 = target.querySelector('#nest-component1 p'); - const nestTrackColor1 = target.querySelector('#nest-component1 span'); - const nestRailColor2 = target.querySelector('#nest-component2 p'); - const nestTrackColor2 = target.querySelector('#nest-component2 span'); + const rail_color1 = target.querySelector('#component1 p'); + const track_color1 = target.querySelector('#component1 span'); + const rail_color2 = target.querySelector('#component2 p'); + const track_color2 = target.querySelector('#component2 span'); + const nest_rail_color1 = target.querySelector('#nest-component1 p'); + const nest_track_color1 = target.querySelector('#nest-component1 span'); + const nest_rail_color2 = target.querySelector('#nest-component2 p'); + const nest_track_color2 = target.querySelector('#nest-component2 span'); - assert.equal(window.getComputedStyle(railColor1).color, 'rgb(0, 0, 0)'); - assert.equal(window.getComputedStyle(trackColor1).color, 'rgb(255, 0, 0)'); - assert.equal(window.getComputedStyle(railColor2).color, 'rgb(0, 255, 0)'); - assert.equal(window.getComputedStyle(trackColor2).color, 'rgb(0, 0, 255)'); - assert.equal(window.getComputedStyle(nestRailColor1).color, 'rgb(0, 255, 255)'); - assert.equal(window.getComputedStyle(nestTrackColor1).color, 'rgb(255, 255, 255)'); - assert.equal(window.getComputedStyle(nestRailColor2).color, 'rgb(0, 255, 255)'); - assert.equal(window.getComputedStyle(nestTrackColor2).color, 'rgb(255, 255, 255)'); - assert.equal(railColor1.textContent, 'Slider2'); - assert.equal(railColor2.textContent, 'Slider2'); - assert.equal(nestRailColor1.textContent, 'Slider2'); - assert.equal(nestRailColor2.textContent, 'Slider2'); + assert.equal(window.getComputedStyle(rail_color1).color, 'rgb(0, 0, 0)'); + assert.equal(window.getComputedStyle(track_color1).color, 'rgb(255, 0, 0)'); + assert.equal(window.getComputedStyle(rail_color2).color, 'rgb(0, 255, 0)'); + assert.equal(window.getComputedStyle(track_color2).color, 'rgb(0, 0, 255)'); + assert.equal(window.getComputedStyle(nest_rail_color1).color, 'rgb(0, 255, 255)'); + assert.equal(window.getComputedStyle(nest_track_color1).color, 'rgb(255, 255, 255)'); + assert.equal(window.getComputedStyle(nest_rail_color2).color, 'rgb(0, 255, 255)'); + assert.equal(window.getComputedStyle(nest_track_color2).color, 'rgb(255, 255, 255)'); + assert.equal(rail_color1.textContent, 'Slider2'); + assert.equal(rail_color2.textContent, 'Slider2'); + assert.equal(nest_rail_color1.textContent, 'Slider2'); + assert.equal(nest_rail_color2.textContent, 'Slider2'); } assert_slider_1(); diff --git a/packages/svelte/test/runtime/runtime.shared.js b/packages/svelte/test/runtime/runtime.shared.js index b02dfb81ff..09b990b514 100644 --- a/packages/svelte/test/runtime/runtime.shared.js +++ b/packages/svelte/test/runtime/runtime.shared.js @@ -55,18 +55,18 @@ async function run_test(dir) { const cwd = path.resolve(`${__dirname}/samples/${dir}`); - const compileOptions = Object.assign({}, config.compileOptions || {}, { + const compile_options = Object.assign({}, config.compileOptions || {}, { hydratable: hydrate, immutable: config.immutable, accessors: 'accessors' in config ? config.accessors : true }); - const load = create_loader(compileOptions, cwd); + const load = create_loader(compile_options, cwd); let mod; let SvelteComponent; - let unintendedError = null; + let unintended_error = null; if (config.expect_unhandled_rejections) { listeners.forEach((listener) => { @@ -111,7 +111,7 @@ async function run_test(dir) { let snapshot = undefined; if (hydrate && from_ssr_html) { - const load_ssr = create_loader({ ...compileOptions, generate: 'ssr' }, cwd); + const load_ssr = create_loader({ ...compile_options, generate: 'ssr' }, cwd); // ssr into target if (config.before_test) config.before_test(); @@ -152,14 +152,14 @@ async function run_test(dir) { console.warn = warn; if (config.error) { - unintendedError = true; + unintended_error = true; assert.fail('Expected a runtime error'); } if (config.warnings) { assert.deepEqual(warnings, config.warnings); } else if (warnings.length) { - unintendedError = true; + unintended_error = true; assert.fail('Received unexpected warnings'); } @@ -183,7 +183,7 @@ async function run_test(dir) { snapshot, window, raf, - compileOptions, + compileOptions: compile_options, load }); } @@ -201,7 +201,7 @@ async function run_test(dir) { await test() .catch((err) => { - if (config.error && !unintendedError) { + if (config.error && !unintended_error) { if (typeof config.error === 'function') { config.error(assert, err); } else { @@ -217,7 +217,7 @@ async function run_test(dir) { mkdirp(path.dirname(out)); // file could be in subdirectory, therefore don't use dir const { js } = compile(fs.readFileSync(`${cwd}/${file}`, 'utf-8').replace(/\r/g, ''), { - ...compileOptions, + ...compile_options, filename: file }); fs.writeFileSync(out, js.code); diff --git a/packages/svelte/test/runtime/samples/$$rest-without-props/_config.js b/packages/svelte/test/runtime/samples/$$rest-without-props/_config.js index 9412aa99df..fb1d4f23ce 100644 --- a/packages/svelte/test/runtime/samples/$$rest-without-props/_config.js +++ b/packages/svelte/test/runtime/samples/$$rest-without-props/_config.js @@ -10,9 +10,9 @@ export default { `, async test({ assert, target, window }) { const [btn1, btn2, btn3, btn4] = target.querySelectorAll('button'); - const clickEvent = new window.MouseEvent('click'); + const click_event = new window.MouseEvent('click'); - await btn1.dispatchEvent(clickEvent); + await btn1.dispatchEvent(click_event); assert.htmlEqual( target.innerHTML, @@ -24,7 +24,7 @@ export default { ` ); - await btn2.dispatchEvent(clickEvent); + await btn2.dispatchEvent(click_event); assert.htmlEqual( target.innerHTML, @@ -36,7 +36,7 @@ export default { ` ); - await btn3.dispatchEvent(clickEvent); + await btn3.dispatchEvent(click_event); assert.htmlEqual( target.innerHTML, @@ -48,7 +48,7 @@ export default { ` ); - await btn4.dispatchEvent(clickEvent); + await btn4.dispatchEvent(click_event); assert.htmlEqual( target.innerHTML, diff --git a/packages/svelte/test/runtime/samples/$$rest/_config.js b/packages/svelte/test/runtime/samples/$$rest/_config.js index 4d050059fc..473ad9f9bc 100644 --- a/packages/svelte/test/runtime/samples/$$rest/_config.js +++ b/packages/svelte/test/runtime/samples/$$rest/_config.js @@ -12,9 +12,9 @@ export default { async test({ assert, target, window }) { const [btn1, btn2, btn3, btn4] = target.querySelectorAll('button'); - const clickEvent = new window.MouseEvent('click'); + const click_event = new window.MouseEvent('click'); - await btn1.dispatchEvent(clickEvent); + await btn1.dispatchEvent(click_event); assert.htmlEqual( target.innerHTML, @@ -27,7 +27,7 @@ export default { ` ); - await btn2.dispatchEvent(clickEvent); + await btn2.dispatchEvent(click_event); assert.htmlEqual( target.innerHTML, @@ -40,7 +40,7 @@ export default { ` ); - await btn3.dispatchEvent(clickEvent); + await btn3.dispatchEvent(click_event); assert.htmlEqual( target.innerHTML, @@ -53,7 +53,7 @@ export default { ` ); - await btn4.dispatchEvent(clickEvent); + await btn4.dispatchEvent(click_event); assert.htmlEqual( target.innerHTML, diff --git a/packages/svelte/test/runtime/samples/action-function/_config.js b/packages/svelte/test/runtime/samples/action-function/_config.js index f8cf390550..1bc45788e5 100644 --- a/packages/svelte/test/runtime/samples/action-function/_config.js +++ b/packages/svelte/test/runtime/samples/action-function/_config.js @@ -5,10 +5,10 @@ export default { async test({ assert, target, window }) { const button = target.querySelector('button'); - const eventEnter = new window.MouseEvent('mouseenter'); - const eventLeave = new window.MouseEvent('mouseleave'); + const event_enter = new window.MouseEvent('mouseenter'); + const event_leave = new window.MouseEvent('mouseleave'); - await button.dispatchEvent(eventEnter); + await button.dispatchEvent(event_enter); assert.htmlEqual( target.innerHTML, ` @@ -17,7 +17,7 @@ export default { ` ); - await button.dispatchEvent(eventLeave); + await button.dispatchEvent(event_leave); assert.htmlEqual( target.innerHTML, ` diff --git a/packages/svelte/test/runtime/samples/action-update/_config.js b/packages/svelte/test/runtime/samples/action-update/_config.js index 0de4397418..f8ce663a8f 100644 --- a/packages/svelte/test/runtime/samples/action-update/_config.js +++ b/packages/svelte/test/runtime/samples/action-update/_config.js @@ -7,7 +7,7 @@ export default { const button = target.querySelector('button'); const enter = new window.MouseEvent('mouseenter'); const leave = new window.MouseEvent('mouseleave'); - const ctrlPress = new window.KeyboardEvent('keydown', { ctrlKey: true }); + const ctrl_press = new window.KeyboardEvent('keydown', { ctrlKey: true }); await button.dispatchEvent(enter); assert.htmlEqual( @@ -18,7 +18,7 @@ export default { ` ); - await window.dispatchEvent(ctrlPress); + await window.dispatchEvent(ctrl_press); assert.htmlEqual( target.innerHTML, ` diff --git a/packages/svelte/test/runtime/samples/action/_config.js b/packages/svelte/test/runtime/samples/action/_config.js index f8cf390550..1bc45788e5 100644 --- a/packages/svelte/test/runtime/samples/action/_config.js +++ b/packages/svelte/test/runtime/samples/action/_config.js @@ -5,10 +5,10 @@ export default { async test({ assert, target, window }) { const button = target.querySelector('button'); - const eventEnter = new window.MouseEvent('mouseenter'); - const eventLeave = new window.MouseEvent('mouseleave'); + const event_enter = new window.MouseEvent('mouseenter'); + const event_leave = new window.MouseEvent('mouseleave'); - await button.dispatchEvent(eventEnter); + await button.dispatchEvent(event_enter); assert.htmlEqual( target.innerHTML, ` @@ -17,7 +17,7 @@ export default { ` ); - await button.dispatchEvent(eventLeave); + await button.dispatchEvent(event_leave); assert.htmlEqual( target.innerHTML, ` diff --git a/packages/svelte/test/runtime/samples/attribute-casing-custom-element/_config.js b/packages/svelte/test/runtime/samples/attribute-casing-custom-element/_config.js new file mode 100644 index 0000000000..1e9874874a --- /dev/null +++ b/packages/svelte/test/runtime/samples/attribute-casing-custom-element/_config.js @@ -0,0 +1,7 @@ +export default { + skip_if_ssr: true, + skip_if_hydrate: true, + html: ` + Hello World! + ` +}; diff --git a/packages/svelte/test/runtime/samples/attribute-casing-custom-element/main.svelte b/packages/svelte/test/runtime/samples/attribute-casing-custom-element/main.svelte new file mode 100644 index 0000000000..6433d0dc76 --- /dev/null +++ b/packages/svelte/test/runtime/samples/attribute-casing-custom-element/main.svelte @@ -0,0 +1,25 @@ + + + diff --git a/packages/svelte/test/runtime/samples/attribute-custom-element-inheritance/_config.js b/packages/svelte/test/runtime/samples/attribute-custom-element-inheritance/_config.js new file mode 100644 index 0000000000..10495ab24e --- /dev/null +++ b/packages/svelte/test/runtime/samples/attribute-custom-element-inheritance/_config.js @@ -0,0 +1,7 @@ +export default { + skip_if_ssr: true, + skip_if_hydrate: true, + html: ` + Hello World! + ` +}; diff --git a/packages/svelte/test/runtime/samples/attribute-custom-element-inheritance/main.svelte b/packages/svelte/test/runtime/samples/attribute-custom-element-inheritance/main.svelte new file mode 100644 index 0000000000..1324bcc4b1 --- /dev/null +++ b/packages/svelte/test/runtime/samples/attribute-custom-element-inheritance/main.svelte @@ -0,0 +1,33 @@ + + + diff --git a/packages/svelte/test/runtime/samples/await-function-promise/_config.js b/packages/svelte/test/runtime/samples/await-function-promise/_config.js index 01fe60cd0b..44cf13160b 100644 --- a/packages/svelte/test/runtime/samples/await-function-promise/_config.js +++ b/packages/svelte/test/runtime/samples/await-function-promise/_config.js @@ -1,8 +1,8 @@ -const realPromise = Promise.resolve(42); +const real_promise = Promise.resolve(42); const promise = () => {}; -promise.then = realPromise.then.bind(realPromise); -promise.catch = realPromise.catch.bind(realPromise); +promise.then = real_promise.then.bind(real_promise); +promise.catch = real_promise.catch.bind(real_promise); export default { get props() { diff --git a/packages/svelte/test/runtime/samples/await-in-each/_config.js b/packages/svelte/test/runtime/samples/await-in-each/_config.js index 0e4109ea49..73dbb01e87 100644 --- a/packages/svelte/test/runtime/samples/await-in-each/_config.js +++ b/packages/svelte/test/runtime/samples/await-in-each/_config.js @@ -1,13 +1,13 @@ let fulfil; -const thePromise = new Promise((f) => { +const the_promise = new Promise((f) => { fulfil = f; }); const items = [ { title: 'a title', - data: thePromise + data: the_promise } ]; @@ -23,7 +23,7 @@ export default { test({ assert, target }) { fulfil(42); - return thePromise.then(() => { + return the_promise.then(() => { assert.htmlEqual( target.innerHTML, ` diff --git a/packages/svelte/test/runtime/samples/await-then-catch-event/_config.js b/packages/svelte/test/runtime/samples/await-then-catch-event/_config.js index 2705eb7e17..32189e2389 100644 --- a/packages/svelte/test/runtime/samples/await-then-catch-event/_config.js +++ b/packages/svelte/test/runtime/samples/await-then-catch-event/_config.js @@ -28,10 +28,10 @@ export default { assert.equal(component.clicked, 42); - const thePromise = Promise.resolve(43); - component.thePromise = thePromise; + const the_promise = Promise.resolve(43); + component.thePromise = the_promise; - return thePromise; + return the_promise; }) .then(() => { const { button } = component; diff --git a/packages/svelte/test/runtime/samples/await-then-catch-if/_config.js b/packages/svelte/test/runtime/samples/await-then-catch-if/_config.js index 42683c56f8..f6a3e2b981 100644 --- a/packages/svelte/test/runtime/samples/await-then-catch-if/_config.js +++ b/packages/svelte/test/runtime/samples/await-then-catch-if/_config.js @@ -1,12 +1,12 @@ let fulfil; -const thePromise = new Promise((f) => { +const the_promise = new Promise((f) => { fulfil = f; }); export default { get props() { - return { show: true, thePromise }; + return { show: true, thePromise: the_promise }; }, html: ` @@ -16,7 +16,7 @@ export default { test({ assert, component, target }) { fulfil(42); - return thePromise.then(() => { + return the_promise.then(() => { assert.htmlEqual( target.innerHTML, ` @@ -35,7 +35,7 @@ export default { component.show = true; - return thePromise.then(() => { + return the_promise.then(() => { assert.htmlEqual( target.innerHTML, ` diff --git a/packages/svelte/test/runtime/samples/await-then-catch-order/_config.js b/packages/svelte/test/runtime/samples/await-then-catch-order/_config.js index 275d250233..b588d2e150 100644 --- a/packages/svelte/test/runtime/samples/await-then-catch-order/_config.js +++ b/packages/svelte/test/runtime/samples/await-then-catch-order/_config.js @@ -1,12 +1,12 @@ let fulfil; -const thePromise = new Promise((f) => { +const the_promise = new Promise((f) => { fulfil = f; }); export default { get props() { - return { thePromise }; + return { thePromise: the_promise }; }, html: ` @@ -16,7 +16,7 @@ export default { test({ assert, target }) { fulfil(42); - return thePromise.then(() => { + return the_promise.then(() => { assert.htmlEqual( target.innerHTML, ` diff --git a/packages/svelte/test/runtime/samples/await-then-if/_config.js b/packages/svelte/test/runtime/samples/await-then-if/_config.js index b32ba04715..38bf183971 100644 --- a/packages/svelte/test/runtime/samples/await-then-if/_config.js +++ b/packages/svelte/test/runtime/samples/await-then-if/_config.js @@ -1,12 +1,12 @@ let fulfil; -const thePromise = new Promise((f) => { +const the_promise = new Promise((f) => { fulfil = f; }); export default { get props() { - return { thePromise }; + return { thePromise: the_promise }; }, html: ` @@ -16,7 +16,7 @@ export default { async test({ assert, target }) { fulfil([]); - await thePromise; + await the_promise; assert.htmlEqual( target.innerHTML, diff --git a/packages/svelte/test/runtime/samples/binding-input-checkbox-with-event-in-each/_config.js b/packages/svelte/test/runtime/samples/binding-input-checkbox-with-event-in-each/_config.js index 85e78d35dc..fb5aa27b91 100644 --- a/packages/svelte/test/runtime/samples/binding-input-checkbox-with-event-in-each/_config.js +++ b/packages/svelte/test/runtime/samples/binding-input-checkbox-with-event-in-each/_config.js @@ -15,12 +15,12 @@ export default { test({ assert, component, target, window }) { const { cats } = component; - const newCats = cats.slice(); - newCats.push({ + const new_cats = cats.slice(); + new_cats.push({ name: 'cat ' + cats.length, checked: false }); - component.cats = newCats; + component.cats = new_cats; let inputs = target.querySelectorAll('input'); assert.equal(inputs.length, 3); diff --git a/packages/svelte/test/runtime/samples/binding-input-group-each-7/_config.js b/packages/svelte/test/runtime/samples/binding-input-group-each-7/_config.js index 7535001f67..3de0231f10 100644 --- a/packages/svelte/test/runtime/samples/binding-input-group-each-7/_config.js +++ b/packages/svelte/test/runtime/samples/binding-input-group-each-7/_config.js @@ -23,7 +23,7 @@ export default { async test({ assert, target, window }) { const inputs = target.querySelectorAll('input'); const checked = new Set(); - const checkInbox = async (i) => { + const check_inbox = async (i) => { checked.add(i); inputs[i].checked = true; await inputs[i].dispatchEvent(event); @@ -35,17 +35,17 @@ export default { const event = new window.Event('change'); - await checkInbox(2); + await check_inbox(2); for (let i = 0; i < 18; i++) { assert.equal(inputs[i].checked, checked.has(i)); } - await checkInbox(12); + await check_inbox(12); for (let i = 0; i < 18; i++) { assert.equal(inputs[i].checked, checked.has(i)); } - await checkInbox(8); + await check_inbox(8); for (let i = 0; i < 18; i++) { assert.equal(inputs[i].checked, checked.has(i)); } diff --git a/packages/svelte/test/runtime/samples/binding-input-group-if-gh-8372-1/_config.js b/packages/svelte/test/runtime/samples/binding-input-group-if-gh-8372-1/_config.js index bdc4da2d57..29d7b14bca 100644 --- a/packages/svelte/test/runtime/samples/binding-input-group-if-gh-8372-1/_config.js +++ b/packages/svelte/test/runtime/samples/binding-input-group-if-gh-8372-1/_config.js @@ -1,8 +1,8 @@ export default { async test({ assert, target, component, window }) { const button = target.querySelector('button'); - const clickEvent = new window.Event('click'); - const changeEvent = new window.Event('change'); + const click_event = new window.Event('click'); + const change_event = new window.Event('change'); const [input1, input2] = target.querySelectorAll('input[type="checkbox"]'); function validate_inputs(v1, v2) { @@ -17,24 +17,24 @@ export default { validate_inputs(true, true); input1.checked = false; - await input1.dispatchEvent(changeEvent); + await input1.dispatchEvent(change_event); assert.deepEqual(component.test, ['b']); input2.checked = false; - await input2.dispatchEvent(changeEvent); + await input2.dispatchEvent(change_event); assert.deepEqual(component.test, []); input1.checked = true; input2.checked = true; - await input1.dispatchEvent(changeEvent); - await input2.dispatchEvent(changeEvent); + await input1.dispatchEvent(change_event); + await input2.dispatchEvent(change_event); assert.deepEqual(component.test, ['b', 'a']); - await button.dispatchEvent(clickEvent); + await button.dispatchEvent(click_event); assert.deepEqual(component.test, ['b', 'a']); // should it be ['a'] only? valid arguments for both outcomes input1.checked = false; - await input1.dispatchEvent(changeEvent); + await input1.dispatchEvent(change_event); assert.deepEqual(component.test, []); } }; diff --git a/packages/svelte/test/runtime/samples/binding-input-group-if-gh-8372-2/_config.js b/packages/svelte/test/runtime/samples/binding-input-group-if-gh-8372-2/_config.js index a8d5a7137f..86f391496e 100644 --- a/packages/svelte/test/runtime/samples/binding-input-group-if-gh-8372-2/_config.js +++ b/packages/svelte/test/runtime/samples/binding-input-group-if-gh-8372-2/_config.js @@ -1,8 +1,8 @@ export default { async test({ assert, target, component, window }) { const button = target.querySelector('button'); - const clickEvent = new window.Event('click'); - const changeEvent = new window.Event('change'); + const click_event = new window.Event('click'); + const change_event = new window.Event('change'); const [input1, input2] = target.querySelectorAll('input[type="radio"]'); function validate_inputs(v1, v2) { @@ -17,18 +17,18 @@ export default { validate_inputs(false, true); input1.checked = true; - await input1.dispatchEvent(changeEvent); + await input1.dispatchEvent(change_event); assert.deepEqual(component.test, 'a'); input2.checked = true; - await input2.dispatchEvent(changeEvent); + await input2.dispatchEvent(change_event); assert.deepEqual(component.test, 'b'); - await button.dispatchEvent(clickEvent); + await button.dispatchEvent(click_event); assert.deepEqual(component.test, 'b'); // should it be undefined? valid arguments for both outcomes input1.checked = true; - await input1.dispatchEvent(changeEvent); + await input1.dispatchEvent(change_event); assert.deepEqual(component.test, 'a'); } }; diff --git a/packages/svelte/test/runtime/samples/binding-input-number-2/_config.js b/packages/svelte/test/runtime/samples/binding-input-number-2/_config.js index 4411eac0b2..d65df9b819 100644 --- a/packages/svelte/test/runtime/samples/binding-input-number-2/_config.js +++ b/packages/svelte/test/runtime/samples/binding-input-number-2/_config.js @@ -1,25 +1,25 @@ export default { test({ assert, target, window, component }) { const input = target.querySelector('input'); - const inputEvent = new window.InputEvent('input'); + const input_event = new window.InputEvent('input'); assert.equal(component.value, 5); assert.equal(input.value, '5'); input.value = '5.'; - input.dispatchEvent(inputEvent); + input.dispatchEvent(input_event); // input type number has value === "" if ends with dot/comma assert.equal(component.value, undefined); assert.equal(input.value, ''); input.value = '5.5'; - input.dispatchEvent(inputEvent); + input.dispatchEvent(input_event); assert.equal(component.value, 5.5); assert.equal(input.value, '5.5'); input.value = '5.50'; - input.dispatchEvent(inputEvent); + input.dispatchEvent(input_event); assert.equal(component.value, 5.5); assert.equal(input.value, '5.50'); diff --git a/packages/svelte/test/runtime/samples/comment-effect-on-reactivity/SomeComponent.svelte b/packages/svelte/test/runtime/samples/comment-effect-on-reactivity/SomeComponent.svelte new file mode 100644 index 0000000000..5c7f400318 --- /dev/null +++ b/packages/svelte/test/runtime/samples/comment-effect-on-reactivity/SomeComponent.svelte @@ -0,0 +1,20 @@ + + + + +{objectPropCopy} +
{count}
diff --git a/packages/svelte/test/runtime/samples/comment-effect-on-reactivity/_config.js b/packages/svelte/test/runtime/samples/comment-effect-on-reactivity/_config.js new file mode 100644 index 0000000000..d1b7d61dcc --- /dev/null +++ b/packages/svelte/test/runtime/samples/comment-effect-on-reactivity/_config.js @@ -0,0 +1,9 @@ +export default { + async test({ assert, target, window }) { + const incrementButton = target.querySelector('button'); + + assert.equal(target.querySelector('#render-count').innerHTML, '1'); + await incrementButton.dispatchEvent(new window.MouseEvent('click')); + assert.equal(target.querySelector('#render-count').innerHTML, '2'); + } +}; diff --git a/packages/svelte/test/runtime/samples/comment-effect-on-reactivity/main.svelte b/packages/svelte/test/runtime/samples/comment-effect-on-reactivity/main.svelte new file mode 100644 index 0000000000..6d1985392a --- /dev/null +++ b/packages/svelte/test/runtime/samples/comment-effect-on-reactivity/main.svelte @@ -0,0 +1,8 @@ + + + diff --git a/packages/svelte/test/runtime/samples/component-binding-deep-b/_config.js b/packages/svelte/test/runtime/samples/component-binding-deep-b/_config.js index 1b0e09f735..fea5ea4151 100644 --- a/packages/svelte/test/runtime/samples/component-binding-deep-b/_config.js +++ b/packages/svelte/test/runtime/samples/component-binding-deep-b/_config.js @@ -9,13 +9,13 @@ const components = [ } ]; -const selectedComponent = components[0]; +const selected_component = components[0]; export default { skip: true, // doesn't reflect real-world bug, maybe a JSDOM quirk get props() { - return { components, selectedComponent }; + return { components, selectedComponent: selected_component }; }, html: ` diff --git a/packages/svelte/test/runtime/samples/component-event-handler-dynamic/_config.js b/packages/svelte/test/runtime/samples/component-event-handler-dynamic/_config.js index 415b860828..775899740e 100644 --- a/packages/svelte/test/runtime/samples/component-event-handler-dynamic/_config.js +++ b/packages/svelte/test/runtime/samples/component-event-handler-dynamic/_config.js @@ -5,13 +5,13 @@ export default { `, async test({ assert, component, target, window }) { - const [updateButton, button] = target.querySelectorAll('button'); + const [update_button, button] = target.querySelectorAll('button'); const event = new window.MouseEvent('click'); await button.dispatchEvent(event); assert.equal(component.count, 1); - await updateButton.dispatchEvent(event); + await update_button.dispatchEvent(event); await button.dispatchEvent(event); assert.equal(component.count, 11); } diff --git a/packages/svelte/test/runtime/samples/component-event-handler-modifier-once-dynamic/_config.js b/packages/svelte/test/runtime/samples/component-event-handler-modifier-once-dynamic/_config.js index 8796e0faf6..47b6c07edc 100644 --- a/packages/svelte/test/runtime/samples/component-event-handler-modifier-once-dynamic/_config.js +++ b/packages/svelte/test/runtime/samples/component-event-handler-modifier-once-dynamic/_config.js @@ -5,10 +5,10 @@ export default { `, async test({ assert, component, target, window }) { - const [updateButton, button] = target.querySelectorAll('button'); + const [update_button, button] = target.querySelectorAll('button'); const event = new window.MouseEvent('click'); - await updateButton.dispatchEvent(event); + await update_button.dispatchEvent(event); await button.dispatchEvent(event); assert.equal(component.count, 10); diff --git a/packages/svelte/test/runtime/samples/component-slot-fallback-2/_config.js b/packages/svelte/test/runtime/samples/component-slot-fallback-2/_config.js index 7c86357a8e..67e464818b 100644 --- a/packages/svelte/test/runtime/samples/component-slot-fallback-2/_config.js +++ b/packages/svelte/test/runtime/samples/component-slot-fallback-2/_config.js @@ -3,7 +3,7 @@ export default { ssrHtml: ' ', async test({ assert, target, component, window }) { - const [input1, input2, inputFallback] = target.querySelectorAll('input'); + const [input1, input2, input_fallback] = target.querySelectorAll('input'); assert.equal(component.getSubscriberCount(), 3); @@ -13,7 +13,7 @@ export default { await input1.dispatchEvent(new window.Event('input')); assert.equal(input1.value, 'ab'); assert.equal(input2.value, 'ab'); - assert.equal(inputFallback.value, 'ab'); + assert.equal(input_fallback.value, 'ab'); component.props = 'hello'; diff --git a/packages/svelte/test/runtime/samples/component-slot-fallback-5/_config.js b/packages/svelte/test/runtime/samples/component-slot-fallback-5/_config.js index 07d09a3be9..1463dcb560 100644 --- a/packages/svelte/test/runtime/samples/component-slot-fallback-5/_config.js +++ b/packages/svelte/test/runtime/samples/component-slot-fallback-5/_config.js @@ -6,9 +6,9 @@ export default { async test({ assert, target, window }) { const btn = target.querySelector('button'); - const clickEvent = new window.MouseEvent('click'); + const click_event = new window.MouseEvent('click'); - await btn.dispatchEvent(clickEvent); + await btn.dispatchEvent(click_event); assert.htmlEqual( target.innerHTML, @@ -18,7 +18,7 @@ export default { ` ); - await btn.dispatchEvent(clickEvent); + await btn.dispatchEvent(click_event); assert.htmlEqual( target.innerHTML, diff --git a/packages/svelte/test/runtime/samples/dynamic-element-animation-2/_config.js b/packages/svelte/test/runtime/samples/dynamic-element-animation-2/_config.js index d8399cac37..306b282f7a 100644 --- a/packages/svelte/test/runtime/samples/dynamic-element-animation-2/_config.js +++ b/packages/svelte/test/runtime/samples/dynamic-element-animation-2/_config.js @@ -1,6 +1,6 @@ -let originalDivGetBoundingClientRect; -let originalSpanGetBoundingClientRect; -let originalParagraphGetBoundingClientRect; +let original_div_get_bounding_client_rect; +let original_span_get_bounding_client_rect; +let original_paragraph_get_bounding_client_rect; export default { skip_if_ssr: true, @@ -26,16 +26,16 @@ export default { `, before_test() { - originalDivGetBoundingClientRect = window.HTMLDivElement.prototype.getBoundingClientRect; - originalSpanGetBoundingClientRect = window.HTMLSpanElement.prototype.getBoundingClientRect; - originalParagraphGetBoundingClientRect = + original_div_get_bounding_client_rect = window.HTMLDivElement.prototype.getBoundingClientRect; + original_span_get_bounding_client_rect = window.HTMLSpanElement.prototype.getBoundingClientRect; + original_paragraph_get_bounding_client_rect = window.HTMLParagraphElement.prototype.getBoundingClientRect; - window.HTMLDivElement.prototype.getBoundingClientRect = fakeGetBoundingClientRect; - window.HTMLSpanElement.prototype.getBoundingClientRect = fakeGetBoundingClientRect; - window.HTMLParagraphElement.prototype.getBoundingClientRect = fakeGetBoundingClientRect; + window.HTMLDivElement.prototype.getBoundingClientRect = fake_get_bounding_client_rect; + window.HTMLSpanElement.prototype.getBoundingClientRect = fake_get_bounding_client_rect; + window.HTMLParagraphElement.prototype.getBoundingClientRect = fake_get_bounding_client_rect; - function fakeGetBoundingClientRect() { + function fake_get_bounding_client_rect() { const index = [...this.parentNode.children].indexOf(this); const top = index * 30; @@ -48,10 +48,10 @@ export default { } }, after_test() { - window.HTMLDivElement.prototype.getBoundingClientRect = originalDivGetBoundingClientRect; - window.HTMLSpanElement.prototype.getBoundingClientRect = originalSpanGetBoundingClientRect; + window.HTMLDivElement.prototype.getBoundingClientRect = original_div_get_bounding_client_rect; + window.HTMLSpanElement.prototype.getBoundingClientRect = original_span_get_bounding_client_rect; window.HTMLParagraphElement.prototype.getBoundingClientRect = - originalParagraphGetBoundingClientRect; + original_paragraph_get_bounding_client_rect; }, async test({ assert, component, raf }) { diff --git a/packages/svelte/test/runtime/samples/dynamic-element-spread-attributes/_config.js b/packages/svelte/test/runtime/samples/dynamic-element-spread-attributes/_config.js new file mode 100644 index 0000000000..2ab9f47c00 --- /dev/null +++ b/packages/svelte/test/runtime/samples/dynamic-element-spread-attributes/_config.js @@ -0,0 +1,3 @@ +export default { + html: '
this is div
' +}; diff --git a/packages/svelte/test/runtime/samples/dynamic-element-spread-attributes/main.svelte b/packages/svelte/test/runtime/samples/dynamic-element-spread-attributes/main.svelte new file mode 100644 index 0000000000..b2ab251dfa --- /dev/null +++ b/packages/svelte/test/runtime/samples/dynamic-element-spread-attributes/main.svelte @@ -0,0 +1,7 @@ + +this is div diff --git a/packages/svelte/test/runtime/samples/each-block-destructured-default-binding/_config.js b/packages/svelte/test/runtime/samples/each-block-destructured-default-binding/_config.js index 2ba27bff03..a27d56a306 100644 --- a/packages/svelte/test/runtime/samples/each-block-destructured-default-binding/_config.js +++ b/packages/svelte/test/runtime/samples/each-block-destructured-default-binding/_config.js @@ -13,10 +13,10 @@ export default { assert.equal(input1.value, ''); assert.equal(input2.value, 'hello'); - const inputEvent = new window.InputEvent('input'); + const input_event = new window.InputEvent('input'); input2.value = 'world'; - input2.dispatchEvent(inputEvent); + input2.dispatchEvent(input_event); assert.equal(input2.value, 'world'); assert.equal(component.array[1].value, 'world'); } diff --git a/packages/svelte/test/runtime/samples/each-block-keyed-random-permute/_config.js b/packages/svelte/test/runtime/samples/each-block-keyed-random-permute/_config.js index 454ef48d0f..4fcea8d68f 100644 --- a/packages/svelte/test/runtime/samples/each-block-keyed-random-permute/_config.js +++ b/packages/svelte/test/runtime/samples/each-block-keyed-random-permute/_config.js @@ -1,6 +1,6 @@ const VALUES = Array.from('abcdefghijklmnopqrstuvwxyz'); -function toObjects(array) { +function to_objects(array) { return array.split('').map((x) => ({ id: x })); } @@ -17,7 +17,7 @@ function permute() { export default { get props() { - return { values: toObjects('abc') }; + return { values: to_objects('abc') }; }, html: '(a)(b)(c)', @@ -29,7 +29,7 @@ export default { .split('') .map((x) => `(${x})`) .join(''); - component.values = toObjects(sequence); + component.values = to_objects(sequence); assert.htmlEqual( target.innerHTML, expected, diff --git a/packages/svelte/test/runtime/samples/each-blocks-assignment-2/_config.js b/packages/svelte/test/runtime/samples/each-blocks-assignment-2/_config.js index 93f06956d0..4f62f6b66b 100644 --- a/packages/svelte/test/runtime/samples/each-blocks-assignment-2/_config.js +++ b/packages/svelte/test/runtime/samples/each-blocks-assignment-2/_config.js @@ -6,8 +6,8 @@ export default { async test({ assert, target, window }) { const button = target.querySelector('button'); - const clickEvent = new window.MouseEvent('click'); - await button.dispatchEvent(clickEvent); + const click_event = new window.MouseEvent('click'); + await button.dispatchEvent(click_event); assert.htmlEqual( target.innerHTML, diff --git a/packages/svelte/test/runtime/samples/each-blocks-assignment/_config.js b/packages/svelte/test/runtime/samples/each-blocks-assignment/_config.js index 5e22381e9e..11591cf026 100644 --- a/packages/svelte/test/runtime/samples/each-blocks-assignment/_config.js +++ b/packages/svelte/test/runtime/samples/each-blocks-assignment/_config.js @@ -9,10 +9,10 @@ export default { `, async test({ assert, target, window }) { - let [incrementBtn, ...buttons] = target.querySelectorAll('button'); + let [increment_btn, ...buttons] = target.querySelectorAll('button'); - const clickEvent = new window.MouseEvent('click'); - await buttons[0].dispatchEvent(clickEvent); + const click_event = new window.MouseEvent('click'); + await buttons[0].dispatchEvent(click_event); assert.htmlEqual( target.innerHTML, @@ -27,7 +27,7 @@ export default { ` ); - await buttons[0].dispatchEvent(clickEvent); + await buttons[0].dispatchEvent(click_event); assert.htmlEqual( target.innerHTML, @@ -42,8 +42,8 @@ export default { ` ); - await buttons[2].dispatchEvent(clickEvent); - await buttons[2].dispatchEvent(clickEvent); + await buttons[2].dispatchEvent(click_event); + await buttons[2].dispatchEvent(click_event); assert.htmlEqual( target.innerHTML, @@ -58,7 +58,7 @@ export default { ` ); - await incrementBtn.dispatchEvent(clickEvent); + await increment_btn.dispatchEvent(click_event); assert.htmlEqual( target.innerHTML, @@ -75,9 +75,9 @@ export default { ` ); - [incrementBtn, ...buttons] = target.querySelectorAll('button'); + [increment_btn, ...buttons] = target.querySelectorAll('button'); - await buttons[3].dispatchEvent(clickEvent); + await buttons[3].dispatchEvent(click_event); assert.htmlEqual( target.innerHTML, diff --git a/packages/svelte/test/runtime/samples/event-handler-dynamic-hash/_config.js b/packages/svelte/test/runtime/samples/event-handler-dynamic-hash/_config.js index 44990524fd..db34d02d12 100644 --- a/packages/svelte/test/runtime/samples/event-handler-dynamic-hash/_config.js +++ b/packages/svelte/test/runtime/samples/event-handler-dynamic-hash/_config.js @@ -9,7 +9,7 @@ export default { `, async test({ assert, target, window }) { - const [updateButton1, updateButton2, button] = target.querySelectorAll('button'); + const [update_button1, update_button2, button] = target.querySelectorAll('button'); const event = new window.MouseEvent('click'); let err = ''; @@ -32,7 +32,7 @@ export default { ` ); - await updateButton1.dispatchEvent(event); + await update_button1.dispatchEvent(event); await button.dispatchEvent(event); assert.htmlEqual( target.innerHTML, @@ -46,7 +46,7 @@ export default { ` ); - await updateButton2.dispatchEvent(event); + await update_button2.dispatchEvent(event); await button.dispatchEvent(event); assert.htmlEqual( target.innerHTML, diff --git a/packages/svelte/test/runtime/samples/event-handler-dynamic-invalid/_config.js b/packages/svelte/test/runtime/samples/event-handler-dynamic-invalid/_config.js index cac6d60f2e..6043d2ba28 100644 --- a/packages/svelte/test/runtime/samples/event-handler-dynamic-invalid/_config.js +++ b/packages/svelte/test/runtime/samples/event-handler-dynamic-invalid/_config.js @@ -4,7 +4,7 @@ export default { `, async test({ assert, target, window }) { - const [buttonUndef, buttonNull, buttonInvalid] = target.querySelectorAll('button'); + const [button_undef, button_null, button_invalid] = target.querySelectorAll('button'); const event = new window.MouseEvent('click'); let err = ''; @@ -14,13 +14,13 @@ export default { }); // All three should not throw if proper checking is done in runtime code - await buttonUndef.dispatchEvent(event); + await button_undef.dispatchEvent(event); assert.equal(err, '', err); - await buttonNull.dispatchEvent(event); + await button_null.dispatchEvent(event); assert.equal(err, '', err); - await buttonInvalid.dispatchEvent(event); + await button_invalid.dispatchEvent(event); assert.equal(err, '', err); } }; diff --git a/packages/svelte/test/runtime/samples/event-handler-dynamic/_config.js b/packages/svelte/test/runtime/samples/event-handler-dynamic/_config.js index 44990524fd..db34d02d12 100644 --- a/packages/svelte/test/runtime/samples/event-handler-dynamic/_config.js +++ b/packages/svelte/test/runtime/samples/event-handler-dynamic/_config.js @@ -9,7 +9,7 @@ export default { `, async test({ assert, target, window }) { - const [updateButton1, updateButton2, button] = target.querySelectorAll('button'); + const [update_button1, update_button2, button] = target.querySelectorAll('button'); const event = new window.MouseEvent('click'); let err = ''; @@ -32,7 +32,7 @@ export default { ` ); - await updateButton1.dispatchEvent(event); + await update_button1.dispatchEvent(event); await button.dispatchEvent(event); assert.htmlEqual( target.innerHTML, @@ -46,7 +46,7 @@ export default { ` ); - await updateButton2.dispatchEvent(event); + await update_button2.dispatchEvent(event); await button.dispatchEvent(event); assert.htmlEqual( target.innerHTML, diff --git a/packages/svelte/test/runtime/samples/event-handler-each-modifier/_config.js b/packages/svelte/test/runtime/samples/event-handler-each-modifier/_config.js index e96cd1a987..72da7a8537 100644 --- a/packages/svelte/test/runtime/samples/event-handler-each-modifier/_config.js +++ b/packages/svelte/test/runtime/samples/event-handler-each-modifier/_config.js @@ -10,21 +10,21 @@ export default { assert.equal(component.updated, 4); const [item1, item2] = target.childNodes; - const [item1Btn1, item1Btn2] = item1.querySelectorAll('button'); - const [item2Btn1, item2Btn2] = item2.querySelectorAll('button'); + const [item1_btn1, item1_btn2] = item1.querySelectorAll('button'); + const [item2_btn1, item2_btn2] = item2.querySelectorAll('button'); - const clickEvent = new window.MouseEvent('click'); + const click_event = new window.MouseEvent('click'); - await item1Btn1.dispatchEvent(clickEvent); + await item1_btn1.dispatchEvent(click_event); assert.equal(component.getNormalCount(), 1); - await item1Btn2.dispatchEvent(clickEvent); + await item1_btn2.dispatchEvent(click_event); assert.equal(component.getModifierCount(), 1); - await item2Btn1.dispatchEvent(clickEvent); + await item2_btn1.dispatchEvent(click_event); assert.equal(component.getNormalCount(), 2); - await item2Btn2.dispatchEvent(clickEvent); + await item2_btn2.dispatchEvent(click_event); assert.equal(component.getModifierCount(), 2); } }; diff --git a/packages/svelte/test/runtime/samples/flush-before-bindings/_config.js b/packages/svelte/test/runtime/samples/flush-before-bindings/_config.js index 4f20299771..6848fbd50c 100644 --- a/packages/svelte/test/runtime/samples/flush-before-bindings/_config.js +++ b/packages/svelte/test/runtime/samples/flush-before-bindings/_config.js @@ -11,11 +11,11 @@ export default { `, test({ assert, component }) { - const visibleThings = component.visibleThings; - assert.deepEqual(visibleThings, ['first thing', 'second thing']); + const visible_things = component.visibleThings; + assert.deepEqual(visible_things, ['first thing', 'second thing']); const snapshots = component.snapshots; - assert.deepEqual(snapshots, [visibleThings]); + assert.deepEqual(snapshots, [visible_things]); // TODO minimise the number of recomputations during oncreate // assert.equal(counter.count, 1); diff --git a/packages/svelte/test/runtime/samples/fragment-trailing-whitespace/_config.js b/packages/svelte/test/runtime/samples/fragment-trailing-whitespace/_config.js index d2c59af0de..142cab9229 100644 --- a/packages/svelte/test/runtime/samples/fragment-trailing-whitespace/_config.js +++ b/packages/svelte/test/runtime/samples/fragment-trailing-whitespace/_config.js @@ -7,10 +7,14 @@ export default { }, async test({ assert, target }) { - const firstSpanList = target.children[0]; - assert.htmlEqualWithOptions(firstSpanList.innerHTML, expected, { withoutNormalizeHtml: true }); + const first_span_list = target.children[0]; + assert.htmlEqualWithOptions(first_span_list.innerHTML, expected, { + withoutNormalizeHtml: true + }); - const secondSpanList = target.children[1]; - assert.htmlEqualWithOptions(secondSpanList.innerHTML, expected, { withoutNormalizeHtml: true }); + const second_span_list = target.children[1]; + assert.htmlEqualWithOptions(second_span_list.innerHTML, expected, { + withoutNormalizeHtml: true + }); } }; diff --git a/packages/svelte/test/runtime/samples/if-block-else-update/_config.js b/packages/svelte/test/runtime/samples/if-block-else-update/_config.js index 3ba36906ad..cbbf65aa2c 100644 --- a/packages/svelte/test/runtime/samples/if-block-else-update/_config.js +++ b/packages/svelte/test/runtime/samples/if-block-else-update/_config.js @@ -2,9 +2,9 @@ export default { async test({ assert, target, window }) { const [btn1, btn2] = target.querySelectorAll('button'); - const clickEvent = new window.MouseEvent('click'); + const click_event = new window.MouseEvent('click'); - await btn2.dispatchEvent(clickEvent); + await btn2.dispatchEvent(click_event); assert.htmlEqual( target.innerHTML, ` @@ -17,7 +17,7 @@ export default { ` ); - await btn1.dispatchEvent(clickEvent); + await btn1.dispatchEvent(click_event); assert.htmlEqual( target.innerHTML, ` @@ -30,7 +30,7 @@ export default { ` ); - await btn2.dispatchEvent(clickEvent); + await btn2.dispatchEvent(click_event); assert.htmlEqual( target.innerHTML, ` @@ -43,7 +43,7 @@ export default { ` ); - await btn1.dispatchEvent(clickEvent); + await btn1.dispatchEvent(click_event); assert.htmlEqual( target.innerHTML, ` diff --git a/packages/svelte/test/runtime/samples/inline-style-directive-update-object-property/_config.js b/packages/svelte/test/runtime/samples/inline-style-directive-update-object-property/_config.js new file mode 100644 index 0000000000..e3c6d72cd1 --- /dev/null +++ b/packages/svelte/test/runtime/samples/inline-style-directive-update-object-property/_config.js @@ -0,0 +1,20 @@ +export default { + html: ` +

+ `, + + test({ assert, target, window, component }) { + const p = target.querySelector('p'); + const styles = window.getComputedStyle(p); + assert.equal(styles.backgroundColor, 'green'); + assert.equal(styles.fontSize, '12px'); + + { + component.modify = true; + const p = target.querySelector('p'); + const styles = window.getComputedStyle(p); + assert.equal(styles.backgroundColor, 'green'); + assert.equal(styles.fontSize, '50px'); + } + } +}; diff --git a/packages/svelte/test/runtime/samples/inline-style-directive-update-object-property/main.svelte b/packages/svelte/test/runtime/samples/inline-style-directive-update-object-property/main.svelte new file mode 100644 index 0000000000..0a643bdf48 --- /dev/null +++ b/packages/svelte/test/runtime/samples/inline-style-directive-update-object-property/main.svelte @@ -0,0 +1,12 @@ + + +

diff --git a/packages/svelte/test/runtime/samples/nbsp-div/_config.js b/packages/svelte/test/runtime/samples/nbsp-div/_config.js index 5489360934..d79db8ee81 100644 --- a/packages/svelte/test/runtime/samples/nbsp-div/_config.js +++ b/packages/svelte/test/runtime/samples/nbsp-div/_config.js @@ -4,14 +4,14 @@ export default {

 hello   hello
`, test({ assert, target }) { - const divList = target.querySelectorAll('div'); - assert.equal(divList[0].textContent.charCodeAt(0), 160); - assert.equal(divList[1].textContent.charCodeAt(0), 160); - assert.equal(divList[1].textContent.charCodeAt(6), 160); - assert.equal(divList[1].textContent.charCodeAt(7), 160); - assert.equal(divList[2].textContent.charCodeAt(0), 160); - assert.equal(divList[2].textContent.charCodeAt(6), 160); - assert.equal(divList[2].textContent.charCodeAt(7), 32); //normal space - assert.equal(divList[2].textContent.charCodeAt(8), 160); + const div_list = target.querySelectorAll('div'); + assert.equal(div_list[0].textContent.charCodeAt(0), 160); + assert.equal(div_list[1].textContent.charCodeAt(0), 160); + assert.equal(div_list[1].textContent.charCodeAt(6), 160); + assert.equal(div_list[1].textContent.charCodeAt(7), 160); + assert.equal(div_list[2].textContent.charCodeAt(0), 160); + assert.equal(div_list[2].textContent.charCodeAt(6), 160); + assert.equal(div_list[2].textContent.charCodeAt(7), 32); //normal space + assert.equal(div_list[2].textContent.charCodeAt(8), 160); } }; diff --git a/packages/svelte/test/runtime/samples/noscript-removal/_config.js b/packages/svelte/test/runtime/samples/noscript-removal/_config.js index a60a4f87b0..69dea81cbd 100644 --- a/packages/svelte/test/runtime/samples/noscript-removal/_config.js +++ b/packages/svelte/test/runtime/samples/noscript-removal/_config.js @@ -14,7 +14,7 @@ export default { // it's okay not to remove the node during hydration // will not be seen by user anyway - removeNoScript(target); + remove_no_script(target); assert.htmlEqual( target.innerHTML, @@ -26,7 +26,7 @@ export default { } }; -function removeNoScript(target) { +function remove_no_script(target) { target.querySelectorAll('noscript').forEach((elem) => { elem.parentNode.removeChild(elem); }); diff --git a/packages/svelte/test/runtime/samples/props-reactive-slot/_config.js b/packages/svelte/test/runtime/samples/props-reactive-slot/_config.js index 6129866605..47effe0d82 100644 --- a/packages/svelte/test/runtime/samples/props-reactive-slot/_config.js +++ b/packages/svelte/test/runtime/samples/props-reactive-slot/_config.js @@ -6,9 +6,9 @@ export default { async test({ assert, target, window }) { const btn = target.querySelector('button'); - const clickEvent = new window.MouseEvent('click'); + const click_event = new window.MouseEvent('click'); - await btn.dispatchEvent(clickEvent); + await btn.dispatchEvent(click_event); assert.htmlEqual( target.innerHTML, diff --git a/packages/svelte/test/runtime/samples/raw-mustache-as-root/_config.js b/packages/svelte/test/runtime/samples/raw-mustache-as-root/_config.js index a38c0b1c81..2f54fd6ab9 100644 --- a/packages/svelte/test/runtime/samples/raw-mustache-as-root/_config.js +++ b/packages/svelte/test/runtime/samples/raw-mustache-as-root/_config.js @@ -6,9 +6,9 @@ export default { `, async test({ assert, target, window }) { const btn = target.querySelector('button'); - const clickEvent = new window.MouseEvent('click'); + const click_event = new window.MouseEvent('click'); - await btn.dispatchEvent(clickEvent); + await btn.dispatchEvent(click_event); assert.htmlEqual( target.innerHTML, @@ -19,7 +19,7 @@ export default { ` ); - await btn.dispatchEvent(clickEvent); + await btn.dispatchEvent(click_event); assert.htmlEqual( target.innerHTML, diff --git a/packages/svelte/test/runtime/samples/raw-mustache-inside-head/_config.js b/packages/svelte/test/runtime/samples/raw-mustache-inside-head/_config.js index f478d186be..eb0df14136 100644 --- a/packages/svelte/test/runtime/samples/raw-mustache-inside-head/_config.js +++ b/packages/svelte/test/runtime/samples/raw-mustache-inside-head/_config.js @@ -1,7 +1,7 @@ export default { async test({ assert, target, window }) { const btn = target.querySelector('button'); - const clickEvent = new window.MouseEvent('click'); + const click_event = new window.MouseEvent('click'); assert.equal( window.document.head.innerHTML.includes( @@ -10,7 +10,7 @@ export default { true ); - await btn.dispatchEvent(clickEvent); + await btn.dispatchEvent(click_event); assert.equal( window.document.head.innerHTML.includes( @@ -19,7 +19,7 @@ export default { true ); - await btn.dispatchEvent(clickEvent); + await btn.dispatchEvent(click_event); assert.equal( window.document.head.innerHTML.includes( diff --git a/packages/svelte/test/runtime/samples/raw-mustache-inside-slot/_config.js b/packages/svelte/test/runtime/samples/raw-mustache-inside-slot/_config.js index a38c0b1c81..2f54fd6ab9 100644 --- a/packages/svelte/test/runtime/samples/raw-mustache-inside-slot/_config.js +++ b/packages/svelte/test/runtime/samples/raw-mustache-inside-slot/_config.js @@ -6,9 +6,9 @@ export default { `, async test({ assert, target, window }) { const btn = target.querySelector('button'); - const clickEvent = new window.MouseEvent('click'); + const click_event = new window.MouseEvent('click'); - await btn.dispatchEvent(clickEvent); + await btn.dispatchEvent(click_event); assert.htmlEqual( target.innerHTML, @@ -19,7 +19,7 @@ export default { ` ); - await btn.dispatchEvent(clickEvent); + await btn.dispatchEvent(click_event); assert.htmlEqual( target.innerHTML, diff --git a/packages/svelte/test/runtime/samples/reactive-import-statement/_config.js b/packages/svelte/test/runtime/samples/reactive-import-statement/_config.js index 1160919839..59856dca94 100644 --- a/packages/svelte/test/runtime/samples/reactive-import-statement/_config.js +++ b/packages/svelte/test/runtime/samples/reactive-import-statement/_config.js @@ -13,9 +13,9 @@ export default { }, async test({ assert, target, window }) { const btn = target.querySelector('button'); - const clickEvent = new window.MouseEvent('click'); + const click_event = new window.MouseEvent('click'); - await btn.dispatchEvent(clickEvent); + await btn.dispatchEvent(click_event); assert.htmlEqual( target.innerHTML, @@ -28,7 +28,7 @@ export default { ` ); - await btn.dispatchEvent(clickEvent); + await btn.dispatchEvent(click_event); assert.htmlEqual( target.innerHTML, diff --git a/packages/svelte/test/runtime/samples/select-options-spread-attributes/_config.js b/packages/svelte/test/runtime/samples/select-options-spread-attributes/_config.js new file mode 100644 index 0000000000..be4faba612 --- /dev/null +++ b/packages/svelte/test/runtime/samples/select-options-spread-attributes/_config.js @@ -0,0 +1,7 @@ +export default { + html: ` + + ` +}; diff --git a/packages/svelte/test/runtime/samples/select-options-spread-attributes/main.svelte b/packages/svelte/test/runtime/samples/select-options-spread-attributes/main.svelte new file mode 100644 index 0000000000..cabaf2ea0a --- /dev/null +++ b/packages/svelte/test/runtime/samples/select-options-spread-attributes/main.svelte @@ -0,0 +1,3 @@ + diff --git a/packages/svelte/test/runtime/samples/spread-element-input-value/_config.js b/packages/svelte/test/runtime/samples/spread-element-input-value/_config.js index 64ae0fe469..c09bf7e7fa 100644 --- a/packages/svelte/test/runtime/samples/spread-element-input-value/_config.js +++ b/packages/svelte/test/runtime/samples/spread-element-input-value/_config.js @@ -11,8 +11,8 @@ export default { // and we determine if svelte does not set the `input.value` again by // spying on the setter of `input.value` - const spy1 = spyOnValueSetter(input1, input1.value); - const spy2 = spyOnValueSetter(input2, input2.value); + const spy1 = spy_on_value_setter(input1, input1.value); + const spy2 = spy_on_value_setter(input2, input2.value); const event = new window.Event('input'); @@ -38,25 +38,25 @@ export default { } }; -function spyOnValueSetter(input, initialValue) { - let value = initialValue; - let isSet = false; +function spy_on_value_setter(input, initial_value) { + let value = initial_value; + let is_set = false; Object.defineProperty(input, 'value', { get() { return value; }, set(_value) { value = _value; - isSet = true; + is_set = true; } }); return { isSetCalled() { - return isSet; + return is_set; }, reset() { - isSet = false; + is_set = false; } }; } diff --git a/packages/svelte/test/runtime/samples/spread-element-input-value/utils.js b/packages/svelte/test/runtime/samples/spread-element-input-value/utils.js index ee941bda55..2fc48fe6ae 100644 --- a/packages/svelte/test/runtime/samples/spread-element-input-value/utils.js +++ b/packages/svelte/test/runtime/samples/spread-element-input-value/utils.js @@ -1,6 +1,6 @@ -export function omit(obj, ...keysToOmit) { +export function omit(obj, ...keys_to_omit) { return Object.keys(obj).reduce((acc, key) => { - if (keysToOmit.indexOf(key) === -1) acc[key] = obj[key]; + if (keys_to_omit.indexOf(key) === -1) acc[key] = obj[key]; return acc; }, {}); } diff --git a/packages/svelte/test/runtime/samples/store-auto-subscribe-event-callback/_config.js b/packages/svelte/test/runtime/samples/store-auto-subscribe-event-callback/_config.js index 58b1740f0f..ba0556644d 100644 --- a/packages/svelte/test/runtime/samples/store-auto-subscribe-event-callback/_config.js +++ b/packages/svelte/test/runtime/samples/store-auto-subscribe-event-callback/_config.js @@ -9,9 +9,9 @@ export default { const input = target.querySelector('input'); input.value = 'foo'; - const inputEvent = new window.InputEvent('input'); + const input_event = new window.InputEvent('input'); - await input.dispatchEvent(inputEvent); + await input.dispatchEvent(input_event); assert.htmlEqual( target.innerHTML, diff --git a/packages/svelte/test/runtime/samples/store-invalidation-while-update-1/_config.js b/packages/svelte/test/runtime/samples/store-invalidation-while-update-1/_config.js index eaa5b3c92b..00e41c98d7 100644 --- a/packages/svelte/test/runtime/samples/store-invalidation-while-update-1/_config.js +++ b/packages/svelte/test/runtime/samples/store-invalidation-while-update-1/_config.js @@ -16,11 +16,11 @@ export default { const input = target.querySelector('input'); const button = target.querySelector('button'); - const inputEvent = new window.InputEvent('input'); - const clickEvent = new window.MouseEvent('click'); + const input_event = new window.InputEvent('input'); + const click_event = new window.MouseEvent('click'); input.value = 'foo'; - await input.dispatchEvent(inputEvent); + await input.dispatchEvent(input_event); assert.htmlEqual( target.innerHTML, @@ -32,7 +32,7 @@ export default { ` ); - await button.dispatchEvent(clickEvent); + await button.dispatchEvent(click_event); assert.htmlEqual( target.innerHTML, ` @@ -44,7 +44,7 @@ export default { ); input.value = 'bar'; - await input.dispatchEvent(inputEvent); + await input.dispatchEvent(input_event); assert.htmlEqual( target.innerHTML, diff --git a/packages/svelte/test/runtime/samples/store-invalidation-while-update-2/_config.js b/packages/svelte/test/runtime/samples/store-invalidation-while-update-2/_config.js index 8c318b0faf..882eb46931 100644 --- a/packages/svelte/test/runtime/samples/store-invalidation-while-update-2/_config.js +++ b/packages/svelte/test/runtime/samples/store-invalidation-while-update-2/_config.js @@ -16,11 +16,11 @@ export default { const input = target.querySelector('input'); const button = target.querySelector('button'); - const inputEvent = new window.InputEvent('input'); - const clickEvent = new window.MouseEvent('click'); + const input_event = new window.InputEvent('input'); + const click_event = new window.MouseEvent('click'); input.value = 'foo'; - await input.dispatchEvent(inputEvent); + await input.dispatchEvent(input_event); assert.htmlEqual( target.innerHTML, @@ -32,7 +32,7 @@ export default { ` ); - await button.dispatchEvent(clickEvent); + await button.dispatchEvent(click_event); assert.htmlEqual( target.innerHTML, ` @@ -44,7 +44,7 @@ export default { ); input.value = 'bar'; - await input.dispatchEvent(inputEvent); + await input.dispatchEvent(input_event); assert.htmlEqual( target.innerHTML, diff --git a/packages/svelte/test/runtime/samples/store-resubscribe-export/_config.js b/packages/svelte/test/runtime/samples/store-resubscribe-export/_config.js index b4615a27d1..44c0fb2403 100644 --- a/packages/svelte/test/runtime/samples/store-resubscribe-export/_config.js +++ b/packages/svelte/test/runtime/samples/store-resubscribe-export/_config.js @@ -1,11 +1,11 @@ -let unsubscribeCalled = false; +let unsubscribe_called = false; -const fakeStore = (val) => ({ +const fake_store = (val) => ({ subscribe: (cb) => { cb(val); return { unsubscribe: () => { - unsubscribeCalled = true; + unsubscribe_called = true; } }; } @@ -13,17 +13,17 @@ const fakeStore = (val) => ({ export default { get props() { - return { foo: fakeStore(1) }; + return { foo: fake_store(1) }; }, html: `

1

`, async test({ assert, component, target }) { - component.foo = fakeStore(5); + component.foo = fake_store(5); assert.htmlEqual(target.innerHTML, '

5

'); - assert.ok(unsubscribeCalled); + assert.ok(unsubscribe_called); } }; diff --git a/packages/svelte/test/runtime/samples/svg-foreignobject-namespace/_config.js b/packages/svelte/test/runtime/samples/svg-foreignobject-namespace/_config.js index 950e35e79d..05a7d7d8ec 100644 --- a/packages/svelte/test/runtime/samples/svg-foreignobject-namespace/_config.js +++ b/packages/svelte/test/runtime/samples/svg-foreignobject-namespace/_config.js @@ -8,8 +8,8 @@ export default { `, test({ assert, target }) { - const foreignObject = target.querySelector('foreignObject'); - assert.equal(foreignObject.namespaceURI, 'http://www.w3.org/2000/svg'); + const foreign_object = target.querySelector('foreignObject'); + assert.equal(foreign_object.namespaceURI, 'http://www.w3.org/2000/svg'); const p = target.querySelector('p'); assert.equal(p.namespaceURI, 'http://www.w3.org/1999/xhtml'); diff --git a/packages/svelte/test/runtime/samples/textarea-content/_config.js b/packages/svelte/test/runtime/samples/textarea-content/_config.js index 7d4f8f9493..fd04d5acbe 100644 --- a/packages/svelte/test/runtime/samples/textarea-content/_config.js +++ b/packages/svelte/test/runtime/samples/textarea-content/_config.js @@ -18,50 +18,53 @@ multiple leading newlines