diff --git a/.eslintignore b/.eslintignore index a0ca1e55c8..b5cb03ae6e 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,8 +1,12 @@ **/_actual.js **/expected.js +_output test/*/samples/*/output.js node_modules +# automatically generated +internal_exports.ts + # output files animate/*.js esing/*.js diff --git a/.eslintrc.js b/.eslintrc.js index 2c7f2ed1b4..946a157e40 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -22,14 +22,7 @@ module.exports = { 'arrow-spacing': 2, 'no-inner-declarations': 0, 'require-atomic-updates': 'off', - '@typescript-eslint/indent': [ - 'error', - 'tab', - { - SwitchCase: 1, - ignoredNodes: ['TemplateLiteral'] - } - ], + '@typescript-eslint/indent': 'off', '@typescript-eslint/camelcase': 'off', '@typescript-eslint/no-use-before-define': 'off', '@typescript-eslint/array-type': ['error', 'array-simple'], @@ -42,13 +35,9 @@ module.exports = { argsIgnorePattern: '^_' } ], - '@typescript-eslint/no-object-literal-type-assertion': [ - 'error', - { - allowAsParameter: true - } - ], - '@typescript-eslint/no-unused-vars': 'off' + '@typescript-eslint/no-object-literal-type-assertion': 'off', + '@typescript-eslint/no-unused-vars': 'off', + '@typescript-eslint/prefer-interface': 'off' }, globals: { globalThis: false diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 98897c5740..14824ecdfa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,6 +13,19 @@ jobs: - uses: actions/setup-node@v1 with: node-version: ${{ matrix.node-version }} - - run: 'npm i && npm test' + - run: npm install + - run: npm test env: CI: true + Lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - uses: actions/setup-node@v1 + - run: 'npm i && npm run lint' + Unit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - uses: actions/setup-node@v1 + - run: 'npm i && npm run test:unit' diff --git a/.gitignore b/.gitignore index 1de9283c03..7a14244929 100644 --- a/.gitignore +++ b/.gitignore @@ -16,12 +16,14 @@ node_modules /scratch/ /coverage/ /coverage.lcov +/test/*/samples/_ /test/sourcemaps/samples/*/output.js /test/sourcemaps/samples/*/output.js.map /test/sourcemaps/samples/*/output.css /test/sourcemaps/samples/*/output.css.map /yarn-error.log _actual*.* +_output /types /site/cypress/screenshots/ @@ -31,5 +33,8 @@ _actual*.* /site/static/svelte-app.json /site/static/contributors.jpg /site/static/workers +/site/static/organisations /site/scripts/svelte-app +/site/scripts/community /site/src/routes/_contributors.js +/site/src/routes/_components/WhosUsingSvelte.svelte diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index 81451039fa..0000000000 --- a/.prettierrc +++ /dev/null @@ -1,3 +0,0 @@ -useTabs: true -singleQuote: true -trailingComma: es5 diff --git a/CHANGELOG.md b/CHANGELOG.md index 51e1e49cba..ef5ba2307f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,197 @@ ## Unreleased +* Exclude global variables from `$capture_state` ([#4463](https://github.com/sveltejs/svelte/issues/4463)) + +## 3.19.1 + +* Do not treat modifications to `$$props` as updates to a store called `$props` ([#4368](https://github.com/sveltejs/svelte/issues/4368)) +* Deconflict `value` parameter name used in contextual bindings ([#4445](https://github.com/sveltejs/svelte/issues/4445)) +* Fix dev mode validation of `{#each}` blocks using strings ([#4450](https://github.com/sveltejs/svelte/issues/4450)) + +## 3.19.0 + +* Fix indirect bindings involving elements with spreads ([#3680](https://github.com/sveltejs/svelte/issues/3680)) +* `$capture_state`/`$inject_state` now act on the component's entire state, rather than its props ([#3822](https://github.com/sveltejs/svelte/pull/3822)) +* Warn when using `` and `Foo` is dynamic ([#4331](https://github.com/sveltejs/svelte/issues/4331)) +* Display compilation warnings in `svelte/register` in dev mode ([#4364](https://github.com/sveltejs/svelte/issues/4364)) +* Fix unneeded updating of keyed each blocks ([#4373](https://github.com/sveltejs/svelte/issues/4373)) +* Throw runtime error in dev mode for non-array-like values in `{#each}` blocks ([#4408](https://github.com/sveltejs/svelte/issues/4408)) + +## 3.18.2 + +* Fix binding to module-level variables ([#4086](https://github.com/sveltejs/svelte/issues/4086)) +* Improve parsing error messages when there is a pending unclosed tag ([#4131](https://github.com/sveltejs/svelte/issues/4131)) +* Disallow attribute/prop names from matching two-way-bound names or `{shorthand}` attribute/prop names ([#4325](https://github.com/sveltejs/svelte/issues/4325)) +* Improve performance of `flush()` by not using `.shift()` ([#4356](https://github.com/sveltejs/svelte/pull/4356)) +* Permit reserved keywords as destructuring keys in `{#each}` ([#4372](https://github.com/sveltejs/svelte/issues/4372)) +* Disallow reserved keywords in `{expressions}` ([#4372](https://github.com/sveltejs/svelte/issues/4372)) +* Fix code generation error with precedence of arrow functions ([#4384](https://github.com/sveltejs/svelte/issues/4384)) +* Fix event handlers that are dynamic via reactive declarations or stores ([#4388](https://github.com/sveltejs/svelte/issues/4388)) +* Fix invalidation in expressions like `++foo.bar` ([#4393](https://github.com/sveltejs/svelte/issues/4393)) + +## 3.18.1 + +* Fix code generation error with adjacent inline and block comments ([#4312](https://github.com/sveltejs/svelte/issues/4312)) +* Fix detection of unused CSS selectors that begin with a `:global()` but contain a scoped portion ([#4314](https://github.com/sveltejs/svelte/issues/4314)) + +## 3.18.0 + +* Fix infinite loop when instantiating another component during `onMount` ([#3218](https://github.com/sveltejs/svelte/issues/3218)) +* Make autosubscribing to a nullish store a no-op ([#2181](https://github.com/sveltejs/svelte/issues/2181)) + +## 3.17.3 + +* Fix updating a `` inside an `{#if}` or other block ([#4292](https://github.com/sveltejs/svelte/issues/4292)) +* Fix using RxJS observables in `derived` stores ([#4298](https://github.com/sveltejs/svelte/issues/4298)) +* Add dev mode check to disallow duplicate keys in a keyed `{#each}` ([#4301](https://github.com/sveltejs/svelte/issues/4301)) +* Fix hydration of `` when starting from SSR-generated code with `hydratable: true` ([#4310](https://github.com/sveltejs/svelte/issues/4310)) + +## 3.17.2 + +* Fix removing attributes during hydration ([#1733](https://github.com/sveltejs/svelte/issues/1733)) +* Disallow two-way binding to a variable declared by an `{#await}` block ([#4012](https://github.com/sveltejs/svelte/issues/4012)) +* Allow access to `let:` variables in sibling attributes on slot root ([#4173](https://github.com/sveltejs/svelte/issues/4173)) +* Fix `~=` and class selector matching against values separated by any whitespace characters ([#4242](https://github.com/sveltejs/svelte/issues/4242)) +* Fix code generation for `await`ed expressions that need parentheses ([#4267](https://github.com/sveltejs/svelte/issues/4267)) +* Preserve JavaScript comments from the original component source where possible ([#4268](https://github.com/sveltejs/svelte/issues/4268)) +* Add some more known globals ([#4276](https://github.com/sveltejs/svelte/pull/4276)) +* Correctly apply event modifiers to `<svelte:body>` events ([#4278](https://github.com/sveltejs/svelte/issues/4278)) + +## 3.17.1 + +* Only attach SSR mode markers to a component's `<head>` elements when compiling with `hydratable: true` ([#4258](https://github.com/sveltejs/svelte/issues/4258)) + +## 3.17.0 + +* Remove old `<head>` elements during hydration so they aren't duplicated ([#1607](https://github.com/sveltejs/svelte/issues/1607)) +* Prevent text input cursor jumping in Safari with one-way binding ([#3449](https://github.com/sveltejs/svelte/issues/3449)) +* Expose compiler version in dev events ([#4047](https://github.com/sveltejs/svelte/issues/4047)) +* Don't run actions before their element is in the document ([#4166](https://github.com/sveltejs/svelte/issues/4166)) +* Fix reactive assignments with destructuring and stores where the destructured value should be undefined ([#4170](https://github.com/sveltejs/svelte/issues/4170)) +* Fix hydrating `{:else}` in `{#each}` ([#4202](https://github.com/sveltejs/svelte/issues/4202)) +* Do not automatically declare variables in reactive declarations when assigning to a member expression ([#4212](https://github.com/sveltejs/svelte/issues/4212)) +* Fix stringifying of attributes in SSR mode when there are spread attributes ([#4240](https://github.com/sveltejs/svelte/issues/4240)) +* Only render one `<title>` in SSR mode when multiple components provide one ([#4250](https://github.com/sveltejs/svelte/pull/4250)) + +## 3.16.7 + +* Also apply actions in the order they're given along with other directives ([#2446](https://github.com/sveltejs/svelte/issues/2446), [#4156](https://github.com/sveltejs/svelte/pull/4156)) +* Check whether a dynamic event handler is a function before calling it ([#4090](https://github.com/sveltejs/svelte/issues/4090)) +* Correctly mark event handlers as dynamic when they involve an expression used in a `bind:` elsewhere ([#4155](https://github.com/sveltejs/svelte/pull/4155)) + +## 3.16.6 + +* Fix CSS specificity bug when encapsulating styles ([#1277](https://github.com/sveltejs/svelte/issues/1277)) +* Apply directives in the order they're given ([#2446](https://github.com/sveltejs/svelte/issues/2446)) +* Fix destructuring in `let:` directives ([#2751](https://github.com/sveltejs/svelte/issues/2751)) +* Preserve whitespace around `<tspan>`s in `<svg>`s ([#3998](https://github.com/sveltejs/svelte/issues/3998)) + +## 3.16.5 + +* Better fix for cascading invalidations and fix some regressions ([#4098](https://github.com/sveltejs/svelte/issues/4098), [#4114](https://github.com/sveltejs/svelte/issues/4114), [#4120](https://github.com/sveltejs/svelte/issues/4120)) + +## 3.16.4 + +* Fix slots with props not propagating through to inner slots ([#4061](https://github.com/sveltejs/svelte/issues/4061)) +* Fix noting autosubscribed stores as `referenced` in `vars` for tooling ([#4081](https://github.com/sveltejs/svelte/issues/4081)) +* Fix cascading invalidations in certain situations ([#4094](https://github.com/sveltejs/svelte/issues/4094)) + +## 3.16.3 + +* Fix bitmask overflow when using slotted components ([#4077](https://github.com/sveltejs/svelte/issues/4077)) +* Remove unnecessary `$$invalidate` calls from init block ([#4018](https://github.com/sveltejs/svelte/issues/4018)) + +## 3.16.2 + +* Handle slot updates when parent component has a bitmask overflow ([#4078](https://github.com/sveltejs/svelte/pull/4078)) + +## 3.16.1 + +* Fix unused export warning for props used as stores ([#4021](https://github.com/sveltejs/svelte/issues/4021)) +* Fix `{:then}` without resolved value containing `{#each}` ([#4022](https://github.com/sveltejs/svelte/issues/4022)) +* Fix incorrect code generated with `loopGuardTimeout` ([#4034](https://github.com/sveltejs/svelte/issues/4034)) +* Fix handling of bitmask overflow and globals ([#4037](https://github.com/sveltejs/svelte/issues/4037)) +* Fix `{:then}` containing `{#if}` ([#4044](https://github.com/sveltejs/svelte/issues/4044)) +* Fix bare `import`s in `format: 'cjs'` output mode ([#4055](https://github.com/sveltejs/svelte/issues/4050)) +* Warn when using a known global as a component name ([#4070](https://github.com/sveltejs/svelte/issues/4070)) + +## 3.16.0 + +* Use bitmasks to track changes ([#3945](https://github.com/sveltejs/svelte/pull/3945)) +* Fix heisenbug with component styles ([#3977](https://github.com/sveltejs/svelte/issues/3977)) +* Do not warn about missing expected props for `export function foo() {}` ([#3954](https://github.com/sveltejs/svelte/issues/3954)) +* Fix `context="module"` exports with the same name as an instance variable ([#3983](https://github.com/sveltejs/svelte/issues/3983)) +* Fix binding to contextual values from `{#each}` blocks referring to global variables ([#3992](https://github.com/sveltejs/svelte/issues/3992)) +* Use `requestAnimationFrame` callback argument for smoother transitions ([#4014](https://github.com/sveltejs/svelte/pull/4014)) +* Fix `listen_dev` argument order ([#4016](https://github.com/sveltejs/svelte/pull/4016)) + +## 3.15.0 + +* Hide commented sections from preprocessors ([#3894](https://github.com/sveltejs/svelte/pull/3894)) +* Add `seeking` and `ended` bindings to media elements ([#3650](https://github.com/sveltejs/svelte/pull/3650)) +* Add `videoWidth` and `videoHeight` bindings to video elements ([#3927](https://github.com/sveltejs/svelte/pull/3927)) +* Fix for dynamic event handlers ([#3934](https://github.com/sveltejs/svelte/pull/3934)) +* Handle scale transforms when using the `flip` animation ([#3555](https://github.com/sveltejs/svelte/issues/3555)) +* Fix some code generation bugs ([#3929](https://github.com/sveltejs/svelte/issues/3929), [#3939](https://github.com/sveltejs/svelte/issues/3939)) +* Add `aria-hidden="true"` to objects generated when adding resize-listeners, to improve accessibility ([#3948](https://github.com/sveltejs/svelte/issues/3948)) + +## 3.14.1 + +* Deconflict block method names with other variables ([#3900](https://github.com/sveltejs/svelte/issues/3900)) +* Fix entity encoding issue in text nodes with constant expressions ([#3911](https://github.com/sveltejs/svelte/issues/3911)) +* Make code for unknown prop warnings compatible with older js engines ([#3914](https://github.com/sveltejs/svelte/issues/3914)) + +## 3.14.0 + +* Add `loopGuardTimeout` option that augments `for`/`while` loops to prevent infinite loops, primarily for use in the REPL ([#3887](https://github.com/sveltejs/svelte/pull/3887)) +* Keep component bindings in sync when changed in reactive statements ([#3382](https://github.com/sveltejs/svelte/issues/3382)) +* Update attributes before bindings ([#3857](https://github.com/sveltejs/svelte/issues/3857)) +* Prevent variable naming conflict ([#3899](https://github.com/sveltejs/svelte/issues/3899)) + + +## 3.13.0 + +* New structured code generation, which eliminates a number of edge cases and obscure bugs ([#3539](https://github.com/sveltejs/svelte/pull/3539)) + +Also: + +* Fix `{#each}` context not shadowing outer scope when using `bind:` ([#1565](https://github.com/sveltejs/svelte/issues/1565)) * Fix edge cases in matching selectors against elements ([#1710](https://github.com/sveltejs/svelte/issues/1710)) +* Fix several bugs related to interaction of `{...spread}` attributes with other features ([#2721](https://github.com/sveltejs/svelte/issues/2721), [#2916](https://github.com/sveltejs/svelte/issues/2916), [#3421](https://github.com/sveltejs/svelte/issues/3421), [#3681](https://github.com/sveltejs/svelte/issues/3681), [#3764](https://github.com/sveltejs/svelte/issues/3764), [#3790](https://github.com/sveltejs/svelte/issues/3790)) +* Allow exiting a reactive block early with `break $` ([#2828](https://github.com/sveltejs/svelte/issues/2828)) +* Fix binding to props that have been renamed with `export { ... as ... }` ([#3508](https://github.com/sveltejs/svelte/issues/3508)) +* Fix application of style scoping class in cases of ambiguity ([#3544](https://github.com/sveltejs/svelte/issues/3544)) +* Check attributes have changed before setting them to avoid image flicker ([#3579](https://github.com/sveltejs/svelte/pull/3579)) +* Fix generating malformed code for `{@debug}` tags with no dependencies ([#3588](https://github.com/sveltejs/svelte/issues/3588)) +* Fix generated code in specific case involving compound ifs and child components ([#3595](https://github.com/sveltejs/svelte/issues/3595)) +* Fix `bind:this` binding to a store ([#3591](https://github.com/sveltejs/svelte/issues/3591)) +* Use safer `HTMLElement` check before extending class ([#3608](https://github.com/sveltejs/svelte/issues/3608)) +* Add `location` as a known global ([#3619](https://github.com/sveltejs/svelte/pull/3619)) +* Support `{#await}` with `{:catch}` but no `{:then}` ([#3623](https://github.com/sveltejs/svelte/issues/3623)) +* Clean up dead code emitted for `<slot/>`s ([#3631](https://github.com/sveltejs/svelte/issues/3631)) +* Fix tracking of dependencies of compound assignments in reactive statements ([#3634](https://github.com/sveltejs/svelte/issues/3634)) +* Flush changes in newly attached block when using `{#await}` ([#3660](https://github.com/sveltejs/svelte/issues/3660)) +* Throw exception immediately when calling `createEventDispatcher()` after component instantiation ([#3667](https://github.com/sveltejs/svelte/pull/3667)) +* Fix globals shadowing contextual template scope ([#3674](https://github.com/sveltejs/svelte/issues/3674)) +* Fix `<svelte:window>` bindings to stores ([#3832](https://github.com/sveltejs/svelte/issues/3832)) +* Deconflict generated var names with builtins ([#3724](https://github.com/sveltejs/svelte/issues/3724)) +* Allow spring/tweened values to be initially undefined ([#3761](https://github.com/sveltejs/svelte/issues/3761)) +* Warn if using `<svelte:options tag="...">` without `customElement: true` option ([#3782](https://github.com/sveltejs/svelte/pull/3782)) +* Add `Event` to list of known globals ([#3810](https://github.com/sveltejs/svelte/pull/3810)) +* Throw helpful error on empty CSS declaration ([#3801](https://github.com/sveltejs/svelte/issues/3801)) +* Support `easing` param on `fade` transition ([#3823](https://github.com/sveltejs/svelte/pull/3823)) +* Generate valid names from filenames with unicode characters ([#3845](https://github.com/sveltejs/svelte/issues/3845)) +* Don't generate any code for markup-less components ([#2200](https://github.com/sveltejs/svelte/issues/2200)) +* Deconflict with internal name `block` ([#3854](https://github.com/sveltejs/svelte/issues/3854)) +* Set attributes before bindings, to prevent erroneous assignments to `input.files` ([#3828](https://github.com/sveltejs/svelte/issues/3828)) +* Smarter unused CSS detection ([#3825](https://github.com/sveltejs/svelte/pull/3825)) +* Allow dynamic event handlers ([#3040](https://github.com/sveltejs/svelte/issues/3040)) +* Prevent erroneous `"undefined"` class name ([#3876](https://github.com/sveltejs/svelte/pull/3876)) +* Prevent resetting of `src` attribute unless changed ([#3579](https://github.com/sveltejs/svelte/pull/3579)) +* Prevent hydration of void element 'children' ([#3882](https://github.com/sveltejs/svelte/issues/3882)) +* Hoist globals even if mentioned in `<script>` block ([#3745](https://github.com/sveltejs/svelte/pull/3745)) + ## 3.12.1 @@ -11,6 +201,7 @@ ## 3.12.0 * Fire events on `document` in development to facilitate dev tooling ([#3005](https://github.com/sveltejs/svelte/pull/3005)) +* Remove old props when the keys in spread props are removed ([#2282](https://github.com/sveltejs/svelte/issues/2282)) ## 3.11.0 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..f7df9770db --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,138 @@ +# Contributing to Svelte + +Svelte is a new way to build web applications. It's a compiler that takes your declarative components and converts them into efficient JavaScript that surgically updates the DOM. + +The [Open Source Guides](https://opensource.guide/) website has a collection of resources for individuals, communities, and companies. These resources help people who want to learn how to run and contribute to open source projects. Contributors and people new to open source alike will find the following guides especially useful: + +* [How to Contribute to Open Source](https://opensource.guide/how-to-contribute/) +* [Building Welcoming Communities](https://opensource.guide/building-community/) + +## Get involved + +There are many ways to contribute to Svelte, and many of them do not involve writing any code. Here's a few ideas to get started: + +- Simply start using Svelte. Go through the [Getting Started](https://svelte.dev/blog/the-easiest-way-to-get-started) guide. Does everything work as expected? If not, we're always looking for improvements. Let us know by [opening an issue](#reporting-new-issues). +- Look through the [open issues](https://github.com/sveltejs/svelte/issues). Provide workarounds, ask for clarification, or suggest labels. Help [triage issues](#triaging-issues-and-pull-requests). +- If you find an issue you would like to fix, [open a pull request](#your-first-pull-request). +- Read through our [tutorials](https://svelte.dev/tutorial/basics). If you find anything that is confusing or can be improved, you can make edits by clicking "Edit this chapter" at the bottom left of the tutorial page. +- Take a look at the [features requested](https://github.com/sveltejs/svelte/labels/enhancement) by others in the community and consider opening a pull request if you see something you want to work on. + +Contributions are very welcome. If you think you need help planning your contribution, please ping us on Discord at [svelte.dev/chat](https://svelte.dev/chat) and let us know you are looking for a bit of help. + +### Triaging issues and pull requests + +One great way you can contribute to the project without writing any code is to help triage issues and pull requests as they come in. + +- Ask for more information if you believe the issue does not provide all the details required to solve it. +- Suggest [labels](https://github.com/sveltejs/svelte/labels) that can help categorize issues. +- Flag issues that are stale or that should be closed. +- Ask for test plans and review code. + +## Bugs + +We use [GitHub issues](https://github.com/sveltejs/svelte/issues) for our public bugs. If you would like to report a problem, take a look around and see if someone already opened an issue about it. If you are certain this is a new unreported bug, you can submit a [bug report](#reporting-new-issues). + +If you have questions about using Svelte, contact us on Discord at [svelte.dev/chat](https://svelte.dev/chat), and we will do our best to answer your questions. + +If you see anything you'd like to be implemented, create a [feature request issue](https://github.com/sveltejs/svelte/issues/new?template=feature_request.md) + +## Reporting new issues + +When [opening a new issue](https://github.com/sveltejs/svelte/issues/new/choose), always make sure to fill out the issue template. **This step is very important!** Not doing so may result in your issue not being managed in a timely fashion. Don't take this personally if this happens, and feel free to open a new issue once you've gathered all the information required by the template. + +- **One issue, one bug:** Please report a single bug per issue. +- **Provide reproduction steps:** List all the steps necessary to reproduce the issue. The person reading your bug report should be able to follow these steps to reproduce your issue with minimal effort. If possible, use the [REPL](https://svelte.dev/repl) to create your reproduction. + +## Installation + +1. Ensure you have [npm](https://www.npmjs.com/get-npm) installed. +1. After cloning the repository, run `npm install` in the root of the repository. +1. To start a development server, run `npm run dev`. + + +## Pull requests + +### Your first pull request + +So you have decided to contribute code back to upstream by opening a pull request. You've invested a good chunk of time, and we appreciate it. We will do our best to work with you and get the PR looked at. + +Working on your first Pull Request? You can learn how from this free video series: + +[**How to Contribute to an Open Source Project on GitHub**](https://egghead.io/courses/how-to-contribute-to-an-open-source-project-on-github) + +### Proposing a change + +If you would like to request a new feature or enhancement but are not yet thinking about opening a pull request, you can also file an issue with [feature template](https://github.com/sveltejs/svelte/issues/new?template=feature_request.md). + +If you're only fixing a bug, it's fine to submit a pull request right away but we still recommend that you file an issue detailing what you're fixing. This is helpful in case we don't accept that specific fix but want to keep track of the issue. + +### Sending a pull request + +Small pull requests are much easier to review and more likely to get merged. Make sure the PR does only one thing, otherwise please split it. + +Please make sure the following is done when submitting a pull request: + +1. Fork [the repository](https://github.com/sveltejs/svelte) and create your branch from `master`. +1. Describe your **test plan** in your pull request description. Make sure to test your changes. +1. Make sure your code lints (`npm run lint`). +1. Make sure your tests pass (`npm run test`). + +All pull requests should be opened against the `master` branch. + +#### Test plan + +A good test plan has the exact commands you ran and their output, provides screenshots or videos if the pull request changes UI. + +- If you've changed APIs, update the documentation. + +#### Writing tests + +All tests are located in `/test` folder. + +Test samples are kept in `/test/xxx/samples` folder. + +#### Running tests + +1. To run test, run `npm run test` +1. To run test for a specific feature, you can use the `-g` (aka `--grep`) option. For example, to only run test involving transitions, run `npm run test -- -g transition`. + +##### Running solo test + +1. To run only one test, rename the test sample folder to end with `.solo`. For example, to run the `test/js/samples/action` only, rename it to `test/js/samples/action.solo`. +1. To run only one test suite, rename the test suite folder to end with `.solo`. For example, to run the `test/js` test suite only, rename it to `test/js.solo`. +1. Remember to rename the test folder back. The CI will fail if there's a solo test. + +##### Updating `.expected` files + +1. Tests suites like `css`, `js`, `server-side-rendering` asserts that the generated output has to match the content in the `.expected` file. For example, in the `js` test suites, the generated js code is compared against the content in `expected.js`. +1. To update the content of the `.expected` file, run the test with `--update` flag. (`npm run test --update`) + +#### Breaking changes + +When adding a new breaking change, follow this template in your pull request: + +```md +### New breaking change here + +- **Who does this affect**: +- **How to migrate**: +- **Why make this breaking change**: +- **Severity (number of people affected x effort)**: +``` + +### What happens next? + +The core Svelte team will be monitoring for pull requests. Do help us by making your pull request easy to review by following the guidelines above. + +## Style guide + +[Eslint](https://eslint.org) will catch most styling issues that may exist in your code. You can check the status of your code styling by simply running `npm run lint`. + +### Code conventions + +- `snake_case` for internal variable names and methods +- `camelCase` for public variable names and methods. + +## 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). diff --git a/LICENSE b/LICENSE index b63fe48148..a8e26a756d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2016-19 [these people](https://github.com/sveltejs/svelte/graphs/contributors) +Copyright (c) 2016-20 [these people](https://github.com/sveltejs/svelte/graphs/contributors) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/README.md b/README.md index b5a0e895dc..3a43725637 100644 --- a/README.md +++ b/README.md @@ -7,15 +7,6 @@ <img src="https://img.shields.io/npm/v/svelte.svg" alt="npm version"> </a> - <a href="https://packagephobia.now.sh/result?p=svelte"> - <img src="https://packagephobia.now.sh/badge?p=svelte" alt="install size"> - </a> - - <a href="https://travis-ci.org/sveltejs/svelte"> - <img src="https://api.travis-ci.org/sveltejs/svelte.svg?branch=master" - alt="build status"> - </a> - <a href="https://github.com/sveltejs/svelte/blob/master/LICENSE"> <img src="https://img.shields.io/npm/l/svelte.svg" alt="license"> </a> diff --git a/package-lock.json b/package-lock.json index acfa52723a..3b275078ec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "svelte", - "version": "3.12.1", + "version": "3.19.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -30,6 +30,113 @@ "integrity": "sha512-KioOCsSvSvXx6xUNLiJz+P+VMb7NRcePjoefOr74Y5P6lEKsiOn35eZyZzgpK4XCNJdXTDR7+zykj0lwxRvZ2g==", "dev": true }, + "@rollup/plugin-commonjs": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-11.0.0.tgz", + "integrity": "sha512-jnm//T5ZWOZ6zmJ61fReSCBOif+Ax8dHVoVggA+d2NA7T4qCWgQ3KYr+zN2faGEYLpe1wa03IzvhR+sqVLxUWg==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^3.0.0", + "estree-walker": "^0.6.1", + "is-reference": "^1.1.2", + "magic-string": "^0.25.2", + "resolve": "^1.11.0" + }, + "dependencies": { + "estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "dev": true + } + } + }, + "@rollup/plugin-json": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-4.0.1.tgz", + "integrity": "sha512-soxllkhOGgchswBAAaTe7X9G80U2tjjHvXv0sBrriLJcC/89PkP59iTrKPOfbz3SjX088mKDmMhAscuyLz8ZSg==", + "dev": true, + "requires": { + "rollup-pluginutils": "^2.5.0" + } + }, + "@rollup/plugin-node-resolve": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-6.0.0.tgz", + "integrity": "sha512-GqWz1CfXOsqpeVMcoM315+O7zMxpRsmhWyhJoxLFHVSp9S64/u02i7len/FnbTNbmgYs+sZyilasijH8UiuboQ==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^3.0.0", + "@types/resolve": "0.0.8", + "builtin-modules": "^3.1.0", + "is-module": "^1.0.0", + "resolve": "^1.11.1" + } + }, + "@rollup/plugin-replace": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.3.0.tgz", + "integrity": "sha512-rzWAMqXAHC1w3eKpK6LxRqiF4f3qVFaa1sGii6Bp3rluKcwHNOpPt+hWRCmAH6SDEPtbPiLFf0pfNQyHs6Btlg==", + "dev": true, + "requires": { + "magic-string": "^0.25.2", + "rollup-pluginutils": "^2.6.0" + } + }, + "@rollup/plugin-sucrase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-sucrase/-/plugin-sucrase-3.0.0.tgz", + "integrity": "sha512-sUQkoAXdw+bnd/cNZHGy5yQKW6OYYU7QlYBGhReI95uZljxO8t1LlbqCO2viIMV/u9pcCjgi8N9PcApcrJCA8Q==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^3.0.1", + "sucrase": "^3.10.1" + } + }, + "@rollup/plugin-typescript": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-2.0.1.tgz", + "integrity": "sha512-UA/bN/DlHN19xdOllXmp7G7pM2ac9dQMg0q2T1rg4Bogzb7oHXj2WGafpiNpEm54PivcJdzGRJvRnI6zCISW3w==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^3.0.0", + "resolve": "^1.12.2" + }, + "dependencies": { + "resolve": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.14.1.tgz", + "integrity": "sha512-fn5Wobh4cxbLzuHaE+nphztHy43/b++4M6SsGFC2gB8uYwf0C8LcarfCz1un7UTW8OFQg9iNjZ4xpcFVGebDPg==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + } + } + }, + "@rollup/plugin-virtual": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-virtual/-/plugin-virtual-2.0.0.tgz", + "integrity": "sha512-yUyQjcflsN1DGcUHj3I0NYL6Y6xrna6qjdaGjM93LjFLq8NFowhR0655ICeV9bNDbk+LI4pz7Q6xqeDdj1RdlA==", + "dev": true + }, + "@rollup/pluginutils": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.0.1.tgz", + "integrity": "sha512-PmNurkecagFimv7ZdKCVOfQuqKDPkrcpLFxRBcQ00LYr4HAjJwhCFxBiY2Xoletll2htTIiXBg6g0Yg21h2M3w==", + "dev": true, + "requires": { + "estree-walker": "^0.6.1" + }, + "dependencies": { + "estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "dev": true + } + } + }, "@types/eslint-visitor-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", @@ -167,9 +274,9 @@ "dev": true }, "acorn": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.0.0.tgz", - "integrity": "sha512-PaF/MduxijYYt7unVGRuds1vBC9bFxbNf+VWqhOClfdgy7RlVkQqt610ig1/yxTgsDIfW1cWDel5EBbOy3jdtQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", + "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", "dev": true }, "acorn-globals": { @@ -489,6 +596,18 @@ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true }, + "code-red": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/code-red/-/code-red-0.1.1.tgz", + "integrity": "sha512-2pEIyya4fxI9HxQcrl9dJl20+9He1nLeja50zkf7gK2OTTV9NpD3CgA74gzXnPqWv2zJpa6uXNSaE0haOCpOsw==", + "dev": true, + "requires": { + "acorn": "^7.1.0", + "is-reference": "^1.1.4", + "periscopic": "^2.0.1", + "sourcemap-codec": "^1.4.6" + } + }, "codecov": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/codecov/-/codecov-3.5.0.tgz", @@ -792,6 +911,13 @@ "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true } } }, @@ -1128,14 +1254,6 @@ "acorn": "^7.0.0", "acorn-jsx": "^5.0.2", "eslint-visitor-keys": "^1.1.0" - }, - "dependencies": { - "acorn": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.0.0.tgz", - "integrity": "sha512-PaF/MduxijYYt7unVGRuds1vBC9bFxbNf+VWqhOClfdgy7RlVkQqt610ig1/yxTgsDIfW1cWDel5EBbOy3jdtQ==", - "dev": true - } } }, "esprima": { @@ -1169,9 +1287,9 @@ "dev": true }, "estree-walker": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", - "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.0.tgz", + "integrity": "sha512-vY6xMN2j47HfQfVWGRqHshr1olf+XS1Y488NoqjDP1c8E1TcoZr/D3eSGa6akBs76WL1X9nluWjgBsCKdt/qKg==", "dev": true }, "esutils": { @@ -1475,15 +1593,23 @@ "dev": true }, "handlebars": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz", - "integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==", + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.3.tgz", + "integrity": "sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA==", "dev": true, "requires": { "neo-async": "^2.6.0", "optimist": "^0.6.1", "source-map": "^0.6.1", "uglify-js": "^3.1.4" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } } }, "har-schema": { @@ -1556,9 +1682,9 @@ } }, "https-proxy-agent": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.2.tgz", - "integrity": "sha512-c8Ndjc9Bkpfx/vCJueCPy0jlP4ccCCSNDp8xwCZzPjKJUm+B+u9WX2x98Qx4n1PiMNTWo3D7KK5ifNV/yJyRzg==", + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", "dev": true, "requires": { "agent-base": "^4.3.0", @@ -1741,9 +1867,9 @@ "dev": true }, "is-reference": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.1.3.tgz", - "integrity": "sha512-W1iHHv/oyBb2pPxkBxtaewxa1BC58Pn5J0hogyCdefwUIvb6R+TGbAcIa4qPNYLqLhb3EnOgUf2MQkkF76BcKw==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.1.4.tgz", + "integrity": "sha512-uJA/CDPO3Tao3GTrxYn6AwkM4nUPJiGGYu5+cB8qbC7WGFlrKZbiRo7SFKxUAEpFUfiHofWCXBUNhvYJMh+6zw==", "dev": true, "requires": { "@types/estree": "0.0.39" @@ -2693,6 +2819,15 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, + "periscopic": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/periscopic/-/periscopic-2.0.1.tgz", + "integrity": "sha512-twJ8e4RatllMAcbmBqKj8cvZ94HtqSzbb8hJoGj4iSCcCHXxKb06HRxOq4heyq2x/6mKynJDvTTreHCz+m6lJw==", + "dev": true, + "requires": { + "is-reference": "^1.1.4" + } + }, "pify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", @@ -3020,87 +3155,14 @@ } }, "rollup": { - "version": "1.21.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.21.4.tgz", - "integrity": "sha512-Pl512XVCmVzgcBz5h/3Li4oTaoDcmpuFZ+kdhS/wLreALz//WuDAMfomD3QEYl84NkDu6Z6wV9twlcREb4qQsw==", + "version": "1.27.14", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.27.14.tgz", + "integrity": "sha512-DuDjEyn8Y79ALYXMt+nH/EI58L5pEw5HU9K38xXdRnxQhvzUTI/nxAawhkAHUQeudANQ//8iyrhVRHJBuR6DSQ==", "dev": true, "requires": { - "@types/estree": "0.0.39", - "@types/node": "^12.7.5", - "acorn": "^7.0.0" - }, - "dependencies": { - "@types/node": { - "version": "12.7.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.5.tgz", - "integrity": "sha512-9fq4jZVhPNW8r+UYKnxF1e2HkDWOWKM5bC2/7c9wPV835I0aOrVbS/Hw/pWPk2uKrNXQqg9Z959Kz+IYDd5p3w==", - "dev": true - } - } - }, - "rollup-plugin-commonjs": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-commonjs/-/rollup-plugin-commonjs-10.1.0.tgz", - "integrity": "sha512-jlXbjZSQg8EIeAAvepNwhJj++qJWNJw1Cl0YnOqKtP5Djx+fFGkp3WRh+W0ASCaFG5w1jhmzDxgu3SJuVxPF4Q==", - "dev": true, - "requires": { - "estree-walker": "^0.6.1", - "is-reference": "^1.1.2", - "magic-string": "^0.25.2", - "resolve": "^1.11.0", - "rollup-pluginutils": "^2.8.1" - } - }, - "rollup-plugin-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-json/-/rollup-plugin-json-4.0.0.tgz", - "integrity": "sha512-hgb8N7Cgfw5SZAkb3jf0QXii6QX/FOkiIq2M7BAQIEydjHvTyxXHQiIzZaTFgx1GK0cRCHOCBHIyEkkLdWKxow==", - "dev": true, - "requires": { - "rollup-pluginutils": "^2.5.0" - } - }, - "rollup-plugin-node-resolve": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-5.2.0.tgz", - "integrity": "sha512-jUlyaDXts7TW2CqQ4GaO5VJ4PwwaV8VUGA7+km3n6k6xtOEacf61u0VXwN80phY/evMcaS+9eIeJ9MOyDxt5Zw==", - "dev": true, - "requires": { - "@types/resolve": "0.0.8", - "builtin-modules": "^3.1.0", - "is-module": "^1.0.0", - "resolve": "^1.11.1", - "rollup-pluginutils": "^2.8.1" - } - }, - "rollup-plugin-replace": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-replace/-/rollup-plugin-replace-2.2.0.tgz", - "integrity": "sha512-/5bxtUPkDHyBJAKketb4NfaeZjL5yLZdeUihSfbF2PQMz+rSTEb8ARKoOl3UBT4m7/X+QOXJo3sLTcq+yMMYTA==", - "dev": true, - "requires": { - "magic-string": "^0.25.2", - "rollup-pluginutils": "^2.6.0" - } - }, - "rollup-plugin-sucrase": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-sucrase/-/rollup-plugin-sucrase-2.1.0.tgz", - "integrity": "sha512-chdA3OruR1FH/IIKrzZCpGKLXAx3DOHoK24RIPtlVccK0wbTpHE0HpGEQYCxte1XaB17NgRe/frFyKR7g45qxQ==", - "dev": true, - "requires": { - "rollup-pluginutils": "^2.3.0", - "sucrase": "3.x" - } - }, - "rollup-plugin-typescript": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/rollup-plugin-typescript/-/rollup-plugin-typescript-1.0.1.tgz", - "integrity": "sha512-rwJDNn9jv/NsKZuyBb/h0jsclP4CJ58qbvZt2Q9zDIGILF2LtdtvCqMOL+Gq9IVq5MTrTlHZNrn8h7VjQgd8tw==", - "dev": true, - "requires": { - "resolve": "^1.10.0", - "rollup-pluginutils": "^2.5.0" + "@types/estree": "*", + "@types/node": "*", + "acorn": "^7.1.0" } }, "rollup-plugin-virtual": { @@ -3110,12 +3172,20 @@ "dev": true }, "rollup-pluginutils": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.1.tgz", - "integrity": "sha512-J5oAoysWar6GuZo0s+3bZ6sVZAC0pfqKz68De7ZgDi5z63jOVZn1uJL/+z1jeKHNbGII8kAyHF5q8LnxSX5lQg==", + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", + "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", "dev": true, "requires": { "estree-walker": "^0.6.1" + }, + "dependencies": { + "estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "dev": true + } } }, "run-async": { @@ -3202,9 +3272,9 @@ } }, "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", "dev": true }, "source-map-support": { @@ -3215,6 +3285,14 @@ "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } } }, "sourcemap-codec": { @@ -3522,6 +3600,15 @@ "requires": { "commander": "~2.20.0", "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + } } }, "uri-js": { @@ -3566,14 +3653,6 @@ "@types/istanbul-lib-coverage": "^2.0.1", "convert-source-map": "^1.6.0", "source-map": "^0.7.3" - }, - "dependencies": { - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - } } }, "validate-npm-package-license": { diff --git a/package.json b/package.json index 4a1622b3f4..7a02f1da10 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "svelte", - "version": "3.12.1", + "version": "3.19.1", "description": "Cybernetically enhanced web apps", "module": "index.mjs", "main": "index", @@ -56,35 +56,37 @@ }, "homepage": "https://github.com/sveltejs/svelte#README", "devDependencies": { + "@rollup/plugin-commonjs": "^11.0.0", + "@rollup/plugin-json": "^4.0.1", + "@rollup/plugin-node-resolve": "^6.0.0", + "@rollup/plugin-replace": "^2.3.0", + "@rollup/plugin-sucrase": "^3.0.0", + "@rollup/plugin-typescript": "^2.0.1", + "@rollup/plugin-virtual": "^2.0.0", "@types/mocha": "^5.2.7", "@types/node": "^8.10.53", "@typescript-eslint/eslint-plugin": "^1.13.0", "@typescript-eslint/parser": "^2.1.0", - "acorn": "^7.0.0", + "acorn": "^7.1.0", "agadoo": "^1.1.0", "c8": "^5.0.1", + "code-red": "0.1.1", "codecov": "^3.5.0", "css-tree": "1.0.0-alpha22", "eslint": "^6.3.0", "eslint-plugin-import": "^2.18.2", "eslint-plugin-svelte3": "^2.7.3", - "estree-walker": "^0.6.1", - "is-reference": "^1.1.3", + "estree-walker": "^1.0.0", + "is-reference": "^1.1.4", "jsdom": "^15.1.1", "kleur": "^3.0.3", "locate-character": "^2.0.5", "magic-string": "^0.25.3", "mocha": "^6.2.0", + "periscopic": "^2.0.1", "puppeteer": "^1.19.0", - "rollup": "^1.21.4", - "rollup-plugin-commonjs": "^10.1.0", - "rollup-plugin-json": "^4.0.0", - "rollup-plugin-node-resolve": "^5.2.0", - "rollup-plugin-replace": "^2.2.0", - "rollup-plugin-sucrase": "^2.1.0", - "rollup-plugin-typescript": "^1.0.1", - "rollup-plugin-virtual": "^1.0.1", - "source-map": "^0.6.1", + "rollup": "^1.27.14", + "source-map": "^0.7.3", "source-map-support": "^0.5.13", "tiny-glob": "^0.2.6", "tslib": "^1.10.0", diff --git a/register.js b/register.js index 3278c1cbf5..25f8aa4309 100644 --- a/register.js +++ b/register.js @@ -36,7 +36,15 @@ function registerExtension(extension) { format: 'cjs' }); - const { js } = compile(fs.readFileSync(filename, 'utf-8'), options); + const { js, warnings } = compile(fs.readFileSync(filename, 'utf-8'), options); + + if (options.dev) { + warnings.forEach(warning => { + console.warn(`\nSvelte Warning in ${warning.filename}:`); + console.warn(warning.message); + console.warn(warning.frame); + }) + } return module._compile(js.code, filename); }; diff --git a/rollup.config.js b/rollup.config.js index 7cce25e24c..6f3d893a33 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,10 +1,10 @@ import fs from 'fs'; -import replace from 'rollup-plugin-replace'; -import resolve from 'rollup-plugin-node-resolve'; -import commonjs from 'rollup-plugin-commonjs'; -import json from 'rollup-plugin-json'; -import sucrase from 'rollup-plugin-sucrase'; -import typescript from 'rollup-plugin-typescript'; +import replace from '@rollup/plugin-replace'; +import resolve from '@rollup/plugin-node-resolve'; +import commonjs from '@rollup/plugin-commonjs'; +import json from '@rollup/plugin-json'; +import sucrase from '@rollup/plugin-sucrase'; +import typescript from '@rollup/plugin-typescript'; import pkg from './package.json'; const is_publish = !!process.env.PUBLISH; @@ -20,8 +20,7 @@ const ts_plugin = is_publish const external = id => id.startsWith('svelte/'); -const inlined_estree = fs.readFileSync('./node_modules/estree-walker/index.d.ts', 'utf-8').replace(/declare.*\{((.|[\n\r])+)\}/m, '$1'); -fs.writeFileSync(`./compiler.d.ts`, `export { compile, parse, preprocess, VERSION } from './types/compiler/index';\n${inlined_estree}`); +fs.writeFileSync(`./compiler.d.ts`, `export { compile, parse, preprocess, VERSION } from './types/compiler/index';`); export default [ /* runtime */ @@ -61,6 +60,9 @@ export default [ ], external, plugins: [ + replace({ + __VERSION__: pkg.version + }), ts_plugin, { writeBundle(bundle) { diff --git a/site/.env.example b/site/.env.example index 4de2f6111a..9cfe50cd6c 100644 --- a/site/.env.example +++ b/site/.env.example @@ -2,7 +2,12 @@ NODE_ENV= PORT= BASEURL= -DATABASE_URL= GITHUB_CLIENT_ID= GITHUB_CLIENT_SECRET= -MAPBOX_ACCESS_TOKEN= \ No newline at end of file +MAPBOX_ACCESS_TOKEN= + +PGHOST=hostname +PGPORT=port +PGUSER=username +PGPASSWORD=password +PGDATABASE=database_name diff --git a/site/.eslintrc.js b/site/.eslintrc.js index a436f7bbe4..255b8af9c5 100644 --- a/site/.eslintrc.js +++ b/site/.eslintrc.js @@ -47,6 +47,12 @@ module.exports = { }, settings: { 'import/core-modules': ['svelte'], - 'svelte3/compiler': require('svelte/compiler') + 'svelte3/compiler': (() => { + try { + return require('svelte/compiler'); + } catch (e) { + return null; + } + })() } }; diff --git a/site/Dockerfile b/site/Dockerfile index c2a65122d9..0261a69521 100644 --- a/site/Dockerfile +++ b/site/Dockerfile @@ -1,3 +1,6 @@ +# IMPORTANT: Don't use this Dockerfile in your own Sapper projects without also looking at the .dockerignore file. +# Without an appropriate .dockerignore, this Dockerfile will copy a large number of unneeded files into your image. + FROM mhart/alpine-node:12 # install dependencies diff --git a/site/Makefile b/site/Makefile index 4c432dc6c9..6fd08fd8ee 100644 --- a/site/Makefile +++ b/site/Makefile @@ -14,9 +14,9 @@ sapper: docker: @echo "\n~> building docker image" - @gcloud builds submit -t $(IMAGE) + @gcloud builds submit --project $(PROJECT) -t $(IMAGE) deploy: sapper docker @echo "\n~> deploying $(SERVICE) to Cloud Run servers" - @gcloud beta run deploy $(SERVICE) --allow-unauthenticated --platform managed --region us-central1 --image $(IMAGE) --memory=512Mi + @gcloud run deploy $(SERVICE) --project $(PROJECT) --allow-unauthenticated --platform managed --region us-central1 --image $(IMAGE) --memory=512Mi diff --git a/site/content/blog/2017-12-31-sapper-towards-the-ideal-web-app-framework.md b/site/content/blog/2017-12-31-sapper-towards-the-ideal-web-app-framework.md index 8799fdacce..cca200e966 100644 --- a/site/content/blog/2017-12-31-sapper-towards-the-ideal-web-app-framework.md +++ b/site/content/blog/2017-12-31-sapper-towards-the-ideal-web-app-framework.md @@ -53,7 +53,7 @@ What happens if we use the new model as a starting point? The same 'hello world' app that took 204kb with React and Next weighs just 7kb with Sapper. That number is likely to fall further in the future as we explore the space of optimisation possibilities, such as not shipping any JavaScript *at all* for pages that aren't interactive, beyond the tiny Sapper runtime that handles client-side routing. -What about a more 'real world' example? Conveniently, the [RealWorld](https://github.com/gothinkster/realworld) project, which challenges frameworks to develop an implementation of a Medium clone, gives us a way to find out. The [Sapper implementation](http://svelte-realworld.now.sh/) takes 39.6kb (11.8kb zipped) to render an interactive homepage. +What about a more 'real world' example? Conveniently, the [RealWorld](https://github.com/gothinkster/realworld) project, which challenges frameworks to develop an implementation of a Medium clone, gives us a way to find out. The [Sapper implementation](https://github.com/sveltejs/realworld) takes 39.6kb (11.8kb zipped) to render an interactive homepage. <aside><p>Code-splitting isn't free — if the reference implementation used code-splitting, it would be larger still</p></aside> diff --git a/site/content/blog/2019-04-15-setting-up-your-editor.md b/site/content/blog/2019-04-15-setting-up-your-editor.md index bea7f4c762..b80223d820 100644 --- a/site/content/blog/2019-04-15-setting-up-your-editor.md +++ b/site/content/blog/2019-04-15-setting-up-your-editor.md @@ -6,28 +6,64 @@ authorURL: https://twitter.com/Rich_Harris draft: true --- -*Coming soon* This post will walk you through setting up your editor so that recognises Svelte files: +*__Coming soon__* + +This post will walk you through setting up your editor so that recognises Svelte files: * eslint-plugin-svelte3 * svelte-vscode -* associating .svelte files with HTML in VSCode, Sublime, Atom, etc etc etc +* associating .svelte files with HTML in VSCode, Sublime, etc. + +## Atom + +To treat `*.svelte` files as HTML, open *__Edit → Config...__* and add the following lines to your `core` section: + +```cson +"*": + core: + … + customFileTypes: + "text.html.basic": [ + "svelte" + ] +``` ## Vim/Neovim To treat all `*.svelte` files as HTML, add the following line to your `init.vim`: -```bash +``` au! BufNewFile,BufRead *.svelte set ft=html ``` To temporarily turn on HTML syntax highlighting for the current buffer, use: -```bash +``` :set ft=html ``` To set the filetype for a single file, use a [modeline](https://vim.fandom.com/wiki/Modeline_magic): -```bash +``` <!-- vim: set ft=html :--> ``` + +## Visual Studio Code + +To treat `*.svelte` files as HTML, add the following lines to your `settings.json` file: + +```cson + "files.associations": { + "*.svelte": "html" + } +``` + +## JetBrains WebStorm + +The [Svelte Framework Integration](https://plugins.jetbrains.com/plugin/12375-svelte/) can be used to add support for Svelte to WebStorm, or other Jetbrains IDEs. Consult the [WebStorm plugin installation guide](https://www.jetbrains.com/help/webstorm/managing-plugins.html) on the JetBrains website for more details. + +## Sublime Text 3 + +Open any `.svelte` file. + +Go to *__View → Syntax → Open all with current extension as... → HTML__*. diff --git a/site/content/blog/2019-04-16-svelte-for-new-developers.md b/site/content/blog/2019-04-16-svelte-for-new-developers.md index 54d5a2b7ce..796a6c11ab 100644 --- a/site/content/blog/2019-04-16-svelte-for-new-developers.md +++ b/site/content/blog/2019-04-16-svelte-for-new-developers.md @@ -3,7 +3,109 @@ title: Svelte for new developers description: Never used Node.js or the command line? No problem author: Rich Harris authorURL: https://twitter.com/Rich_Harris -draft: true --- -*Coming soon* This blog post will walk you through installing Node.js and git and using Terminal.app to clone a project template and start developing with Svelte \ No newline at end of file +This short guide is designed to help you — someone who has looked at the [tutorial](/tutorial) and wants to start creating Svelte apps, but doesn't have a ton of experience using JavaScript build tooling — get up and running. + +If there are things that don't make sense, or that we're glossing over, feel free to [raise an issue](https://github.com/sveltejs/svelte/issues) or [suggest edits to this page](https://github.com/sveltejs/svelte/blob/master/site/content/blog/2019-04-16-svelte-for-new-developers.md) that will help us help more people. + +If you get stuck at any point following this guide, the best place to ask for help is in the [chatroom](https://svelte.dev/chat). + + +## First things first + +You'll be using the *command line*, also known as the terminal. On Windows, you can access it by running **Command Prompt** from the Start menu; on a Mac, hit `Cmd` and `Space` together to bring up **Spotlight**, then start typing `Terminal.app`. On most Linux systems, `Ctrl-Alt-T` brings up the command line. + +The command line is a way to interact with your computer (or another computer! but that's a topic for another time) with more power and control than the GUI (graphical user interface) that most people use day-to-day. + +Once on the command line, you can navigate the filesystem using `ls` (`dir` on Windows) to list the contents of your current directory, and `cd` to change the current directory. For example, if you had a `Development` directory of your projects inside your home directory, you would type + +```bash +cd Development +``` + +to go to it. From there, you could create a new project directory with the `mkdir` command: + +```bash +mkdir svelte-projects +cd svelte-projects +``` + +A full introduction to the command line is out of the scope of this guide, but here are a few more useful commands: + +* `cd ..` — navigates to the parent of the current directory +* `cat my-file.txt` — on Mac/Linux (`type my-file.txt` on Windows), lists the contents of `my-file.txt` +* `open .` (or `start .` on Windows) — opens the current directory in Finder or File Explorer + + +## Installing Node.js + +[Node](https://nodejs.org/en/) is a way to run JavaScript on the command line. It's used by many tools, including Svelte. If you don't yet have it installed, the easiest way is to download the latest version straight from the [website](https://nodejs.org/en/). + +Once installed, you'll have access to three new commands: + +* `node my-file.js` — runs the JavaScript in `my-file.js` +* `npm [subcommand]` — [npm](https://www.npmjs.com/) is a way to install 'packages' that your application depends on, such as the [svelte](https://www.npmjs.com/) package +* `npx [subcommand]` — a convenient way to run programs available on npm without permanently installing them + + +## Installing a text editor + +To write code, you need a good editor. The most popular choice is [Visual Studio Code](https://code.visualstudio.com/) or VSCode, and justifiably so — it's well-designed and fully-featured, and has a wealth of extensions ([including one for Svelte](https://marketplace.visualstudio.com/items?itemName=JamesBirtles.svelte-vscode), which provides syntax highlighting and diagnostic messages when you're writing components). + + +## Creating a project + +We're going to follow the instructions in part two of [The easiest way to get started with Svelte](/blog/the-easiest-way-to-get-started). + +First, we'll use npx to run [degit](https://github.com/Rich-Harris/degit), a program for cloning project templates from [GitHub](https://github.com) and other code storage websites. You don't have to use a project template, but it means you have to do a lot less setup work. + +(Eventually you'll probably have to learn [git](https://git-scm.com/), which most programmers use to manage their projects. But you don't need to worry about it just yet.) + +On the command line, navigate to where you want to create a new project, then type the following lines (you can paste the whole lot, but you'll develop better muscle memory if you get into the habit of writing each line out one at a time then running it): + +```bash +npx degit sveltejs/template my-svelte-project +cd my-svelte-project +npm install +``` + +This creates a new directory, `my-svelte-project`, adds files from the [sveltejs/template](https://github.com/sveltejs/template) code repository, and installs a number of packages from npm. Open the directory in your text editor and take a look around. The app's 'source code' lives in the `src` directory, while the files your app can load are in `public`. + +In the `package.json` file, there is a section called `"scripts"`. These scripts define shortcuts for working with your application — `dev`, `build` and `start`. To launch your app in development mode, type the following: + +> TODO update the template, it needs... some work + +```bash +npm run dev +``` + +Running the `dev` script starts a program called [Rollup](https://rollupjs.org/guide/en/). Rollup's job is to take your application's source files (so far, just `src/main.js` and `src/App.svelte`), pass them to other programs (including Svelte, in our case) and convert them into the code that will actually run when you open the application in a browser. + +Speaking of which, open a browser and navigate to http://localhost:5000. This is your application running on a local *web server* (hence 'localhost') on port 5000. + +Try changing `src/App.svelte` and saving it. The application will reload with your changes. + + +## Building your app + +In the last step, we were running the app in 'development mode'. In dev mode, Svelte adds extra code that helps with debugging, and Rollup skips the final step where your app's JavaScript is compressed using [Terser](https://terser.org/). + +When you share your app with the world, you want to build it in 'production mode', so that it's as small and efficient as possible for end users. To do that, use the `build` command: + +```bash +npm run build +``` + +Your `public` directory now contains a compressed `bundle.js` file containing your app's JavaScript. You can run it like so: + +```bash +npm run start +``` + +This will run the app on http://localhost:5000. + + +## Next steps + +To share your app with the world you'll need to *deploy* it. There are many ways to do so — some are listed in the `README.md` file inside your project. diff --git a/site/content/blog/2019-04-20-write-less-code.md b/site/content/blog/2019-04-20-write-less-code.md index d6c8b77193..d56c5312e8 100644 --- a/site/content/blog/2019-04-20-write-less-code.md +++ b/site/content/blog/2019-04-20-write-less-code.md @@ -159,6 +159,6 @@ In Vue, meanwhile, we have a default export with a `data` function that returns ## Death to boilerplate -These are just some of the ways that Svelte helps you build user interfaces with a minimum of fuss. There are plenty of others — for example, [reactive declarations](https://svelte.dev/tutorial/reactive-declarations) essentially do the work of React's `useMemo`, `useCallback` and `useEffect` without the boilerplate (or indeed the garbage collection overhead of creating inline functions and arrays on each state change). +These are just some of the ways that Svelte helps you build user interfaces with a minimum of fuss. There are plenty of others — for example, [reactive declarations](tutorial/reactive-declarations) essentially do the work of React's `useMemo`, `useCallback` and `useEffect` without the boilerplate (or indeed the garbage collection overhead of creating inline functions and arrays on each state change). How? By choosing a different set of constraints. Because [Svelte is a compiler](blog/frameworks-without-the-framework), we're not bound to the peculiarities of JavaScript: we can *design* a component authoring experience, rather than having to fit it around the semantics of the language. Paradoxically, this results in *more* idiomatic code — for example using variables naturally rather than via proxies or hooks — while delivering significantly more performant apps. diff --git a/site/content/docs/00-introduction.md b/site/content/docs/00-introduction.md index 2456b85f9c..15fdffbde2 100644 --- a/site/content/docs/00-introduction.md +++ b/site/content/docs/00-introduction.md @@ -2,8 +2,8 @@ title: Before we begin --- -> Temporary note: This document is a work-in-progress. Please forgive any missing or misleading parts, and don't be shy about asking for help in the [Discord chatroom](chat). The [tutorial](tutorial) is more complete; start there. - This page contains detailed API reference documentation. It's intended to be a resource for people who already have some familiarity with Svelte. If that's not you (yet), you may prefer to visit the [interactive tutorial](tutorial) or the [examples](examples) before consulting this reference. + +Don't be shy about asking for help in the [Discord chatroom](chat). \ No newline at end of file diff --git a/site/content/docs/01-component-format.md b/site/content/docs/01-component-format.md index 3d349af51d..07a59c69f8 100644 --- a/site/content/docs/01-component-format.md +++ b/site/content/docs/01-component-format.md @@ -42,13 +42,13 @@ Svelte uses the `export` keyword to mark a variable declaration as a *property* --- -You can specify a default value, which will be used if the component's consumer doesn't specify a prop. +You can specify a default initial value for a prop. It will be used if the component's consumer doesn't specify the prop on the component (or if its initial value is `undefined`) when instantiating the component. Note that whenever a prop is removed by the consumer, its value is set to `undefined` rather than the initial value. -In development mode (see the [compiler options](docs#svelte_compile)), a warning will be printed if no default is provided and the consumer does not specify a value. To squelch this warning, ensure that a default is specified, even if it is `undefined`. +In development mode (see the [compiler options](docs#svelte_compile)), a warning will be printed if no default initial value is provided and the consumer does not specify a value. To squelch this warning, ensure that a default initial value is specified, even if it is `undefined`. ```html <script> - export let bar = 'optional default value'; + export let bar = 'optional default initial value'; export let baz = undefined; </script> ``` @@ -147,24 +147,7 @@ If a statement consists entirely of an assignment to an undeclared variable, Sve --- -A *store* is any object that allows reactive access to a value via a simple *store contract*. - -The [`svelte/store` module](docs#svelte_store) contains minimal store implementations which fulfil this contract. You can use these as the basis for your own stores, or you can implement your stores from scratch. - -A store must contain a `.subscribe` method, which must accept as its argument a subscription function. This subscription function must be immediately and synchronously called with the store's current value upon calling `.subscribe`. All of a store's active subscription functions must later be synchronously called whenever the store's value changes. The `.subscribe` method must also return an unsubscription function. Calling an unsubscription function must stop its subscription, and its corresponding subscription function must not be called again by the store. - -A store may optionally contain a `.set` method, which must accept as its argument a new value for the store, and which synchronously calls all of the store's active subscription functions. Such a store is called a *writable store*. - -```js -const unsubscribe = store.subscribe(value => { - console.log(value); -}); // logs `value` - -// later... -unsubscribe(); -``` - ---- +A *store* is an object that allows reactive access to a value via a simple *store contract*. The [`svelte/store` module](docs#svelte_store) contains minimal store implementations which fulfil this contract. Any time you have a reference to a store, you can access its value inside a component by prefixing it with the `$` character. This causes Svelte to declare the prefixed variable, and set up a store subscription that will be unsubscribed when appropriate. @@ -189,6 +172,20 @@ Local variables (that do not represent store values) must *not* have a `$` prefi </script> ``` +##### Store contract + +```js +store = { subscribe: (subscription: (value: any) => void) => () => void, set?: (value: any) => void } +``` + +You can create your own stores without relying on [`svelte/store`](docs#svelte_store), by implementing the *store contract*: + +1. A store must contain a `.subscribe` method, which must accept as its argument a subscription function. This subscription function must be immediately and synchronously called with the store's current value upon calling `.subscribe`. All of a store's active subscription functions must later be synchronously called whenever the store's value changes. +2. The `.subscribe` method must return an unsubscribe function. Calling an unsubscribe function must stop its subscription, and its corresponding subscription function must not be called again by the store. +3. A store may *optionally* contain a `.set` method, which must accept as its argument a new value for the store, and which synchronously calls all of the store's active subscription functions. Such a store is called a *writable store*. + +For interoperability with RxJS Observables, the `.subscribe` method is also allowed to return an object with an `.unsubscribe` method, rather than return the unsubscription function directly. Note however that unless `.subscribe` synchronously calls the subscription (which is not required by the Observable spec), Svelte will see the value of the store as `undefined` until it does. + ### <script context="module"> @@ -200,7 +197,7 @@ You can `export` bindings from this block, and they will become exports of the c You cannot `export default`, since the default export is the component itself. -> Variables defined in `module` scripts are not reactive — reassigning them will not trigger a rerender even though the variable itself will update. For values shared between multiple components, consider using a [store](https://svelte.dev/docs#svelte_store). +> Variables defined in `module` scripts are not reactive — reassigning them will not trigger a rerender even though the variable itself will update. For values shared between multiple components, consider using a [store](docs#svelte_store). ```html <script context="module"> @@ -256,3 +253,15 @@ To apply styles to a selector globally, use the `:global(...)` modifier. } </style> ``` + +--- + +If you want to make @keyframes that are accessible globally, you need to prepend your keyframe names with `-global-`. + +The `-global-` part will be removed when compiled, and the keyframe then be referenced using just `my-animation-name` elsewhere in your code. + +```html +<style> + @keyframes -global-my-animation-name {...} +</style> +``` diff --git a/site/content/docs/02-template-syntax.md b/site/content/docs/02-template-syntax.md index b878f1453e..55b913ca94 100644 --- a/site/content/docs/02-template-syntax.md +++ b/site/content/docs/02-template-syntax.md @@ -205,6 +205,8 @@ Iterating over lists of values can be done with an each block. </ul> ``` +You can use each blocks to iterate over any array or array-like value — that is, any object with a `length` property. + --- An each block can also specify an *index*, equivalent to the second argument in an `array.map(...)` callback: @@ -563,29 +565,38 @@ Elements with the `contenteditable` attribute support `innerHTML` and `textConte --- -Media elements (`<audio>` and `<video>`) have their own set of bindings — four *readonly* ones... +Media elements (`<audio>` and `<video>`) have their own set of bindings — six *readonly* ones... * `duration` (readonly) — the total duration of the video, in seconds * `buffered` (readonly) — an array of `{start, end}` objects * `seekable` (readonly) — ditto * `played` (readonly) — ditto +* `seeking` (readonly) — boolean +* `ended` (readonly) — boolean -...and three *two-way* bindings: +...and four *two-way* bindings: * `currentTime` — the current point in the video, in seconds +* `playbackRate` — how fast to play the video, where 1 is 'normal' * `paused` — this one should be self-explanatory * `volume` — a value between 0 and 1 +Videos additionally have readonly `videoWidth` and `videoHeight` bindings. + ```html <video src={clip} bind:duration bind:buffered bind:seekable + bind:seeking bind:played + bind:ended bind:currentTime bind:paused bind:volume + bind:videoWidth + bind:videoHeight ></video> ``` @@ -784,7 +795,7 @@ transition = (node: HTMLElement, params: any) => { A transition is triggered by an element entering or leaving the DOM as a result of a state change. -Elements inside an *outroing* block are kept in the DOM until all current transitions have completed. +When a block is transitioning out, elements inside the block are kept in the DOM until all current transitions have completed. The `transition:` directive indicates a *bidirectional* transition, which means it can be smoothly reversed while the transition is in progress. @@ -1007,7 +1018,7 @@ DOMRect { ​top: number, width: number, x: number, - y:number + y: number } ``` @@ -1145,7 +1156,7 @@ bind:property={variable} --- -You can bind to component props using the same mechanism. +You can bind to component props using the same syntax as for elements. ```html <Keypad bind:value={pin}/> @@ -1193,14 +1204,16 @@ The content is exposed in the child component using the `<slot>` element, which ```html <!-- App.svelte --> +<Widget></Widget> + <Widget> - <p>this is some child content</p> + <p>this is some child content that will overwrite the default slot content</p> </Widget> <!-- Widget.svelte --> <div> <slot> - this will be rendered if someone does <Widget/> + this fallback content will be rendered when no content is provided, like in the first example </slot> </div> ``` @@ -1236,15 +1249,15 @@ The usual shorthand rules apply — `let:item` is equivalent to `let:item={item} ```html <!-- App.svelte --> -<FancyList {items} let:item={item}> - <div>{item.text}</div> +<FancyList {items} let:prop={thing}> + <div>{thing.text}</div> </FancyList> <!-- FancyList.svelte --> <ul> {#each items as item} <li class="fancy"> - <slot item={item}></slot> + <slot prop={item}></slot> </li> {/each} </ul> @@ -1257,7 +1270,7 @@ Named slots can also expose values. The `let:` directive goes on the element wit ```html <!-- App.svelte --> <FancyList {items}> - <div slot="item" let:item={item}>{item.text}</div> + <div slot="item" let:item>{item.text}</div> <p slot="footer">Copyright (c) 2019 Svelte Industries</p> </FancyList> @@ -1265,7 +1278,7 @@ Named slots can also expose values. The `let:` directive goes on the element wit <ul> {#each items as item} <li class="fancy"> - <slot name="item" item={item}></slot> + <slot name="item" {item}></slot> </li> {/each} </ul> @@ -1380,7 +1393,7 @@ As with `<svelte:window>`, this element allows you to add listeners to events on --- -This element makes it possible to insert elements into `document.head`. During server-side rendering, `head` content exposed separately to the main `html` content. +This element makes it possible to insert elements into `document.head`. During server-side rendering, `head` content is exposed separately to the main `html` content. ```html <svelte:head> diff --git a/site/content/docs/03-run-time.md b/site/content/docs/03-run-time.md index 8e56f4ce59..c75ec694d9 100644 --- a/site/content/docs/03-run-time.md +++ b/site/content/docs/03-run-time.md @@ -184,7 +184,7 @@ dispatch: ((name: string, detail?: any) => void) = createEventDispatcher(); --- -Creates an event dispatcher that can be used to dispatch [component events](docs#Component_events). Event dispatchers are functions that can take two arguments: `name` and `detail`. +Creates an event dispatcher that can be used to dispatch [component events](docs#on_component_event). Event dispatchers are functions that can take two arguments: `name` and `detail`. Component events created with `createEventDispatcher` create a [CustomEvent](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent). These events do not [bubble](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#Event_bubbling_and_capture) and are not cancellable with `event.preventDefault()`. The `detail` argument corresponds to the [CustomEvent.detail](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/detail) property and can contain any type of data. @@ -214,7 +214,11 @@ Events dispatched from child components can be listened to in their parent. Any ### `svelte/store` -The `svelte/store` module exports functions for creating [stores](docs#4_Prefix_stores_with_$_to_access_their_values). +The `svelte/store` module exports functions for creating [readable](docs#readable), [writable](docs#writable) and [derived](docs#derived) stores. + +Keep in mind that you don't *have* to use these functions to enjoy the [reactive `$store` syntax](docs#4_Prefix_stores_with_$_to_access_their_values) in your components. Any object that correctly implements `.subscribe`, unsubscribe, and (optionally) `.set` is a valid store, and will work both with the special syntax, and with Svelte's built-in [`derived` stores](docs#derived). + +This makes it possible to wrap almost any other reactive state handling library for use in Svelte. Read more about the [store contract](docs#Store_contract) to see what a correct implementation looks like. #### `writable` @@ -433,6 +437,19 @@ Out of the box, Svelte will interpolate between two numbers, two arrays or two o --- +If the initial value is `undefined` or `null`, the first value change will take effect immediately. This is useful when you have tweened values that are based on props, and don't want any motion when the component first renders. + +```js +const size = tweened(undefined, { + duration: 300, + easing: cubicOut +}); + +$: $size = big ? 100 : 10; +``` + +--- + The `interpolate` option allows you to tween between *any* arbitrary values. It must be an `(a, b) => t => value` function, where `a` is the starting value, `b` is the target value, `t` is a number between 0 and 1, and `value` is the result. For example, we can use the [d3-interpolate](https://github.com/d3/d3-interpolate) package to smoothly interpolate between two colours. ```html @@ -476,7 +493,7 @@ A `spring` store gradually changes to its target value based on its `stiffness` --- -As with [`tweened`](#tweened) stores, `set` and `update` return a Promise that resolves if the spring settles. The `store.stiffness` and `store.damping` properties can be changed while the spring is in motion, and will take immediate effect. +As with [`tweened`](docs#tweened) stores, `set` and `update` return a Promise that resolves if the spring settles. The `store.stiffness` and `store.damping` properties can be changed while the spring is in motion, and will take immediate effect. Both `set` and `update` can take a second argument — an object with `hard` or `soft` properties. `{ hard: true }` sets the target value immediately; `{ soft: n }` preserves existing momentum for `n` seconds before settling. `{ soft: true }` is equivalent to `{ soft: 0.5 }`. @@ -493,6 +510,15 @@ Both `set` and `update` can take a second argument — an object with `hard` or </script> ``` +--- + +If the initial value is `undefined` or `null`, the first value change will take effect immediately, just as with `tweened` values (see above). + +```js +const size = spring(); +$: $size = big ? 100 : 10; +``` + ### `svelte/transition` The `svelte/transition` module exports six functions: `fade`, `fly`, `slide`, `scale`, `draw` and `crossfade`. They are for use with svelte [`transitions`](docs#Transitions). @@ -861,7 +887,7 @@ Existing children of `target` are left where they are. --- -The `hydrate` option instructs Svelte to upgrade existing DOM (usually from server-side rendering) rather than creating new elements. It will only work if the component was compiled with the [`hydratable: true` option](docs#svelte_compile). +The `hydrate` option instructs Svelte to upgrade existing DOM (usually from server-side rendering) rather than creating new elements. It will only work if the component was compiled with the [`hydratable: true` option](docs#svelte_compile). Hydration of `<head>` elements only works properly if the server-side rendering code was also compiled with `hydratable: true`, which adds a marker to each element in the `<head>` so that the component knows which elements it's responsible for removing during hydration. Whereas children of `target` are normally left alone, `hydrate: true` will cause any children to be removed. For that reason, the `anchor` option cannot be used alongside `hydrate: true`. @@ -945,7 +971,7 @@ app.count += 1; --- -Svelte components can also be compiled to custom elements (aka web components) using the `customElements: true` compiler option. You should specify a tag name for the component using the `<svelte:options>` [element](docs#svelte_options). +Svelte components can also be compiled to custom elements (aka web components) using the `customElement: true` compiler option. You should specify a tag name for the component using the `<svelte:options>` [element](docs#svelte_options). ```html <svelte:options tag="my-element"> @@ -1019,8 +1045,12 @@ Unlike client-side components, server-side components don't have a lifespan afte A server-side component exposes a `render` method that can be called with optional props. It returns an object with `head`, `html`, and `css` properties, where `head` contains the contents of any `<svelte:head>` elements encountered. +You can import a Svelte component directly into Node using [`svelte/register`](docs#svelte_register). + ```js -const App = require('./App.svelte'); +require('svelte/register'); + +const App = require('./App.svelte').default; const { head, html, css } = App.render({ answer: 42 diff --git a/site/content/docs/04-compile-time.md b/site/content/docs/04-compile-time.md index c6675e8a0b..0cb2ac3caf 100644 --- a/site/content/docs/04-compile-time.md +++ b/site/content/docs/04-compile-time.md @@ -4,9 +4,9 @@ title: Compile time Typically, you won't interact with the Svelte compiler directly, but will instead integrate it into your build system using a bundler plugin: -* [rollup-plugin-svelte](https://github.com/rollup/rollup-plugin-svelte) for users of [Rollup](https://rollupjs.org) +* [rollup-plugin-svelte](https://github.com/sveltejs/rollup-plugin-svelte) for users of [Rollup](https://rollupjs.org) * [svelte-loader](https://github.com/sveltejs/svelte-loader) for users of [webpack](https://webpack.js.org) -* [parcel-plugin-svelte](https://github.com/DeMoorJasper/parcel-plugin-svelte) for users of [Parcel](https://parceljs.org/) +* or one of the [community-maintained plugins](https://github.com/sveltejs/integrations#bundler-plugins) Nonetheless, it's useful to understand how to use the compiler, since bundler plugins generally expose compiler options to you. @@ -53,6 +53,7 @@ The following options can be passed to the compiler. None are required: | `tag` | string | null | `accessors` | boolean | `false` | `css` | boolean | `true` +| `loopGuardTimeout` | number | 0 | `preserveComments` | boolean | `false` | `preserveWhitespace` | boolean | `false` | `outputFilename` | string | `null` @@ -67,14 +68,15 @@ The following options can be passed to the compiler. None are required: | `generate` | `"dom"` | If `"dom"`, Svelte emits a JavaScript class for mounting to the DOM. If `"ssr"`, Svelte emits an object with a `render` method suitable for server-side rendering. If `false`, no JavaScript or CSS is returned; just metadata. | `dev` | `false` | If `true`, causes extra code to be added to components that will perform runtime checks and provide debugging information during development. | `immutable` | `false` | If `true`, tells the compiler that you promise not to mutate any objects. This allows it to be less conservative about checking whether values have changed. -| `hydratable` | `false` | If `true`, enables the `hydrate: true` runtime option, which allows a component to upgrade existing DOM rather than creating new DOM from scratch. +| `hydratable` | `false` | If `true` when generating DOM code, enables the `hydrate: true` runtime option, which allows a component to upgrade existing DOM rather than creating new DOM from scratch. When generating SSR code, this adds markers to `<head>` elements so that hydration knows which to replace. | `legacy` | `false` | If `true`, generates code that will work in IE9 and IE10, which don't support things like `element.dataset`. | `accessors` | `false` | If `true`, getters and setters will be created for the component's props. If `false`, they will only be created for readonly exported values (i.e. those declared with `const`, `class` and `function`). If compiling with `customElement: true` this option defaults to `true`. | `customElement` | `false` | If `true`, tells the compiler to generate a custom element constructor instead of a regular Svelte component. | `tag` | `null` | A `string` that tells Svelte what tag name to register the custom element with. It must be a lowercase alphanumeric string with at least one hyphen, e.g. `"my-element"`. | `css` | `true` | If `true`, styles will be included in the JavaScript class and injected at runtime. It's recommended that you set this to `false` and use the CSS that is statically generated, as it will result in smaller JavaScript bundles and better performance. +| `loopGuardTimeout` | 0 | A `number` that tells Svelte to break the loop if it blocks the thread for more than `loopGuardTimeout` ms. This is useful to prevent infinite loops. **Only available when `dev: true`** | `preserveComments` | `false` | If `true`, your HTML comments will be preserved during server-side rendering. By default, they are stripped out. -| `preserveWhitespace` | `false` | If `true`, whitespace inside and between elements is kept as you typed it, rather than optimised by Svelte. +| `preserveWhitespace` | `false` | If `true`, whitespace inside and between elements is kept as you typed it, rather than removed or collapsed to a single space where possible. | `outputFilename` | `null` | A `string` used for your JavaScript sourcemap. | `cssOutputFilename` | `null` | A `string` used for your CSS sourcemap. | `sveltePath` | `"svelte"` | The location of the `svelte` package. Any imports from `svelte` or `svelte/[module]` will be modified accordingly. @@ -183,7 +185,7 @@ const ast = svelte.parse(source, { filename: 'App.svelte' }); result: { code: string, dependencies: Array<string> -} = svelte.preprocess( +} = await svelte.preprocess( source: string, preprocessors: Array<{ markup?: (input: { content: string, filename: string }) => Promise<{ @@ -220,7 +222,7 @@ The `markup` function receives the entire component source text, along with the ```js const svelte = require('svelte/compiler'); -const { code } = svelte.preprocess(source, { +const { code } = await svelte.preprocess(source, { markup: ({ content, filename }) => { return { code: content.replace(/foo/g, 'bar') @@ -235,14 +237,14 @@ const { code } = svelte.preprocess(source, { The `script` and `style` functions receive the contents of `<script>` and `<style>` elements respectively. In addition to `filename`, they get an object of the element's attributes. -If a `dependencies` array is returned, it will be included in the result object. This is used by packages like [rollup-plugin-svelte](https://github.com/rollup/rollup-plugin-svelte) to watch additional files for changes, in the case where your `<style>` tag has an `@import` (for example). +If a `dependencies` array is returned, it will be included in the result object. This is used by packages like [rollup-plugin-svelte](https://github.com/sveltejs/rollup-plugin-svelte) to watch additional files for changes, in the case where your `<style>` tag has an `@import` (for example). ```js const svelte = require('svelte/compiler'); const sass = require('node-sass'); const { dirname } = require('path'); -const { code, dependencies } = svelte.preprocess(source, { +const { code, dependencies } = await svelte.preprocess(source, { style: async ({ content, attributes, filename }) => { // only process <style lang="sass"> if (attributes.lang !== 'sass') return; @@ -275,7 +277,7 @@ Multiple preprocessors can be used together. The output of the first becomes the ```js const svelte = require('svelte/compiler'); -const { code } = svelte.preprocess(source, [ +const { code } = await svelte.preprocess(source, [ { markup: () => { console.log('this runs first'); diff --git a/site/content/examples/00-introduction/02-styling/App.svelte b/site/content/examples/00-introduction/02-styling/App.svelte index cacaf8ccba..7148dcf10f 100644 --- a/site/content/examples/00-introduction/02-styling/App.svelte +++ b/site/content/examples/00-introduction/02-styling/App.svelte @@ -1,7 +1,7 @@ <style> p { color: purple; - font-family: 'Comic Sans MS'; + font-family: 'Comic Sans MS', cursive; font-size: 2em; } </style> diff --git a/site/content/examples/00-introduction/03-nested-components/App.svelte b/site/content/examples/00-introduction/03-nested-components/App.svelte index e0a2e5fe17..bb97f50ace 100644 --- a/site/content/examples/00-introduction/03-nested-components/App.svelte +++ b/site/content/examples/00-introduction/03-nested-components/App.svelte @@ -5,7 +5,7 @@ <style> p { color: purple; - font-family: 'Comic Sans MS'; + font-family: 'Comic Sans MS', cursive; font-size: 2em; } </style> diff --git a/site/content/examples/04-events/05-dom-event-forwarding/App.svelte b/site/content/examples/04-events/05-dom-event-forwarding/App.svelte index 1429cae207..e75c78106a 100644 --- a/site/content/examples/04-events/05-dom-event-forwarding/App.svelte +++ b/site/content/examples/04-events/05-dom-event-forwarding/App.svelte @@ -1,9 +1,9 @@ <script> - import FancyButton from './FancyButton.svelte'; + import CustomButton from './CustomButton.svelte'; function handleClick() { alert('clicked'); } </script> -<FancyButton on:click={handleClick}/> \ No newline at end of file +<CustomButton on:click={handleClick}/> \ No newline at end of file diff --git a/site/content/examples/04-events/05-dom-event-forwarding/CustomButton.svelte b/site/content/examples/04-events/05-dom-event-forwarding/CustomButton.svelte new file mode 100644 index 0000000000..f521c1f471 --- /dev/null +++ b/site/content/examples/04-events/05-dom-event-forwarding/CustomButton.svelte @@ -0,0 +1,22 @@ +<style> + button { + height: 4rem; + width: 8rem; + background-color: #aaa; + border-color: #f1c40f; + color: #f1c40f; + font-size: 1.25rem; + background-image: linear-gradient(45deg, #f1c40f 50%, transparent 50%); + background-position: 100%; + background-size: 400%; + transition: background 300ms ease-in-out; + } + button:hover { + background-position: 0; + color: #aaa; + } +</style> + +<button on:click> + Click me +</button> \ No newline at end of file diff --git a/site/content/examples/04-events/05-dom-event-forwarding/FancyButton.svelte b/site/content/examples/04-events/05-dom-event-forwarding/FancyButton.svelte deleted file mode 100644 index 75630ea99c..0000000000 --- a/site/content/examples/04-events/05-dom-event-forwarding/FancyButton.svelte +++ /dev/null @@ -1,15 +0,0 @@ -<style> - button { - font-family: 'Comic Sans MS'; - font-size: 2em; - padding: 0.5em 1em; - color: royalblue; - background: gold; - border-radius: 1em; - box-shadow: 2px 2px 4px rgba(0,0,0,0.5); - } -</style> - -<button on:click> - Click me -</button> \ No newline at end of file diff --git a/site/content/examples/05-bindings/08-media-elements/App.svelte b/site/content/examples/05-bindings/08-media-elements/App.svelte index fd4f843ca1..469e9e12eb 100644 --- a/site/content/examples/05-bindings/08-media-elements/App.svelte +++ b/site/content/examples/05-bindings/08-media-elements/App.svelte @@ -14,7 +14,7 @@ showControlsTimeout = setTimeout(() => showControls = false, 2500); showControls = true; - if (e.which !== 1) return; // mouse not down + if (!(e.buttons & 1)) return; // mouse not down if (!duration) return; // video not loaded yet const { left, right } = this.getBoundingClientRect(); @@ -127,4 +127,4 @@ <span class="time">{format(duration)}</span> </div> </div> -</div> \ No newline at end of file +</div> diff --git a/site/content/examples/05-bindings/10-bind-this/App.svelte b/site/content/examples/05-bindings/10-bind-this/App.svelte index 9a8fabc265..8e4b3c5bef 100644 --- a/site/content/examples/05-bindings/10-bind-this/App.svelte +++ b/site/content/examples/05-bindings/10-bind-this/App.svelte @@ -43,8 +43,8 @@ width: 100%; height: 100%; background-color: #666; - -webkit-mask: url(logo-mask.svg) 50% 50% no-repeat; - mask: url(logo-mask.svg) 50% 50% no-repeat; + -webkit-mask: url(svelte-logo-mask.svg) 50% 50% no-repeat; + mask: url(svelte-logo-mask.svg) 50% 50% no-repeat; } </style> diff --git a/site/content/examples/12-svg/05-svg-transitions/App.svelte b/site/content/examples/12-svg/05-svg-transitions/App.svelte index 6059b3645f..6e1e636b20 100644 --- a/site/content/examples/12-svg/05-svg-transitions/App.svelte +++ b/site/content/examples/12-svg/05-svg-transitions/App.svelte @@ -33,7 +33,7 @@ font-family: 'Overpass'; letter-spacing: 0.12em; color: #676778; - font-weight: 100; + font-weight: 400; } .centered span { @@ -71,4 +71,4 @@ toggle me </label> -<link href="https://fonts.googleapis.com/css?family=Overpass:100" rel="stylesheet"> \ No newline at end of file +<link href="https://fonts.googleapis.com/css?family=Overpass:100,400" rel="stylesheet"> diff --git a/site/content/examples/13-actions/01-adding-parameters-to-actions/App.svelte b/site/content/examples/13-actions/01-adding-parameters-to-actions/App.svelte index 0bd9d56113..d6eaa0ff12 100644 --- a/site/content/examples/13-actions/01-adding-parameters-to-actions/App.svelte +++ b/site/content/examples/13-actions/01-adding-parameters-to-actions/App.svelte @@ -1,70 +1,20 @@ <script> - let language = "english"; + import { longpress } from './longpress.js'; - const translations = { - english: { - tooltip: "Switch Languages", - }, - latin: { - tooltip: "Itchsway Anguageslay", - } - }; - - function tooltip(node, text) { - const tooltip = document.createElement('div'); - tooltip.textContent = text; - - Object.assign(tooltip.style, { - position: 'absolute', - background: 'black', - color: 'white', - padding: '0.5em 1em', - fontSize: '12px', - pointerEvents: 'none', - transform: 'translate(5px, -50%)', - borderRadius: '2px', - transition: 'opacity 0.4s' - }); - - function position() { - const { top, right, bottom } = node.getBoundingClientRect(); - tooltip.style.top = `${(top + bottom) / 2}px`; - tooltip.style.left = `${right}px`; - } - - function append() { - document.body.appendChild(tooltip); - tooltip.style.opacity = 0; - setTimeout(() => tooltip.style.opacity = 1); - position(); - } - - function remove() { - tooltip.remove(); - } - - node.addEventListener('mouseenter', append); - node.addEventListener('mouseleave', remove); - - return { - update(text) { - tooltip.textContent = text; - position(); - }, + let pressed = false; + let duration = 2000; +</script> - destroy() { - tooltip.remove(); - node.removeEventListener('mouseenter', append); - node.removeEventListener('mouseleave', remove); - } - }; - } +<label> + <input type=range bind:value={duration} max={2000} step={100}> + {duration}ms +</label> - function toggleLanguage() { - language = language === 'english' ? 'latin' : 'english' - } -</script> +<button use:longpress={duration} + on:longpress="{() => pressed = true}" + on:mouseenter="{() => pressed = false}" +>press and hold</button> -<button on:click={toggleLanguage} use:tooltip={translations[language].tooltip}> - {language} -</button> \ No newline at end of file +{#if pressed} + <p>congratulations, you pressed and held for {duration}ms</p> +{/if} \ No newline at end of file diff --git a/site/content/examples/13-actions/01-adding-parameters-to-actions/longpress.js b/site/content/examples/13-actions/01-adding-parameters-to-actions/longpress.js new file mode 100644 index 0000000000..9d807cb13a --- /dev/null +++ b/site/content/examples/13-actions/01-adding-parameters-to-actions/longpress.js @@ -0,0 +1,28 @@ +export function longpress(node, duration) { + let timer; + + const handleMousedown = () => { + timer = setTimeout(() => { + node.dispatchEvent( + new CustomEvent('longpress') + ); + }, duration); + }; + + const handleMouseup = () => { + clearTimeout(timer) + }; + + node.addEventListener('mousedown', handleMousedown); + node.addEventListener('mouseup', handleMouseup); + + return { + update(newDuration) { + duration = newDuration; + }, + destroy() { + node.removeEventListener('mousedown', handleMousedown); + node.removeEventListener('mouseup', handleMouseup); + } + }; +} \ No newline at end of file diff --git a/site/content/examples/15-composition/04-modal/Modal.svelte b/site/content/examples/15-composition/04-modal/Modal.svelte index 5ffa5989a4..4a5329b05b 100644 --- a/site/content/examples/15-composition/04-modal/Modal.svelte +++ b/site/content/examples/15-composition/04-modal/Modal.svelte @@ -1,9 +1,56 @@ <script> - import { createEventDispatcher } from 'svelte'; + import { createEventDispatcher, onDestroy } from 'svelte'; const dispatch = createEventDispatcher(); + const close = () => dispatch('close'); + + let modal; + + const handle_keydown = e => { + if (e.key === 'Escape') { + close(); + return; + } + + if (e.key === 'Tab') { + // trap focus + const nodes = modal.querySelectorAll('*'); + const tabbable = Array.from(nodes).filter(n => n.tabIndex >= 0); + + let index = tabbable.indexOf(document.activeElement); + if (index === -1 && e.shiftKey) index = 0; + + index += tabbable.length + (e.shiftKey ? -1 : 1); + index %= tabbable.length; + + tabbable[index].focus(); + e.preventDefault(); + } + }; + + const previously_focused = typeof document !== 'undefined' && document.activeElement; + + if (previously_focused) { + onDestroy(() => { + previously_focused.focus(); + }); + } </script> +<svelte:window on:keydown={handle_keydown}/> + +<div class="modal-background" on:click={close}></div> + +<div class="modal" role="dialog" aria-modal="true" bind:this={modal}> + <slot name="header"></slot> + <hr> + <slot></slot> + <hr> + + <!-- svelte-ignore a11y-autofocus --> + <button autofocus on:click={close}>close modal</button> +</div> + <style> .modal-background { position: fixed; @@ -32,14 +79,3 @@ display: block; } </style> - -<div class='modal-background' on:click='{() => dispatch("close")}'></div> - -<div class='modal'> - <slot name='header'></slot> - <hr> - <slot></slot> - <hr> - - <button on:click='{() => dispatch("close")}'>close modal</button> -</div> diff --git a/site/content/examples/20-7guis/05-7guis-crud/App.svelte b/site/content/examples/20-7guis/05-7guis-crud/App.svelte index f55aeb0d83..aec623d2a4 100644 --- a/site/content/examples/20-7guis/05-7guis-crud/App.svelte +++ b/site/content/examples/20-7guis/05-7guis-crud/App.svelte @@ -2,18 +2,9 @@ <script> let people = [ - { - first: 'Hans', - last: 'Emil' - }, - { - first: 'Max', - last: 'Mustermann' - }, - { - first: 'Roman', - last: 'Tisch' - } + { first: 'Hans', last: 'Emil' }, + { first: 'Max', last: 'Mustermann' }, + { first: 'Roman', last: 'Tisch' } ]; let prefix = ''; @@ -39,7 +30,9 @@ } function update() { - people[i] = { first, last }; + selected.first = first; + selected.last = last; + people = people; } function remove() { diff --git a/site/content/examples/99-embeds/20181225-blog-svelte-css-in-js/styles.js b/site/content/examples/99-embeds/20181225-blog-svelte-css-in-js/styles.js index c7e10606c5..a18491b271 100644 --- a/site/content/examples/99-embeds/20181225-blog-svelte-css-in-js/styles.js +++ b/site/content/examples/99-embeds/20181225-blog-svelte-css-in-js/styles.js @@ -11,7 +11,7 @@ export const title = css` `; export const comicSans = css` - font-family: 'Comic Sans MS'; + font-family: 'Comic Sans MS', cursive; `; export const box = css` diff --git a/site/content/tutorial/01-introduction/04-styling/app-b/App.svelte b/site/content/tutorial/01-introduction/04-styling/app-b/App.svelte index ab87af83d8..5feb02e701 100644 --- a/site/content/tutorial/01-introduction/04-styling/app-b/App.svelte +++ b/site/content/tutorial/01-introduction/04-styling/app-b/App.svelte @@ -1,7 +1,7 @@ <style> p { color: purple; - font-family: 'Comic Sans MS'; + font-family: 'Comic Sans MS', cursive; font-size: 2em; } </style> diff --git a/site/content/tutorial/01-introduction/04-styling/text.md b/site/content/tutorial/01-introduction/04-styling/text.md index 9f285d2f51..71d031dcab 100644 --- a/site/content/tutorial/01-introduction/04-styling/text.md +++ b/site/content/tutorial/01-introduction/04-styling/text.md @@ -8,7 +8,7 @@ Just like in HTML, you can add a `<style>` tag to your component. Let's add some <style> p { color: purple; - font-family: 'Comic Sans MS'; + font-family: 'Comic Sans MS', cursive; font-size: 2em; } </style> diff --git a/site/content/tutorial/01-introduction/05-nested-components/app-a/App.svelte b/site/content/tutorial/01-introduction/05-nested-components/app-a/App.svelte index ab87af83d8..5feb02e701 100644 --- a/site/content/tutorial/01-introduction/05-nested-components/app-a/App.svelte +++ b/site/content/tutorial/01-introduction/05-nested-components/app-a/App.svelte @@ -1,7 +1,7 @@ <style> p { color: purple; - font-family: 'Comic Sans MS'; + font-family: 'Comic Sans MS', cursive; font-size: 2em; } </style> diff --git a/site/content/tutorial/01-introduction/05-nested-components/app-b/App.svelte b/site/content/tutorial/01-introduction/05-nested-components/app-b/App.svelte index 9ba76665bf..f553eed355 100644 --- a/site/content/tutorial/01-introduction/05-nested-components/app-b/App.svelte +++ b/site/content/tutorial/01-introduction/05-nested-components/app-b/App.svelte @@ -5,7 +5,7 @@ <style> p { color: purple; - font-family: 'Comic Sans MS'; + font-family: 'Comic Sans MS', cursive; font-size: 2em; } </style> diff --git a/site/content/tutorial/01-introduction/07-making-an-app/text.md b/site/content/tutorial/01-introduction/07-making-an-app/text.md index f8755ef532..4d044272b5 100644 --- a/site/content/tutorial/01-introduction/07-making-an-app/text.md +++ b/site/content/tutorial/01-introduction/07-making-an-app/text.md @@ -4,11 +4,12 @@ title: Making an app This tutorial is designed to get you familiar with the process of writing components. But at some point, you'll want to start writing components in the comfort of your own text editor. -First, you'll need to integrate Svelte with a build tool. Popular choices are: +First, you'll need to integrate Svelte with a build tool. There are officially maintained plugins for [Rollup](https://rollupjs.org) and [webpack](https://webpack.js.org/)... -* [Rollup](https://rollupjs.org) / [rollup-plugin-svelte](https://github.com/rollup/rollup-plugin-svelte) -* [webpack](https://webpack.js.org/) / [svelte-loader](https://github.com/sveltejs/svelte-loader) -* [Parcel](https://parceljs.org/) / [parcel-plugin-svelte](https://github.com/DeMoorJasper/parcel-plugin-svelte) +* [rollup-plugin-svelte](https://github.com/sveltejs/rollup-plugin-svelte) +* [svelte-loader](https://github.com/sveltejs/svelte-loader) + +...and a variety of [community-maintained ones](https://github.com/sveltejs/integrations#bundler-plugins). Don't worry if you're relatively new to web development and haven't used these tools before. We've prepared a simple step-by-step guide, [Svelte for new developers](blog/svelte-for-new-developers), which walks you through the process. diff --git a/site/content/tutorial/02-reactivity/02-reactive-declarations/text.md b/site/content/tutorial/02-reactivity/02-reactive-declarations/text.md index 365908cf22..027a91a44a 100644 --- a/site/content/tutorial/02-reactivity/02-reactive-declarations/text.md +++ b/site/content/tutorial/02-reactivity/02-reactive-declarations/text.md @@ -11,7 +11,7 @@ let count = 0; $: doubled = count * 2; ``` -> Don't worry if this looks a little alien. It's valid (if unconventional) JavaScript, which Svelte interprets to mean 're-run this code whenever any of the referenced values change'. Once you get used to it, there's no going back. +> Don't worry if this looks a little alien. It's [valid](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label) (if unconventional) JavaScript, which Svelte interprets to mean 're-run this code whenever any of the referenced values change'. Once you get used to it, there's no going back. Let's use `doubled` in our markup: @@ -19,4 +19,4 @@ Let's use `doubled` in our markup: <p>{count} doubled is {doubled}</p> ``` -Of course, you could just write `{count * 2}` in the markup instead — you don't have to use reactive values. Reactive values become particularly valuable when you need to reference them multiple times, or you have values that depend on *other* reactive values. \ No newline at end of file +Of course, you could just write `{count * 2}` in the markup instead — you don't have to use reactive values. Reactive values become particularly valuable when you need to reference them multiple times, or you have values that depend on *other* reactive values. diff --git a/site/content/tutorial/02-reactivity/04-updating-arrays-and-objects/text.md b/site/content/tutorial/02-reactivity/04-updating-arrays-and-objects/text.md index b70b09f728..82e4c91d35 100644 --- a/site/content/tutorial/02-reactivity/04-updating-arrays-and-objects/text.md +++ b/site/content/tutorial/02-reactivity/04-updating-arrays-and-objects/text.md @@ -30,3 +30,12 @@ function addNumber() { numbers[numbers.length] = numbers.length + 1; } ``` + +A simple rule of thumb: the name of the updated variable must appear on the left hand side of the assignment. For example this... + +```js +const foo = obj.foo; +foo.bar = 'baz'; +``` + +...won't update references to `obj.foo.bar`, unless you follow it up with `obj = obj`. \ No newline at end of file diff --git a/site/content/tutorial/05-events/06-dom-event-forwarding/app-a/App.svelte b/site/content/tutorial/05-events/06-dom-event-forwarding/app-a/App.svelte index 1429cae207..e75c78106a 100644 --- a/site/content/tutorial/05-events/06-dom-event-forwarding/app-a/App.svelte +++ b/site/content/tutorial/05-events/06-dom-event-forwarding/app-a/App.svelte @@ -1,9 +1,9 @@ <script> - import FancyButton from './FancyButton.svelte'; + import CustomButton from './CustomButton.svelte'; function handleClick() { alert('clicked'); } </script> -<FancyButton on:click={handleClick}/> \ No newline at end of file +<CustomButton on:click={handleClick}/> \ No newline at end of file diff --git a/site/content/tutorial/05-events/06-dom-event-forwarding/app-a/CustomButton.svelte b/site/content/tutorial/05-events/06-dom-event-forwarding/app-a/CustomButton.svelte new file mode 100644 index 0000000000..0955930b5d --- /dev/null +++ b/site/content/tutorial/05-events/06-dom-event-forwarding/app-a/CustomButton.svelte @@ -0,0 +1,22 @@ +<style> + button { + height: 4rem; + width: 8rem; + background-color: #aaa; + border-color: #f1c40f; + color: #f1c40f; + font-size: 1.25rem; + background-image: linear-gradient(45deg, #f1c40f 50%, transparent 50%); + background-position: 100%; + background-size: 400%; + transition: background 300ms ease-in-out; + } + button:hover { + background-position: 0; + color: #aaa; + } +</style> + +<button> + Click me +</button> \ No newline at end of file diff --git a/site/content/tutorial/05-events/06-dom-event-forwarding/app-a/FancyButton.svelte b/site/content/tutorial/05-events/06-dom-event-forwarding/app-a/FancyButton.svelte deleted file mode 100644 index 9c3ae75809..0000000000 --- a/site/content/tutorial/05-events/06-dom-event-forwarding/app-a/FancyButton.svelte +++ /dev/null @@ -1,15 +0,0 @@ -<style> - button { - font-family: 'Comic Sans MS'; - font-size: 2em; - padding: 0.5em 1em; - color: royalblue; - background: gold; - border-radius: 1em; - box-shadow: 2px 2px 4px rgba(0,0,0,0.5); - } -</style> - -<button> - Click me -</button> \ No newline at end of file diff --git a/site/content/tutorial/05-events/06-dom-event-forwarding/app-b/App.svelte b/site/content/tutorial/05-events/06-dom-event-forwarding/app-b/App.svelte index 1429cae207..e75c78106a 100644 --- a/site/content/tutorial/05-events/06-dom-event-forwarding/app-b/App.svelte +++ b/site/content/tutorial/05-events/06-dom-event-forwarding/app-b/App.svelte @@ -1,9 +1,9 @@ <script> - import FancyButton from './FancyButton.svelte'; + import CustomButton from './CustomButton.svelte'; function handleClick() { alert('clicked'); } </script> -<FancyButton on:click={handleClick}/> \ No newline at end of file +<CustomButton on:click={handleClick}/> \ No newline at end of file diff --git a/site/content/tutorial/05-events/06-dom-event-forwarding/app-b/CustomButton.svelte b/site/content/tutorial/05-events/06-dom-event-forwarding/app-b/CustomButton.svelte new file mode 100644 index 0000000000..f521c1f471 --- /dev/null +++ b/site/content/tutorial/05-events/06-dom-event-forwarding/app-b/CustomButton.svelte @@ -0,0 +1,22 @@ +<style> + button { + height: 4rem; + width: 8rem; + background-color: #aaa; + border-color: #f1c40f; + color: #f1c40f; + font-size: 1.25rem; + background-image: linear-gradient(45deg, #f1c40f 50%, transparent 50%); + background-position: 100%; + background-size: 400%; + transition: background 300ms ease-in-out; + } + button:hover { + background-position: 0; + color: #aaa; + } +</style> + +<button on:click> + Click me +</button> \ No newline at end of file diff --git a/site/content/tutorial/05-events/06-dom-event-forwarding/app-b/FancyButton.svelte b/site/content/tutorial/05-events/06-dom-event-forwarding/app-b/FancyButton.svelte deleted file mode 100644 index 75630ea99c..0000000000 --- a/site/content/tutorial/05-events/06-dom-event-forwarding/app-b/FancyButton.svelte +++ /dev/null @@ -1,15 +0,0 @@ -<style> - button { - font-family: 'Comic Sans MS'; - font-size: 2em; - padding: 0.5em 1em; - color: royalblue; - background: gold; - border-radius: 1em; - box-shadow: 2px 2px 4px rgba(0,0,0,0.5); - } -</style> - -<button on:click> - Click me -</button> \ No newline at end of file diff --git a/site/content/tutorial/05-events/06-dom-event-forwarding/text.md b/site/content/tutorial/05-events/06-dom-event-forwarding/text.md index 0959e1d98b..be9ae77f89 100644 --- a/site/content/tutorial/05-events/06-dom-event-forwarding/text.md +++ b/site/content/tutorial/05-events/06-dom-event-forwarding/text.md @@ -4,7 +4,7 @@ title: DOM event forwarding Event forwarding works for DOM events too. -We want to get notified of clicks on our `<FancyButton>` — to do that, we just need to forward `click` events on the `<button>` element in `FancyButton.svelte`: +We want to get notified of clicks on our `<CustomButton>` — to do that, we just need to forward `click` events on the `<button>` element in `CustomButton.svelte`: ```html <button on:click> diff --git a/site/content/tutorial/06-bindings/10-media-elements/app-a/App.svelte b/site/content/tutorial/06-bindings/10-media-elements/app-a/App.svelte index 4b24316232..40276110f4 100644 --- a/site/content/tutorial/06-bindings/10-media-elements/app-a/App.svelte +++ b/site/content/tutorial/06-bindings/10-media-elements/app-a/App.svelte @@ -14,7 +14,7 @@ showControlsTimeout = setTimeout(() => showControls = false, 2500); showControls = true; - if (e.which !== 1) return; // mouse not down + if (!(e.buttons & 1)) return; // mouse not down if (!duration) return; // video not loaded yet const { left, right } = this.getBoundingClientRect(); @@ -124,4 +124,4 @@ <span class="time">{format(duration)}</span> </div> </div> -</div> \ No newline at end of file +</div> diff --git a/site/content/tutorial/06-bindings/10-media-elements/app-b/App.svelte b/site/content/tutorial/06-bindings/10-media-elements/app-b/App.svelte index 59e3dbe0c7..8712d6718b 100644 --- a/site/content/tutorial/06-bindings/10-media-elements/app-b/App.svelte +++ b/site/content/tutorial/06-bindings/10-media-elements/app-b/App.svelte @@ -14,7 +14,7 @@ showControlsTimeout = setTimeout(() => showControls = false, 2500); showControls = true; - if (e.which !== 1) return; // mouse not down + if (!(e.buttons & 1)) return; // mouse not down if (!duration) return; // video not loaded yet const { left, right } = this.getBoundingClientRect(); diff --git a/site/content/tutorial/06-bindings/10-media-elements/text.md b/site/content/tutorial/06-bindings/10-media-elements/text.md index b86717d9ec..f08f3975d7 100644 --- a/site/content/tutorial/06-bindings/10-media-elements/text.md +++ b/site/content/tutorial/06-bindings/10-media-elements/text.md @@ -24,12 +24,14 @@ Now, when you click on the video, it will update `time`, `duration` and `paused` > Ordinarily on the web, you would track `currentTime` by listening for `timeupdate` events. But these events fire too infrequently, resulting in choppy UI. Svelte does better — it checks `currentTime` using `requestAnimationFrame`. -The complete set of bindings for `<audio>` and `<video>` is as follows — four *readonly* bindings... +The complete set of bindings for `<audio>` and `<video>` is as follows — six *readonly* bindings... * `duration` (readonly) — the total duration of the video, in seconds * `buffered` (readonly) — an array of `{start, end}` objects * `seekable` (readonly) — ditto * `played` (readonly) — ditto +* `seeking` (readonly) — boolean +* `ended` (readonly) — boolean ...and four *two-way* bindings: @@ -37,3 +39,5 @@ The complete set of bindings for `<audio>` and `<video>` is as follows — four * `playbackRate` — how fast to play the video, where `1` is 'normal' * `paused` — this one should be self-explanatory * `volume` — a value between 0 and 1 + +Videos additionally have readonly `videoWidth` and `videoHeight` bindings. \ No newline at end of file diff --git a/site/content/tutorial/06-bindings/11-dimensions/app-a/App.svelte b/site/content/tutorial/06-bindings/11-dimensions/app-a/App.svelte index 59e11c79f0..62e92cd536 100644 --- a/site/content/tutorial/06-bindings/11-dimensions/app-a/App.svelte +++ b/site/content/tutorial/06-bindings/11-dimensions/app-a/App.svelte @@ -8,6 +8,7 @@ <style> input { display: block; } div { display: inline-block; } + span { word-break: break-all; } </style> <input type=range bind:value={size}> diff --git a/site/content/tutorial/06-bindings/11-dimensions/app-b/App.svelte b/site/content/tutorial/06-bindings/11-dimensions/app-b/App.svelte index ca992599c1..920c74d276 100644 --- a/site/content/tutorial/06-bindings/11-dimensions/app-b/App.svelte +++ b/site/content/tutorial/06-bindings/11-dimensions/app-b/App.svelte @@ -8,6 +8,7 @@ <style> input { display: block; } div { display: inline-block; } + span { word-break: break-all; } </style> <input type=range bind:value={size}> diff --git a/site/content/tutorial/06-bindings/12-bind-this/app-a/App.svelte b/site/content/tutorial/06-bindings/12-bind-this/app-a/App.svelte index c85cab9225..d40c45ef6c 100644 --- a/site/content/tutorial/06-bindings/12-bind-this/app-a/App.svelte +++ b/site/content/tutorial/06-bindings/12-bind-this/app-a/App.svelte @@ -43,8 +43,8 @@ width: 100%; height: 100%; background-color: #666; - -webkit-mask: url(logo-mask.svg) 50% 50% no-repeat; - mask: url(logo-mask.svg) 50% 50% no-repeat; + -webkit-mask: url(svelte-logo-mask.svg) 50% 50% no-repeat; + mask: url(svelte-logo-mask.svg) 50% 50% no-repeat; } </style> diff --git a/site/content/tutorial/06-bindings/12-bind-this/app-b/App.svelte b/site/content/tutorial/06-bindings/12-bind-this/app-b/App.svelte index 9a8fabc265..8e4b3c5bef 100644 --- a/site/content/tutorial/06-bindings/12-bind-this/app-b/App.svelte +++ b/site/content/tutorial/06-bindings/12-bind-this/app-b/App.svelte @@ -43,8 +43,8 @@ width: 100%; height: 100%; background-color: #666; - -webkit-mask: url(logo-mask.svg) 50% 50% no-repeat; - mask: url(logo-mask.svg) 50% 50% no-repeat; + -webkit-mask: url(svelte-logo-mask.svg) 50% 50% no-repeat; + mask: url(svelte-logo-mask.svg) 50% 50% no-repeat; } </style> diff --git a/site/content/tutorial/07-lifecycle/03-update/app-a/App.svelte b/site/content/tutorial/07-lifecycle/03-update/app-a/App.svelte index 75fce63ca2..d8c4caabef 100644 --- a/site/content/tutorial/07-lifecycle/03-update/app-a/App.svelte +++ b/site/content/tutorial/07-lifecycle/03-update/app-a/App.svelte @@ -88,6 +88,7 @@ background-color: #0074D9; color: white; border-radius: 1em 1em 0 1em; + word-break: break-all; } </style> diff --git a/site/content/tutorial/07-lifecycle/03-update/app-b/App.svelte b/site/content/tutorial/07-lifecycle/03-update/app-b/App.svelte index 3eb2dceb52..bdf42e28a9 100644 --- a/site/content/tutorial/07-lifecycle/03-update/app-b/App.svelte +++ b/site/content/tutorial/07-lifecycle/03-update/app-b/App.svelte @@ -88,6 +88,7 @@ background-color: #0074D9; color: white; border-radius: 1em 1em 0 1em; + word-break: break-all; } </style> diff --git a/site/content/tutorial/09-motion/01-tweened/text.md b/site/content/tutorial/09-motion/01-tweened/text.md index def011c993..50cd0c2fba 100644 --- a/site/content/tutorial/09-motion/01-tweened/text.md +++ b/site/content/tutorial/09-motion/01-tweened/text.md @@ -28,7 +28,7 @@ Clicking the buttons causes the progress bar to animate to its new value. It's a </script> ``` -> The `svelte/easing` module contains the [Penner easing equations](http://robertpenner.com/easing/), or you can supply your own `p => t` function where `p` and `t` are both values between 0 and 1. +> The `svelte/easing` module contains the [Penner easing equations](https://web.archive.org/web/20190805215728/http://robertpenner.com/easing/), or you can supply your own `p => t` function where `p` and `t` are both values between 0 and 1. The full set of options available to `tweened`: @@ -37,4 +37,4 @@ The full set of options available to `tweened`: * `easing` — a `p => t` function * `interpolate` — a custom `(from, to) => t => value` function for interpolating between arbitrary values. By default, Svelte will interpolate between numbers, dates, and identically-shaped arrays and objects (as long as they only contain numbers and dates or other valid arrays and objects). If you want to interpolate (for example) colour strings or transformation matrices, supply a custom interpolator -You can also pass these options to `progress.set` and `progress.update` as a second argument, in which case they will override the defaults. The `set` and `update` methods both return a promise that resolves when the tween completes. \ No newline at end of file +You can also pass these options to `progress.set` and `progress.update` as a second argument, in which case they will override the defaults. The `set` and `update` methods both return a promise that resolves when the tween completes. diff --git a/site/content/tutorial/12-actions/01-actions/text.md b/site/content/tutorial/12-actions/01-actions/text.md index 38de8f9a65..3706b31e7c 100644 --- a/site/content/tutorial/12-actions/01-actions/text.md +++ b/site/content/tutorial/12-actions/01-actions/text.md @@ -23,7 +23,9 @@ import { pannable } from './pannable.js'; on:panstart={handlePanStart} on:panmove={handlePanMove} on:panend={handlePanEnd} - style="transform: translate({$coords.x}px,{$coords.y}px)" + style="transform: + translate({$coords.x}px,{$coords.y}px) + rotate({$coords.x * 0.2}deg)" ></div> ``` diff --git a/site/content/tutorial/12-actions/02-adding-parameters-to-actions/app-a/App.svelte b/site/content/tutorial/12-actions/02-adding-parameters-to-actions/app-a/App.svelte index 0bd9d56113..8ed286b574 100644 --- a/site/content/tutorial/12-actions/02-adding-parameters-to-actions/app-a/App.svelte +++ b/site/content/tutorial/12-actions/02-adding-parameters-to-actions/app-a/App.svelte @@ -1,70 +1,20 @@ <script> - let language = "english"; + import { longpress } from './longpress.js'; - const translations = { - english: { - tooltip: "Switch Languages", - }, - latin: { - tooltip: "Itchsway Anguageslay", - } - }; - - function tooltip(node, text) { - const tooltip = document.createElement('div'); - tooltip.textContent = text; - - Object.assign(tooltip.style, { - position: 'absolute', - background: 'black', - color: 'white', - padding: '0.5em 1em', - fontSize: '12px', - pointerEvents: 'none', - transform: 'translate(5px, -50%)', - borderRadius: '2px', - transition: 'opacity 0.4s' - }); - - function position() { - const { top, right, bottom } = node.getBoundingClientRect(); - tooltip.style.top = `${(top + bottom) / 2}px`; - tooltip.style.left = `${right}px`; - } - - function append() { - document.body.appendChild(tooltip); - tooltip.style.opacity = 0; - setTimeout(() => tooltip.style.opacity = 1); - position(); - } - - function remove() { - tooltip.remove(); - } - - node.addEventListener('mouseenter', append); - node.addEventListener('mouseleave', remove); - - return { - update(text) { - tooltip.textContent = text; - position(); - }, + let pressed = false; + let duration = 2000; +</script> - destroy() { - tooltip.remove(); - node.removeEventListener('mouseenter', append); - node.removeEventListener('mouseleave', remove); - } - }; - } +<label> + <input type=range bind:value={duration} max={2000} step={100}> + {duration}ms +</label> - function toggleLanguage() { - language = language === 'english' ? 'latin' : 'english' - } -</script> +<button use:longpress + on:longpress="{() => pressed = true}" + on:mouseenter="{() => pressed = false}" +>press and hold</button> -<button on:click={toggleLanguage} use:tooltip={translations[language].tooltip}> - {language} -</button> \ No newline at end of file +{#if pressed} + <p>congratulations, you pressed and held for {duration}ms</p> +{/if} \ No newline at end of file diff --git a/site/content/tutorial/12-actions/02-adding-parameters-to-actions/app-a/longpress.js b/site/content/tutorial/12-actions/02-adding-parameters-to-actions/app-a/longpress.js new file mode 100644 index 0000000000..00bb9d05c8 --- /dev/null +++ b/site/content/tutorial/12-actions/02-adding-parameters-to-actions/app-a/longpress.js @@ -0,0 +1,25 @@ +export function longpress(node, duration) { + let timer; + + const handleMousedown = () => { + timer = setTimeout(() => { + node.dispatchEvent( + new CustomEvent('longpress') + ); + }, 500); + }; + + const handleMouseup = () => { + clearTimeout(timer) + }; + + node.addEventListener('mousedown', handleMousedown); + node.addEventListener('mouseup', handleMouseup); + + return { + destroy() { + node.removeEventListener('mousedown', handleMousedown); + node.removeEventListener('mouseup', handleMouseup); + } + }; +} \ No newline at end of file diff --git a/site/content/tutorial/12-actions/02-adding-parameters-to-actions/app-b/App.svelte b/site/content/tutorial/12-actions/02-adding-parameters-to-actions/app-b/App.svelte index 0bd9d56113..d6eaa0ff12 100644 --- a/site/content/tutorial/12-actions/02-adding-parameters-to-actions/app-b/App.svelte +++ b/site/content/tutorial/12-actions/02-adding-parameters-to-actions/app-b/App.svelte @@ -1,70 +1,20 @@ <script> - let language = "english"; + import { longpress } from './longpress.js'; - const translations = { - english: { - tooltip: "Switch Languages", - }, - latin: { - tooltip: "Itchsway Anguageslay", - } - }; - - function tooltip(node, text) { - const tooltip = document.createElement('div'); - tooltip.textContent = text; - - Object.assign(tooltip.style, { - position: 'absolute', - background: 'black', - color: 'white', - padding: '0.5em 1em', - fontSize: '12px', - pointerEvents: 'none', - transform: 'translate(5px, -50%)', - borderRadius: '2px', - transition: 'opacity 0.4s' - }); - - function position() { - const { top, right, bottom } = node.getBoundingClientRect(); - tooltip.style.top = `${(top + bottom) / 2}px`; - tooltip.style.left = `${right}px`; - } - - function append() { - document.body.appendChild(tooltip); - tooltip.style.opacity = 0; - setTimeout(() => tooltip.style.opacity = 1); - position(); - } - - function remove() { - tooltip.remove(); - } - - node.addEventListener('mouseenter', append); - node.addEventListener('mouseleave', remove); - - return { - update(text) { - tooltip.textContent = text; - position(); - }, + let pressed = false; + let duration = 2000; +</script> - destroy() { - tooltip.remove(); - node.removeEventListener('mouseenter', append); - node.removeEventListener('mouseleave', remove); - } - }; - } +<label> + <input type=range bind:value={duration} max={2000} step={100}> + {duration}ms +</label> - function toggleLanguage() { - language = language === 'english' ? 'latin' : 'english' - } -</script> +<button use:longpress={duration} + on:longpress="{() => pressed = true}" + on:mouseenter="{() => pressed = false}" +>press and hold</button> -<button on:click={toggleLanguage} use:tooltip={translations[language].tooltip}> - {language} -</button> \ No newline at end of file +{#if pressed} + <p>congratulations, you pressed and held for {duration}ms</p> +{/if} \ No newline at end of file diff --git a/site/content/tutorial/12-actions/02-adding-parameters-to-actions/app-b/longpress.js b/site/content/tutorial/12-actions/02-adding-parameters-to-actions/app-b/longpress.js new file mode 100644 index 0000000000..9d807cb13a --- /dev/null +++ b/site/content/tutorial/12-actions/02-adding-parameters-to-actions/app-b/longpress.js @@ -0,0 +1,28 @@ +export function longpress(node, duration) { + let timer; + + const handleMousedown = () => { + timer = setTimeout(() => { + node.dispatchEvent( + new CustomEvent('longpress') + ); + }, duration); + }; + + const handleMouseup = () => { + clearTimeout(timer) + }; + + node.addEventListener('mousedown', handleMousedown); + node.addEventListener('mouseup', handleMouseup); + + return { + update(newDuration) { + duration = newDuration; + }, + destroy() { + node.removeEventListener('mousedown', handleMousedown); + node.removeEventListener('mouseup', handleMouseup); + } + }; +} \ No newline at end of file diff --git a/site/content/tutorial/12-actions/02-adding-parameters-to-actions/text.md b/site/content/tutorial/12-actions/02-adding-parameters-to-actions/text.md index e6262b2f6c..0cb3b7aeca 100644 --- a/site/content/tutorial/12-actions/02-adding-parameters-to-actions/text.md +++ b/site/content/tutorial/12-actions/02-adding-parameters-to-actions/text.md @@ -2,4 +2,45 @@ title: Adding parameters --- -TODO come up with a better example \ No newline at end of file +Like transitions and animations, an action can take an argument, which the action function will be called with alongside the element it belongs to. + +Here, we're using a `longpress` action that fires an event with the same name whenever the user presses and holds the button for a given duration. Right now, if you switch over to the `longpress.js` file, you'll see it's hardcoded to 500ms. + +We can change the action function to accept a `duration` as a second argument, and pass that `duration` to the `setTimeout` call: + +```js +export function longpress(node, duration) { + // ... + + const handleMousedown = () => { + timer = setTimeout(() => { + node.dispatchEvent( + new CustomEvent('longpress') + ); + }, duration); + }; + + // ... +} +``` + +Back in `App.svelte`, we can pass the `duration` value to the action: + +```html +<button use:longpress={duration} +``` + +This *almost* works — the event now only fires after 2 seconds. But if you slide the duration down, it will still take two seconds. + +To change that, we can add an `update` method in `longpress.js`. This will be called whenever the argument changes: + +```js +return { + update(newDuration) { + duration = newDuration; + }, + // ... +}; +``` + +> If you need to pass multiple arguments to an action, combine them into a single object, as in `use:longpress={{duration, spiciness}}` \ No newline at end of file diff --git a/site/content/tutorial/16-special-elements/07-svelte-options/app-a/Todo.svelte b/site/content/tutorial/16-special-elements/07-svelte-options/app-a/Todo.svelte index dae595e7d0..5e0dbca300 100644 --- a/site/content/tutorial/16-special-elements/07-svelte-options/app-a/Todo.svelte +++ b/site/content/tutorial/16-special-elements/07-svelte-options/app-a/Todo.svelte @@ -3,7 +3,6 @@ import flash from './flash.js'; export let todo; - export let toggle; let div; diff --git a/site/content/tutorial/16-special-elements/07-svelte-options/app-b/Todo.svelte b/site/content/tutorial/16-special-elements/07-svelte-options/app-b/Todo.svelte index 447ddc601c..e7ddcedc47 100644 --- a/site/content/tutorial/16-special-elements/07-svelte-options/app-b/Todo.svelte +++ b/site/content/tutorial/16-special-elements/07-svelte-options/app-b/Todo.svelte @@ -5,7 +5,6 @@ import flash from './flash.js'; export let todo; - export let toggle; let div; diff --git a/site/package-lock.json b/site/package-lock.json index 189068b42d..646ca0ce53 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -1256,19 +1256,19 @@ } }, "@polka/redirect": { - "version": "1.0.0-next.0", - "resolved": "https://registry.npmjs.org/@polka/redirect/-/redirect-1.0.0-next.0.tgz", - "integrity": "sha512-ym6ooqMr09+cV+y52p5kszJ0jYcX+nJfm8POrQb7QYowvpPPuneZ71EclHrQSB7a50lcytgR/xtL6AUFdvyEkg==" + "version": "1.0.0-next.7", + "resolved": "https://registry.npmjs.org/@polka/redirect/-/redirect-1.0.0-next.7.tgz", + "integrity": "sha512-sHh1oVy9VBVhn41fOlrUdlxFkcbKrYdBcqePTSxvf2NqKu7UcMPZse/wDeQZk17A8cqDArKsR4m0MXd+3/Q83g==" }, "@polka/send": { - "version": "1.0.0-next.6", - "resolved": "https://registry.npmjs.org/@polka/send/-/send-1.0.0-next.6.tgz", - "integrity": "sha512-4ON4Yf/QcP9I6HmFvn8rspRdBQ6NupSkUvAkUKo4gT2SSSWrrHMqDVQJsvDr4BRGRIVZSg+gr6W3M9Xj3V3JSQ==" + "version": "1.0.0-next.7", + "resolved": "https://registry.npmjs.org/@polka/send/-/send-1.0.0-next.7.tgz", + "integrity": "sha512-X/7sxWMfzuHuMXSls3SuOgfwcoNakuaNWciVS/KX3RML8NIPKQYgbhpqYPCujtXK9Z/KvW3/gzr2TUpabIJRMg==" }, "@polka/url": { - "version": "1.0.0-next.3", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.3.tgz", - "integrity": "sha512-Uom7l6OeP6vcf85lMImelYu5WKVWjXyhkpi9WsRdRzlJFJFPVhjBtBCktgDUj7dk1N5FURUdegSZ5XOjxf8JZg==" + "version": "1.0.0-next.9", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.9.tgz", + "integrity": "sha512-VZqSaulg2kVQYMulmuZcvapPwH5/y81YHANiFIKz1GNZoG/F4o1JSeLlrvXJ8tC+RPUjxdrebfT3Qn+bnMi0bA==" }, "@sindresorhus/slugify": { "version": "0.9.1", @@ -1281,9 +1281,9 @@ } }, "@sveltejs/site-kit": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@sveltejs/site-kit/-/site-kit-1.1.3.tgz", - "integrity": "sha512-cJfz45cqq1nfPnk1V3oYVMcSySI/GnbHyvr+vQAyHhmOpmknO3pYavXDj545YXWJvEXg2sk8Fxcah+Z/56Ka0Q==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@sveltejs/site-kit/-/site-kit-1.1.4.tgz", + "integrity": "sha512-PsFUX1C/fhV0ODdCJaEQ8OwzgmaPJVmdefiSYA+i6zttBeV19d/ow+l7SPMXxBkux+vUIl5can4BwValCukCsw==", "dev": true, "requires": { "@sindresorhus/slugify": "^0.9.1", @@ -1291,17 +1291,24 @@ } }, "@sveltejs/svelte-repl": { - "version": "0.1.9", - "resolved": "https://registry.npmjs.org/@sveltejs/svelte-repl/-/svelte-repl-0.1.9.tgz", - "integrity": "sha512-OXDfHwT5O7UXVYnf4ndTk3dKMITTmWcMty4/lOFte80ui01i47QiVy3GEe9G8FkcU1YBe+c06MMnIgm7j0Ln7Q==", + "version": "0.1.17", + "resolved": "https://registry.npmjs.org/@sveltejs/svelte-repl/-/svelte-repl-0.1.17.tgz", + "integrity": "sha512-rM0DC+pZnqwH6PiuxXUmFRwYZ9XNkexxTNt+prR91Qs7ssxGgf0QkH6kGivSNLbrOtOvcgJbt1nUDybWra5HKA==", "dev": true, "requires": { - "codemirror": "^5.48.4", - "estree-walker": "^0.6.1", + "codemirror": "^5.49.2", + "estree-walker": "^0.9.0", "sourcemap-codec": "^1.4.6", + "svelte-json-tree": "0.0.5", "yootils": "0.0.16" }, "dependencies": { + "estree-walker": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.9.0.tgz", + "integrity": "sha512-12U47o7XHUX329+x3FzNVjCx3SHEzMF0nkDv7r/HnBzX/xNTKxajBk6gyygaxrAFtLj39219oMfbtxv4KpaOiA==", + "dev": true + }, "sourcemap-codec": { "version": "1.4.6", "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.6.tgz", @@ -1587,9 +1594,9 @@ "dev": true }, "codemirror": { - "version": "5.48.4", - "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.48.4.tgz", - "integrity": "sha512-pUhZXDQ6qXSpWdwlgAwHEkd4imA0kf83hINmUEzJpmG80T/XLtDDEzZo8f6PQLuRCcUQhmzqqIo3ZPTRaWByRA==", + "version": "5.49.2", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.49.2.tgz", + "integrity": "sha512-dwJ2HRPHm8w51WB5YTF9J7m6Z5dtkqbU9ntMZ1dqXyFB9IpjoUFDj80ahRVEoVanfIp6pfASJbOlbWdEf8FOzQ==", "dev": true }, "color-convert": { @@ -2510,9 +2517,9 @@ } }, "mime": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.3.tgz", - "integrity": "sha512-QgrPRJfE+riq5TPZMcHZOtm8c6K/yYrMbKIoRfapfiGLxS8OTeIfRhUGW5LU7MlRa52KOAGCfUNruqLrIBvWZw==" + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", + "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==" }, "mimic-fn": { "version": "2.1.0", @@ -3119,11 +3126,11 @@ "dev": true }, "polka": { - "version": "1.0.0-next.6", - "resolved": "https://registry.npmjs.org/polka/-/polka-1.0.0-next.6.tgz", - "integrity": "sha512-e3vZm2cMmPPrgn+0J5DO0rrSTfsCHGyh+YS6jjrqYP8BHJkPq8nCVSDxHkaiEN4f0c2dtR6FB+snDmLE/sRz7A==", + "version": "1.0.0-next.9", + "resolved": "https://registry.npmjs.org/polka/-/polka-1.0.0-next.9.tgz", + "integrity": "sha512-oAWH5O3CIPTzPKNx9KF9NDfy3KRyy9NtUhDEJGmMRCDT6s3CZaGDm7xafcKtm0uK6g0CBiNtoeGWpPFSLUXeaw==", "requires": { - "@polka/url": "^1.0.0-next.3", + "@polka/url": "^1.0.0-next.9", "trouter": "^3.1.0" } }, @@ -3368,12 +3375,6 @@ "requires": { "@babel/helper-module-imports": "^7.0.0", "rollup-pluginutils": "^2.8.1" - }, - "dependencies": { - "estree-walker": { - "version": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", - "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==" - } } }, "rollup-plugin-commonjs": { @@ -3411,10 +3412,6 @@ "rollup-pluginutils": "^2.8.1" }, "dependencies": { - "estree-walker": { - "version": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", - "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==" - }, "resolve": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz", @@ -3458,12 +3455,6 @@ "rollup-pluginutils": "^2.8.1", "serialize-javascript": "^1.7.0", "terser": "^4.1.0" - }, - "dependencies": { - "estree-walker": { - "version": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", - "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==" - } } }, "rollup-pluginutils": { @@ -3473,14 +3464,6 @@ "dev": true, "requires": { "estree-walker": "^0.6.1" - }, - "dependencies": { - "estree-walker": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", - "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", - "dev": true - } } }, "safe-buffer": { @@ -3600,19 +3583,13 @@ "dev": true }, "sirv": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-0.4.2.tgz", - "integrity": "sha512-dQbZnsMaIiTQPZmbGmktz+c74zt/hyrJEB4tdp2Jj0RNv9J6B/OWR5RyrZEvIn9fyh9Zlg2OlE2XzKz6wMKGAw==", + "version": "1.0.0-next.2", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-1.0.0-next.2.tgz", + "integrity": "sha512-hWp0todr4jSb1BFBiANRmqYRXzX02l36/X4tyHPYKqMZ+e1hrDZKUjIIXrAOBRWlAE/G5cGImUciMrUcU8DeOg==", "requires": { - "@polka/url": "^0.5.0", - "mime": "^2.3.1" - }, - "dependencies": { - "@polka/url": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-0.5.0.tgz", - "integrity": "sha512-oZLYFEAzUKyi3SKnXvj32ZCEGH6RDnao7COuCVhDydMS9NrCSVXhM79VaKyP5+Zc33m0QXEd2DN3UkU7OsHcfw==" - } + "@polka/url": "^1.0.0-next.9", + "mime": "^2.3.1", + "totalist": "^1.0.0" } }, "source-map": { @@ -3780,6 +3757,12 @@ "integrity": "sha512-9/broj3bjShrsk3FuVDH0Bho2BchPKT8ubAqRcTqwkqrO9npOS3Vi98Yb5mBaa4bYV+ELTuvPvaQZbCJYMFRdg==", "dev": true }, + "svelte-json-tree": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/svelte-json-tree/-/svelte-json-tree-0.0.5.tgz", + "integrity": "sha512-kTcOVlsldI2neszYNQAfFCt+u62OWWAZgpeoW9RN3hjtJCWI5bkVj0gtljZWUlyEWTfgpmag5L5AHDKg8w8ZmQ==", + "dev": true + }, "tar": { "version": "4.4.10", "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.10.tgz", @@ -3843,6 +3826,11 @@ "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", "dev": true }, + "totalist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-1.0.1.tgz", + "integrity": "sha512-HuAt9bWDCdLkebrIQr+i63NgQSvjeD2VTNUIEBqof/4pG4Gb6omuBOMUX0vF371cbfImXQzmb4Ue/0c9MUWGew==" + }, "trim-right": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", diff --git a/site/package.json b/site/package.json index 3f362ac891..a94d264217 100644 --- a/site/package.json +++ b/site/package.json @@ -7,14 +7,14 @@ "copy-workers": "rm -rf static/workers && cp -r node_modules/@sveltejs/svelte-repl/workers static", "migrate": "node-pg-migrate -r dotenv/config", "sapper": "npm run copy-workers && sapper build --legacy", - "update": "node scripts/update_template.js && node scripts/get-contributors.js", + "update": "node scripts/update_template.js && node scripts/get-contributors.js && node scripts/update_whos_using.js", "start": "node __sapper__/build", "test": "mocha -r esm test/**", "deploy": "make deploy" }, "dependencies": { - "@polka/redirect": "^1.0.0-next.0", - "@polka/send": "^1.0.0-next.6", + "@polka/redirect": "^1.0.0-next.7", + "@polka/send": "^1.0.0-next.7", "cookie": "^0.4.0", "devalue": "^2.0.0", "do-not-zip": "^1.0.0", @@ -23,9 +23,9 @@ "jsonwebtoken": "^8.5.1", "marked": "^0.7.0", "pg": "^7.12.1", - "polka": "^1.0.0-next.6", + "polka": "^1.0.0-next.9", "prismjs": "^1.17.1", - "sirv": "^0.4.2", + "sirv": "^1.0.0-next.2", "yootils": "0.0.16" }, "devDependencies": { @@ -35,8 +35,8 @@ "@babel/preset-env": "^7.6.0", "@babel/runtime": "^7.6.0", "@sindresorhus/slugify": "^0.9.1", - "@sveltejs/site-kit": "^1.1.3", - "@sveltejs/svelte-repl": "^0.1.9", + "@sveltejs/site-kit": "^1.1.4", + "@sveltejs/svelte-repl": "^0.1.17", "degit": "^2.1.4", "dotenv": "^8.1.0", "esm": "^3.2.25", diff --git a/site/rollup.config.js b/site/rollup.config.js index c713be33c1..9cb963a87d 100644 --- a/site/rollup.config.js +++ b/site/rollup.config.js @@ -13,6 +13,9 @@ const mode = process.env.NODE_ENV; const dev = mode === 'development'; const legacy = !!process.env.SAPPER_LEGACY_BUILD; +const onwarn = (warning, onwarn) => (warning.code === 'CIRCULAR_DEPENDENCY' && /[/\\]@sapper[/\\]/.test(warning.message)) || onwarn(warning); +const dedupe = importee => importee === 'svelte' || importee.startsWith('svelte/'); + export default { client: { input: config.client.input(), @@ -28,7 +31,10 @@ export default { hydratable: true, emitCss: true }), - resolve(), + resolve({ + browser: true, + dedupe + }), commonjs(), json(), @@ -53,6 +59,7 @@ export default { module: true }) ], + onwarn }, server: { @@ -67,7 +74,9 @@ export default { generate: 'ssr', dev }), - resolve(), + resolve({ + dedupe + }), commonjs(), json() ], @@ -78,6 +87,7 @@ export default { require('module').builtinModules || Object.keys(process.binding('natives')) ) ], + onwarn }, serviceworker: { diff --git a/site/scripts/update_whos_using.js b/site/scripts/update_whos_using.js new file mode 100644 index 0000000000..131a162359 --- /dev/null +++ b/site/scripts/update_whos_using.js @@ -0,0 +1,12 @@ +const sh = require('shelljs'); + +sh.cd(__dirname + '/../'); + +// fetch community repo +sh.rm('-rf','scripts/community'); +sh.exec('npx degit sveltejs/community scripts/community'); + +// copy over relevant files +sh.cp('scripts/community/whos-using-svelte/WhosUsingSvelte.svelte', 'src/routes/_components/WhosUsingSvelte.svelte'); +sh.rm('-rf', 'static/organisations'); +sh.cp('-r', 'scripts/community/whos-using-svelte/organisations', 'static'); diff --git a/site/src/routes/_components/Contributors.svelte b/site/src/routes/_components/Contributors.svelte new file mode 100644 index 0000000000..74eb3fa50f --- /dev/null +++ b/site/src/routes/_components/Contributors.svelte @@ -0,0 +1,26 @@ +<script> + import contributors from '../_contributors.js'; +</script> + +<style> + .contributor { + width: 2.4em; + height: 2.4em; + border-radius: 50%; + text-indent: -9999px; + display: inline-block; + background: no-repeat url(/contributors.jpg); + background-size: auto 102%; + margin: 0 0.5em 0.5em 0; + border: 2px solid var(--second); + } +</style> + +{#each contributors as contributor, i} + <a + class="contributor" + style="background-position: {(100 * i) / (contributors.length - 1)}% 0" + href="https://github.com/{contributor}"> + {contributor} + </a> +{/each} diff --git a/site/src/routes/_components/WhosUsingSvelte.svelte b/site/src/routes/_components/WhosUsingSvelte.svelte deleted file mode 100644 index 6444596cc8..0000000000 --- a/site/src/routes/_components/WhosUsingSvelte.svelte +++ /dev/null @@ -1,85 +0,0 @@ -<!-- - Instructions for adding new logos: - - * Fork this repo, and clone your fork - * Create a branch called e.g. `add-myorganisation-logo` - * Add the logo to the `static/organisations` directory (preferably SVG) - * Add a new <a> tag in this component, in alphabetical order - * Create a pull request. Thanks! ---> - -<style> - .logos { - margin: 1em 0 0 0; - display: flex; - flex-wrap: wrap; - } - - a { - height: 40px; - margin: 0 0.5em 0.5em 0; - display: flex; - align-items: center; - border: 2px solid var(--second); - padding: 5px 10px; - border-radius: 20px; - color: var(--text); - } - - .add-yourself { - color: var(--prime); - } - - picture, - img { - height: 100%; - } - - @media (min-width: 540px) { - a { - height: 60px; - padding: 10px 20px; - border-radius: 30px; - } - } -</style> - -<div class="logos"> - <a target="_blank" rel="noopener" href="https://bekchy.com"><img src="organisations/bekchy.png" alt="Bekchy logo" loading="lazy"></a> - <a target="_blank" rel="noopener" href="https://beyonk.com"><img src="organisations/beyonk.svg" alt="Beyonk logo" loading="lazy"></a> - <a target="_blank" rel="noopener" href="https://buydotstar.com"><img src="organisations/buydotstar.svg" alt="buy.* logo" loading="lazy"></a> - <a target="_blank" rel="noopener" href="https://chess.com" style="background-color: rgb(49,46,43);"><img src="organisations/chess.svg" alt="Chess.com logo" loading="lazy"></a> - <a target="_blank" rel="noopener" href="https://comigosaude.com.br"><img src="organisations/comigo.svg" alt="Comigo logo" loading="lazy"></a> - <a target="_blank" rel="noopener" href="https://datawrapper.de"><img src="organisations/datawrapper.svg" alt="Datawrapper logo" loading="lazy"></a> - <a target="_blank" rel="noopener" href="https://db.nomics.world" style="background-color: rgb(15,39,47);"><picture><source type="image/webp" srcset="organisations/dbnomics.webp"><img src="organisations/dbnomics.jpg" alt="DBNomics logo" loading="lazy"></picture></a> - <a target="_blank" rel="noopener" href="https://deck.nl"><img src="organisations/deck.svg" alt="Deck logo" loading="lazy"></a> - <a target="_blank" rel="noopener" href="https://dextra.com.br/pt/"><img src="organisations/dextra.png" alt="Dextra logo" loading="lazy"></a> - <a target="_blank" rel="noopener" href="https://www.entriwise.com/"><img src="organisations/entriwise.png" alt="Entriwise logo" loading="lazy"></a> - <a target="_blank" rel="noopener" href="https://from-now-on.com"><img src="organisations/from-now-on.png" alt="From-Now-On logo" loading="lazy"></a> - <a target="_blank" rel="noopener" href="https://fusioncharts.com"><img src="organisations/fusioncharts.svg" alt="FusionCharts logo" loading="lazy"></a> - <a target="_blank" rel="noopener" href="https://godaddy.com"><img src="organisations/godaddy.svg" alt="GoDaddy logo" loading="lazy"></a> - <a target="_blank" rel="noopener" href="https://www.grainger.com"><img src="organisations/grainger.svg" alt="Grainger logo" loading="lazy"></a> - <a target="_blank" rel="noopener" href="http://healthtree.org/"><img src="organisations/healthtree.png" alt="HealthTree logo" loading="lazy"></a> - <a target="_blank" rel="noopener" href="https://itslearning.com"><img src="organisations/itslearning.svg" alt="itslearning logo" loading="lazy"></a> - <a target="_blank" rel="noopener" href="https://www.metrovias.com.ar/"><img src="organisations/metrovias.svg" alt="Metrovias logo" loading="lazy"></a> - <a target="_blank" rel="noopener" href="http://mustlab.ru"><img src="organisations/mustlab.png" alt="Mustlab logo" loading="lazy"></a> - <a target="_blank" rel="noopener" href="https://www.nesta.org.uk"><img src="organisations/nesta.svg" alt="Nesta logo" loading="lazy"></a> - <a target="_blank" rel="noopener" href="https://www.nonkositelecoms.com"><img src="organisations/nonkosi.svg" alt="Nonkosi Telecoms logo" loading="lazy"></a> - <a target="_blank" rel="noopener" href="https://www.nzz.ch"><img src="organisations/nzz.svg" alt="Neue Zürcher Zeitung logo" loading="lazy"></a> - <a target="_blank" rel="noopener" href="https://nytimes.com"><img src="organisations/nyt.svg" alt="The New York Times logo" loading="lazy"></a> - <a target="_blank" rel="noopener" href="https://oberonspace.xyz"><img src="organisations/oberonspace.svg" alt="OberonSPACE logo" loading="lazy"></a> - <a target="_blank" rel="noopener" href="https://ofof.nl"><img src="organisations/ofof.png" alt="Ofof logo" loading="lazy"></a> - <a target="_blank" rel="noopener" href="https://openstate.eu"><img src="organisations/open-state-foundation.svg" alt="Open State Foundation logo" loading="lazy"></a> - <a target="_blank" rel="noopener" href="https://panascais.net"><img src="organisations/panascais.svg" alt="Panascais logo" loading="lazy"></a> - <a target="_blank" rel="noopener" href="https://pankod.com"><img src="organisations/pankod.svg" alt="Pankod logo" loading="lazy"></a> - <a target="_blank" rel="noopener" href="https://razorpay.com"><img src="organisations/razorpay.svg" alt="Razorpay logo" loading="lazy"></a> - <a target="_blank" rel="noopener" href="https://sp.nl"><img src="organisations/socialist-party.svg" alt="Socialist Party logo" loading="lazy"></a> - <a target="_blank" rel="noopener" href="https://www.stone.co"><img src="organisations/stone.svg" alt="Stone Payments logo" loading="lazy"></a> - <a target="_blank" rel="noopener" href="https://www.strixengine.com"><img src="organisations/strixcloud.svg" alt="Strix Cloud logo" loading="lazy"><span>Strix Cloud</span></a> - <a target="_blank" rel="noopener" href="https://sucuri.net" style="background-color: rgb(93, 93, 93);"><img src="organisations/sucuri.png" alt="Sucuri logo" loading="lazy"></a> - <a target="_blank" rel="noopener" href="https://thunderdome.dev"><img src="organisations/thunderdome.svg" alt="Thunderdome logo" loading="lazy"></a> - <a target="_blank" rel="noopener" href="https://m.tokopedia.com"><img src="organisations/tokopedia.png" alt="Tokopedia logo" srcset="organisations/tokopedia.2x.png 2x, organisations/tokopedia.3x.png 3x" loading="lazy"></a> - <a target="_blank" rel="noopener" href="https://webdesq.net"><img src="organisations/webdesq.svg" alt="Webdesq logo" loading="lazy"></a> - <a target="_blank" rel="noopener" href="https://zevvle.com/"><img src="organisations/zevvle.svg" alt="Zevvle logo" loading="lazy"></a> - <a target="_blank" rel="noopener" href="https://github.com/sveltejs/svelte/blob/master/site/src/routes/_components/WhosUsingSvelte.svelte" class="add-yourself"><span>+ your company?</span></a> -</div> diff --git a/site/src/routes/blog/_posts.js b/site/src/routes/blog/_posts.js index d180ebd35e..2c86e13656 100644 --- a/site/src/routes/blog/_posts.js +++ b/site/src/routes/blog/_posts.js @@ -1,11 +1,10 @@ import fs from 'fs'; import path from 'path'; -import { extract_frontmatter, langs, link_renderer } from '@sveltejs/site-kit/utils/markdown.js'; +import { extract_frontmatter, link_renderer } from '@sveltejs/site-kit/utils/markdown.js'; import marked from 'marked'; import { makeSlugProcessor } from '../../utils/slug'; +import { highlight } from '../../utils/highlight'; import { SLUG_PRESERVE_UNICODE } from '../../../config'; -import PrismJS from 'prismjs'; -import 'prismjs/components/prism-bash'; const makeSlug = makeSlugProcessor(SLUG_PRESERVE_UNICODE); @@ -32,16 +31,7 @@ export default function get_posts() { renderer.link = link_renderer; - renderer.code = (source, lang) => { - const plang = langs[lang]; - const highlighted = PrismJS.highlight( - source, - PrismJS.languages[plang], - lang, - ); - - return `<pre class='language-${plang}'><code>${highlighted}</code></pre>`; - }; + renderer.code = highlight; renderer.heading = (text, level, rawtext) => { const fragment = makeSlug(rawtext); diff --git a/site/src/routes/blog/index.svelte b/site/src/routes/blog/index.svelte index 6f96731af0..92fc5ce96d 100644 --- a/site/src/routes/blog/index.svelte +++ b/site/src/routes/blog/index.svelte @@ -11,7 +11,7 @@ <svelte:head> <title>Blog • Svelte - + diff --git a/site/src/routes/docs/_sections.js b/site/src/routes/docs/_sections.js index 35edc16cfa..bb081a050b 100644 --- a/site/src/routes/docs/_sections.js +++ b/site/src/routes/docs/_sections.js @@ -1,11 +1,10 @@ import fs from 'fs'; import path from 'path'; import { SLUG_PRESERVE_UNICODE, SLUG_SEPARATOR } from '../../../config'; -import { extract_frontmatter, extract_metadata, langs, link_renderer } from '@sveltejs/site-kit/utils/markdown.js'; +import { extract_frontmatter, extract_metadata, link_renderer } from '@sveltejs/site-kit/utils/markdown.js'; import { make_session_slug_processor } from '@sveltejs/site-kit/utils/slug'; +import { highlight } from '../../utils/highlight'; import marked from 'marked'; -import PrismJS from 'prismjs'; -import 'prismjs/components/prism-bash'; const blockTypes = [ 'blockquote', @@ -73,14 +72,7 @@ export default function() { if (meta && meta.hidden) return ''; - const plang = langs[lang]; - const highlighted = PrismJS.highlight( - source, - PrismJS.languages[plang], - lang - ); - - const html = `
${prefix}
${highlighted}
`; + const html = `
${prefix}${highlight(source, lang)}
`; if (block_open) { block_open = false; diff --git a/site/src/routes/examples/_TableOfContents.svelte b/site/src/routes/examples/_TableOfContents.svelte index f89a9741ae..d5a8b7240f 100644 --- a/site/src/routes/examples/_TableOfContents.svelte +++ b/site/src/routes/examples/_TableOfContents.svelte @@ -29,34 +29,48 @@ font-weight: 700; } + div { + display: flex; + flex-direction: row; + padding: 0.2rem 3rem; + margin: 0 -3rem; + } + + div.active { + background: rgba(0, 0, 0, 0.15) calc(100% - 3rem) 47% no-repeat + url(/icons/arrow-right.svg); + background-size: 1em 1em; + color: white; + } + + div.active.loading { + background: rgba(0, 0, 0, 0.1) calc(100% - 3rem) 47% no-repeat + url(/icons/loading.svg); + background-size: 1em 1em; + color: white; + } + a { display: flex; + flex: 1 1 auto; position: relative; color: var(--sidebar-text); border-bottom: none; - padding: 0.2rem 3rem; - margin: 0 -3rem; font-size: 1.6rem; align-items: center; justify-content: start; + padding: 0; } a:hover { color: white; } - a.active { - background: rgba(0, 0, 0, 0.15) calc(100% - 3rem) 50% no-repeat - url(/icons/arrow-right.svg); - background-size: 1em 1em; - color: white; - } - - a.active.loading { - background: rgba(0, 0, 0, 0.1) calc(100% - 3rem) 50% no-repeat - url(/icons/loading.svg); - background-size: 1em 1em; - color: white; + .repl-link { + flex: 0 1 auto; + font-size: 1.2rem; + font-weight: 700; + margin-right: 2.5rem; } .thumbnail { @@ -72,27 +86,31 @@ diff --git a/site/src/routes/index.svelte b/site/src/routes/index.svelte index cbbdf43e95..73fbffbc6a 100644 --- a/site/src/routes/index.svelte +++ b/site/src/routes/index.svelte @@ -1,9 +1,9 @@ '; -function get_context(parser: Parser, attributes: Node[], start: number) { +function get_context(parser: Parser, attributes: any[], start: number): string { const context = attributes.find(attribute => attribute.name === 'context'); if (!context) return 'default'; @@ -28,7 +28,7 @@ function get_context(parser: Parser, attributes: Node[], start: number) { return value; } -export default function read_script(parser: Parser, start: number, attributes: Node[]) { +export default function read_script(parser: Parser, start: number, attributes: Node[]): Script { const script_start = parser.index; const script_end = parser.template.indexOf(script_closing_tag, script_start); @@ -37,20 +37,22 @@ export default function read_script(parser: Parser, start: number, attributes: N message: ` + + + +
+
+ +
+
diff --git a/test/css/samples/omit-scoping-attribute-global-descendants/expected.css b/test/css/samples/omit-scoping-attribute-global-descendants/expected.css new file mode 100644 index 0000000000..c1fd7da897 --- /dev/null +++ b/test/css/samples/omit-scoping-attribute-global-descendants/expected.css @@ -0,0 +1 @@ +html body .root.svelte-xyz p.svelte-xyz{color:red} \ No newline at end of file diff --git a/test/css/samples/omit-scoping-attribute-global-descendants/expected.html b/test/css/samples/omit-scoping-attribute-global-descendants/expected.html new file mode 100644 index 0000000000..3750091bc7 --- /dev/null +++ b/test/css/samples/omit-scoping-attribute-global-descendants/expected.html @@ -0,0 +1,5 @@ +
+
+

hello

+
+
\ No newline at end of file diff --git a/test/css/samples/omit-scoping-attribute-global-descendants/input.svelte b/test/css/samples/omit-scoping-attribute-global-descendants/input.svelte new file mode 100644 index 0000000000..7c9782ebad --- /dev/null +++ b/test/css/samples/omit-scoping-attribute-global-descendants/input.svelte @@ -0,0 +1,16 @@ + + + + +
+
+

hello

+
+
diff --git a/test/css/samples/omit-scoping-attribute-multiple-descendants/expected.css b/test/css/samples/omit-scoping-attribute-multiple-descendants/expected.css new file mode 100644 index 0000000000..5452f68073 --- /dev/null +++ b/test/css/samples/omit-scoping-attribute-multiple-descendants/expected.css @@ -0,0 +1 @@ +.root.svelte-xyz p.svelte-xyz{color:red} \ No newline at end of file diff --git a/test/css/samples/omit-scoping-attribute-multiple-descendants/expected.html b/test/css/samples/omit-scoping-attribute-multiple-descendants/expected.html new file mode 100644 index 0000000000..3750091bc7 --- /dev/null +++ b/test/css/samples/omit-scoping-attribute-multiple-descendants/expected.html @@ -0,0 +1,5 @@ +
+
+

hello

+
+
\ No newline at end of file diff --git a/test/css/samples/omit-scoping-attribute-multiple-descendants/input.svelte b/test/css/samples/omit-scoping-attribute-multiple-descendants/input.svelte new file mode 100644 index 0000000000..dc77a6c794 --- /dev/null +++ b/test/css/samples/omit-scoping-attribute-multiple-descendants/input.svelte @@ -0,0 +1,16 @@ + + + + +
+
+

hello

+
+
diff --git a/test/css/samples/preserve-specificity/expected.css b/test/css/samples/preserve-specificity/expected.css new file mode 100644 index 0000000000..1d4f54820f --- /dev/null +++ b/test/css/samples/preserve-specificity/expected.css @@ -0,0 +1 @@ +a.svelte-xyz b c span.svelte-xyz{color:red;font-size:2em;font-family:'Comic Sans MS'}.foo.svelte-xyz.svelte-xyz{color:green} \ No newline at end of file diff --git a/test/css/samples/preserve-specificity/expected.html b/test/css/samples/preserve-specificity/expected.html new file mode 100644 index 0000000000..171d90d362 --- /dev/null +++ b/test/css/samples/preserve-specificity/expected.html @@ -0,0 +1,12 @@ + + + + + Big red Comic Sans + + + Big red Comic Sans + + + + \ No newline at end of file diff --git a/test/css/samples/preserve-specificity/input.svelte b/test/css/samples/preserve-specificity/input.svelte new file mode 100644 index 0000000000..1c0a594145 --- /dev/null +++ b/test/css/samples/preserve-specificity/input.svelte @@ -0,0 +1,24 @@ + + + + + + Big red Comic Sans + + + Big red Comic Sans + + + + + + \ No newline at end of file diff --git a/test/css/samples/undefined-with-scope/expected.css b/test/css/samples/undefined-with-scope/expected.css new file mode 100644 index 0000000000..5d8d69ac33 --- /dev/null +++ b/test/css/samples/undefined-with-scope/expected.css @@ -0,0 +1 @@ +p.svelte-xyz{color:red} \ No newline at end of file diff --git a/test/css/samples/undefined-with-scope/expected.html b/test/css/samples/undefined-with-scope/expected.html new file mode 100644 index 0000000000..ddb9429bc8 --- /dev/null +++ b/test/css/samples/undefined-with-scope/expected.html @@ -0,0 +1 @@ +

Foo

\ No newline at end of file diff --git a/test/css/samples/undefined-with-scope/input.svelte b/test/css/samples/undefined-with-scope/input.svelte new file mode 100644 index 0000000000..c68fb40dea --- /dev/null +++ b/test/css/samples/undefined-with-scope/input.svelte @@ -0,0 +1,3 @@ + + +

Foo

\ No newline at end of file diff --git a/test/css/samples/unused-selector-string-concat/_config.js b/test/css/samples/unused-selector-string-concat/_config.js new file mode 100644 index 0000000000..81318fd3ac --- /dev/null +++ b/test/css/samples/unused-selector-string-concat/_config.js @@ -0,0 +1,143 @@ +export default { + warnings: [ + { + code: 'css-unused-selector', + message: 'Unused CSS selector', + frame: + ` 9: `, + start: { line: 28, column: 2, character: 595 }, + end: { line: 28, column: 9, character: 602 }, + pos: 595, + }, + ], +}; diff --git a/test/css/samples/unused-selector-string-concat/expected.css b/test/css/samples/unused-selector-string-concat/expected.css new file mode 100644 index 0000000000..756c2eecae --- /dev/null +++ b/test/css/samples/unused-selector-string-concat/expected.css @@ -0,0 +1 @@ +.foo.svelte-xyz{color:red}.foocc.svelte-xyz{color:red}.aa.svelte-xyz{color:red}.bb.svelte-xyz{color:red}.cc.svelte-xyz{color:red}.dd.svelte-xyz{color:red}.aabar.svelte-xyz{color:red}.fooddbar.svelte-xyz{color:red}.baz.svelte-xyz{color:red} \ No newline at end of file diff --git a/test/css/samples/unused-selector-string-concat/input.svelte b/test/css/samples/unused-selector-string-concat/input.svelte new file mode 100644 index 0000000000..0f69463e78 --- /dev/null +++ b/test/css/samples/unused-selector-string-concat/input.svelte @@ -0,0 +1,29 @@ + + +
+ some stuff +
+ + \ No newline at end of file diff --git a/test/css/samples/unused-selector-ternary-bailed/_config.js b/test/css/samples/unused-selector-ternary-bailed/_config.js new file mode 100644 index 0000000000..e5f82e4a85 --- /dev/null +++ b/test/css/samples/unused-selector-ternary-bailed/_config.js @@ -0,0 +1,3 @@ +export default { + warnings: [], +}; diff --git a/test/css/samples/unused-selector-ternary-bailed/expected.css b/test/css/samples/unused-selector-ternary-bailed/expected.css new file mode 100644 index 0000000000..042d33f3cc --- /dev/null +++ b/test/css/samples/unused-selector-ternary-bailed/expected.css @@ -0,0 +1 @@ +.thing.svelte-xyz{color:blue}.active.svelte-xyz{color:blue}.thing.active.svelte-xyz{color:blue}.hover.svelte-xyz{color:blue}.hover.unused.svelte-xyz{color:blue}.unused.svelte-xyz{color:blue} \ No newline at end of file diff --git a/test/css/samples/unused-selector-ternary-bailed/input.svelte b/test/css/samples/unused-selector-ternary-bailed/input.svelte new file mode 100644 index 0000000000..f9af44ec8b --- /dev/null +++ b/test/css/samples/unused-selector-ternary-bailed/input.svelte @@ -0,0 +1,18 @@ + + +
+ some stuff +
+ + \ No newline at end of file diff --git a/test/css/samples/unused-selector-ternary-concat/_config.js b/test/css/samples/unused-selector-ternary-concat/_config.js new file mode 100644 index 0000000000..5015fccb25 --- /dev/null +++ b/test/css/samples/unused-selector-ternary-concat/_config.js @@ -0,0 +1,25 @@ +export default { + warnings: [ + { + code: 'css-unused-selector', + end: { + character: 205, + column: 9, + line: 14, + }, + frame: ` + 12: .thing.active {color: blue;} + 13: + 14: .unused {color: blue;} + ^ + 15: `, + message: 'Unused CSS selector', + pos: 198, + start: { + character: 198, + column: 2, + line: 14, + }, + }, + ], +}; diff --git a/test/css/samples/unused-selector-ternary-concat/expected.css b/test/css/samples/unused-selector-ternary-concat/expected.css new file mode 100644 index 0000000000..8142a20e83 --- /dev/null +++ b/test/css/samples/unused-selector-ternary-concat/expected.css @@ -0,0 +1 @@ +.thing.svelte-xyz{color:blue}.active.svelte-xyz{color:blue}.thing.active.svelte-xyz{color:blue} \ No newline at end of file diff --git a/test/css/samples/unused-selector-ternary-concat/input.svelte b/test/css/samples/unused-selector-ternary-concat/input.svelte new file mode 100644 index 0000000000..8db417c928 --- /dev/null +++ b/test/css/samples/unused-selector-ternary-concat/input.svelte @@ -0,0 +1,15 @@ + + +
+ some stuff +
+ + \ No newline at end of file diff --git a/test/css/samples/unused-selector-ternary-nested/_config.js b/test/css/samples/unused-selector-ternary-nested/_config.js new file mode 100644 index 0000000000..afee5ac822 --- /dev/null +++ b/test/css/samples/unused-selector-ternary-nested/_config.js @@ -0,0 +1,31 @@ +export default { + warnings: [ + { + code: 'css-unused-selector', + message: 'Unused CSS selector', + frame: ` + 13: .thing.active {color: blue;} + 14: .hover { color: blue; } + 15: .hover.unused { color: blue; } + ^ + 16: + 17: .unused {color: blue;}`, + start: { line: 15, column: 2, character: 261 }, + end: { line: 15, column: 15, character: 274 }, + pos: 261, + }, + { + code: 'css-unused-selector', + message: 'Unused CSS selector', + frame: ` + 15: .hover.unused { color: blue; } + 16: + 17: .unused {color: blue;} + ^ + 18: `, + start: { line: 17, column: 2, character: 295 }, + end: { line: 17, column: 9, character: 302 }, + pos: 295, + }, + ], +}; diff --git a/test/css/samples/unused-selector-ternary-nested/expected.css b/test/css/samples/unused-selector-ternary-nested/expected.css new file mode 100644 index 0000000000..85a95ad23e --- /dev/null +++ b/test/css/samples/unused-selector-ternary-nested/expected.css @@ -0,0 +1 @@ +.thing.svelte-xyz{color:blue}.active.svelte-xyz{color:blue}.thing.active.svelte-xyz{color:blue}.hover.svelte-xyz{color:blue} \ No newline at end of file diff --git a/test/css/samples/unused-selector-ternary-nested/input.svelte b/test/css/samples/unused-selector-ternary-nested/input.svelte new file mode 100644 index 0000000000..a7a8f0e02a --- /dev/null +++ b/test/css/samples/unused-selector-ternary-nested/input.svelte @@ -0,0 +1,18 @@ + + +
+ some stuff +
+ + \ No newline at end of file diff --git a/test/custom-elements/assert.js b/test/custom-elements/assert.js index 79aba6c736..0edbd31124 100644 --- a/test/custom-elements/assert.js +++ b/test/custom-elements/assert.js @@ -1,3 +1,29 @@ +export function deepEqual(a, b, message) { + if (!is_equal(a, b)) { + throw new Error(message || `Expected ${JSON.stringify(a)} to equal ${JSON.stringify(b)}`); + } +} + +function is_equal(a, b) { + if (a && typeof a === 'object') { + const is_array = Array.isArray(a); + if (Array.isArray(b) !== is_array) return false; + + if (is_array) { + if (a.length !== b.length) return false; + return a.every((value, i) => is_equal(value, b[i])); + } + + const a_keys = Object.keys(a).sort(); + const b_keys = Object.keys(b).sort(); + if (a_keys.join(',') !== b_keys.join(',')) return false; + + return a_keys.every(key => is_equal(a[key], b[key])); + } + + return a === b; +} + export function equal(a, b, message) { if (a != b) throw new Error(message || `Expected ${a} to equal ${b}`); } diff --git a/test/custom-elements/index.js b/test/custom-elements/index.js index 9255d33c0e..d68d3b94c5 100644 --- a/test/custom-elements/index.js +++ b/test/custom-elements/index.js @@ -2,7 +2,7 @@ import * as fs from 'fs'; import * as path from 'path'; import * as http from 'http'; import { rollup } from 'rollup'; -import * as virtual from 'rollup-plugin-virtual'; +import * as virtual from '@rollup/plugin-virtual'; import * as puppeteer from 'puppeteer'; import { addLineNumbers, loadConfig, loadSvelte } from "../helpers.js"; import { deepEqual } from 'assert'; @@ -14,7 +14,7 @@ const page = ` `; -const assert = fs.readFileSync('test/custom-elements/assert.js', 'utf-8'); +const assert = fs.readFileSync(`${__dirname}/assert.js`, 'utf-8'); describe('custom-elements', function() { this.timeout(10000); @@ -53,7 +53,7 @@ describe('custom-elements', function() { await browser.close(); }); - fs.readdirSync('test/custom-elements/samples').forEach(dir => { + fs.readdirSync(`${__dirname}/samples`).forEach(dir => { if (dir[0] === '.') return; const solo = /\.solo$/.test(dir); @@ -67,7 +67,7 @@ describe('custom-elements', function() { const expected_warnings = config.warnings || []; const bundle = await rollup({ - input: `test/custom-elements/samples/${dir}/test.js`, + input: `${__dirname}/samples/${dir}/test.js`, plugins: [ { resolveId(importee) { @@ -109,6 +109,11 @@ describe('custom-elements', function() { console[type](...args); }); + page.on('error', error => { + console.log('>>> an error happened'); + console.error(error); + }); + try { await page.goto('http://localhost:6789'); diff --git a/test/custom-elements/samples/extended-builtin/_config.js b/test/custom-elements/samples/extended-builtin/_config.js index 08580e780a..cbd57acc65 100644 --- a/test/custom-elements/samples/extended-builtin/_config.js +++ b/test/custom-elements/samples/extended-builtin/_config.js @@ -2,15 +2,15 @@ export default { warnings: [{ code: "avoid-is", message: "The 'is' attribute is not supported cross-browser and should be avoided", - pos: 97, + pos: 98, start: { - character: 97, + character: 98, column: 8, line: 7 }, end: { - character: 114, - column: 25, + character: 116, + column: 26, line: 7 } }] diff --git a/test/custom-elements/samples/extended-builtin/custom-button.js b/test/custom-elements/samples/extended-builtin/custom-button.js new file mode 100644 index 0000000000..9134b2af9f --- /dev/null +++ b/test/custom-elements/samples/extended-builtin/custom-button.js @@ -0,0 +1,2 @@ +class CustomButton extends HTMLButtonElement {} +customElements.define('custom-button', CustomButton, { extends: 'button' }); \ No newline at end of file diff --git a/test/custom-elements/samples/extended-builtin/fancy-button.js b/test/custom-elements/samples/extended-builtin/fancy-button.js deleted file mode 100644 index eaa7d84135..0000000000 --- a/test/custom-elements/samples/extended-builtin/fancy-button.js +++ /dev/null @@ -1,2 +0,0 @@ -class FancyButton extends HTMLButtonElement {} -customElements.define('fancy-button', FancyButton, { extends: 'button' }); \ No newline at end of file diff --git a/test/custom-elements/samples/extended-builtin/main.svelte b/test/custom-elements/samples/extended-builtin/main.svelte index 0919d9585e..3f1b59db53 100644 --- a/test/custom-elements/samples/extended-builtin/main.svelte +++ b/test/custom-elements/samples/extended-builtin/main.svelte @@ -1,7 +1,7 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/test/custom-elements/samples/extended-builtin/test.js b/test/custom-elements/samples/extended-builtin/test.js index d676fd137b..3886ae1149 100644 --- a/test/custom-elements/samples/extended-builtin/test.js +++ b/test/custom-elements/samples/extended-builtin/test.js @@ -11,5 +11,5 @@ export default function (target) { const el = target.querySelector('custom-element'); const button = el.shadowRoot.querySelector('button'); - assert.ok(button instanceof customElements.get('fancy-button')); + assert.ok(button instanceof customElements.get('custom-button')); } \ No newline at end of file diff --git a/test/custom-elements/samples/no-missing-prop-warnings/test.js b/test/custom-elements/samples/no-missing-prop-warnings/test.js index e7ced25e19..1909e7aef9 100644 --- a/test/custom-elements/samples/no-missing-prop-warnings/test.js +++ b/test/custom-elements/samples/no-missing-prop-warnings/test.js @@ -11,8 +11,9 @@ export default function (target) { target.innerHTML = ''; - assert.equal(warnings.length, 1); - assert.equal(warnings[0], ` was created without expected prop 'bar'`); + assert.deepEqual(warnings, [ + ` was created without expected prop 'bar'` + ]); console.warn = warn; } \ No newline at end of file diff --git a/test/helpers.js b/test/helpers.js index e0c4c980ee..a764d43f96 100644 --- a/test/helpers.js +++ b/test/helpers.js @@ -1,6 +1,7 @@ import * as jsdom from 'jsdom'; import * as assert from 'assert'; import * as glob from 'tiny-glob/sync.js'; +import * as path from 'path'; import * as fs from 'fs'; import * as colors from 'kleur'; @@ -44,22 +45,36 @@ export function tryToReadFile(file) { } } +export function cleanRequireCache() { + Object.keys(require.cache) + .filter(x => x.endsWith('.svelte')) + .forEach(file => delete require.cache[file]); +} + const virtualConsole = new jsdom.VirtualConsole(); virtualConsole.sendTo(console); -global.window = new jsdom.JSDOM('
', {virtualConsole}).window; +const window = new jsdom.JSDOM('
', {virtualConsole}).window; global.document = window.document; global.navigator = window.navigator; global.getComputedStyle = window.getComputedStyle; global.requestAnimationFrame = null; // placeholder, filled in using set_raf +global.window = window; // add missing ecmascript globals to window for (const key of Object.getOwnPropertyNames(global)) { window[key] = window[key] || global[key]; } +// implement mock scroll +window.scrollTo = function(pageXOffset, pageYOffset) { + window.pageXOffset = pageXOffset; + window.pageYOffset = pageYOffset; +}; + export function env() { window.document.title = ''; + window.document.head.innerHTML = ''; window.document.body.innerHTML = '
'; return window; @@ -182,62 +197,64 @@ export function showOutput(cwd, options = {}, compile = svelte.compile) { glob('**/*.svelte', { cwd }).forEach(file => { if (file[0] === '_') return; - const { js } = compile( - fs.readFileSync(`${cwd}/${file}`, 'utf-8'), - Object.assign(options, { - filename: file - }) - ); + try { + const { js } = compile( + fs.readFileSync(`${cwd}/${file}`, 'utf-8'), + Object.assign(options, { + filename: file + }) + ); - console.log( // eslint-disable-line no-console - `\n>> ${colors.cyan().bold(file)}\n${addLineNumbers(js.code)}\n<< ${colors.cyan().bold(file)}` - ); + console.log( // eslint-disable-line no-console + `\n>> ${colors.cyan().bold(file)}\n${addLineNumbers(js.code)}\n<< ${colors.cyan().bold(file)}` + ); + } catch (err) { + console.log(`failed to generate output: ${err.message}`); + } }); } -const start = /\n(\t+)/; -export function deindent(strings, ...values) { - const indentation = start.exec(strings[0])[1]; - const pattern = new RegExp(`^${indentation}`, 'gm'); +export function shouldUpdateExpected() { + return process.argv.includes('--update'); +} - let result = strings[0].replace(start, '').replace(pattern, ''); +export function spaces(i) { + let result = ''; + while (i--) result += ' '; + return result; +} - let trailingIndentation = getTrailingIndentation(result); +// fake timers +const original_set_timeout = global.setTimeout; - for (let i = 1; i < strings.length; i += 1) { - let expression = values[i - 1]; - const string = strings[i].replace(pattern, ''); +export function useFakeTimers() { + const callbacks = []; - if (Array.isArray(expression)) { - expression = expression.length ? expression.join('\n') : null; - } + global.setTimeout = function(fn) { + callbacks.push(fn); + }; - if (expression || expression === '') { - const value = String(expression).replace( - /\n/g, - `\n${trailingIndentation}` - ); - result += value + string; - } else { - let c = result.length; - while (/\s/.test(result[c - 1])) c -= 1; - result = result.slice(0, c) + string; + return { + flush() { + callbacks.forEach(fn => fn()); + callbacks.splice(0, callbacks.length); + }, + removeFakeTimers() { + callbacks.splice(0, callbacks.length); + global.setTimeout = original_set_timeout; } - - trailingIndentation = getTrailingIndentation(result); - } - - return result.trim().replace(/\t+$/gm, ''); + }; } -function getTrailingIndentation(str) { - let i = str.length; - while (str[i - 1] === ' ' || str[i - 1] === '\t') i -= 1; - return str.slice(i, str.length); -} +export function mkdirp(dir) { + const parent = path.dirname(dir); + if (parent === dir) return; -export function spaces(i) { - let result = ''; - while (i--) result += ' '; - return result; -} + mkdirp(parent); + + try { + fs.mkdirSync(dir); + } catch (err) { + // do nothing + } +} \ No newline at end of file diff --git a/test/hydration/index.js b/test/hydration/index.js index 856052d69e..f57a0cdc1a 100644 --- a/test/hydration/index.js +++ b/test/hydration/index.js @@ -7,7 +7,8 @@ import { loadConfig, loadSvelte, env, - setupHtmlEqual + setupHtmlEqual, + shouldUpdateExpected } from '../helpers.js'; let compileOptions = null; @@ -41,13 +42,14 @@ describe('hydration', () => { if (dir[0] === '.') return; const config = loadConfig(`./hydration/samples/${dir}/_config.js`); + const solo = config.solo || /\.solo/.test(dir); - if (config.solo && process.env.CI) { + if (solo && process.env.CI) { throw new Error('Forgot to remove `solo: true` from test'); } - (config.skip ? it.skip : config.solo ? it.only : it)(dir, () => { - const cwd = path.resolve(`test/hydration/samples/${dir}`); + (config.skip ? it.skip : solo ? it.only : it)(dir, () => { + const cwd = path.resolve(`${__dirname}/samples/${dir}`); compileOptions = config.compileOptions || {}; @@ -65,8 +67,16 @@ describe('hydration', () => { } const target = window.document.body; + const head = window.document.head; + target.innerHTML = fs.readFileSync(`${cwd}/_before.html`, 'utf-8'); + let before_head; + try { + before_head = fs.readFileSync(`${cwd}/_before_head.html`, 'utf-8'); + head.innerHTML = before_head; + } catch (err) {} + const snapshot = config.snapshot ? config.snapshot(target) : {}; const component = new SvelteComponent({ @@ -75,7 +85,29 @@ describe('hydration', () => { props: config.props }); - assert.htmlEqual(target.innerHTML, fs.readFileSync(`${cwd}/_after.html`, 'utf-8')); + try { + assert.htmlEqual(target.innerHTML, fs.readFileSync(`${cwd}/_after.html`, 'utf-8')); + } catch (error) { + if (shouldUpdateExpected()) { + fs.writeFileSync(`${cwd}/_after.html`, target.innerHTML); + console.log(`Updated ${cwd}/_after.html.`); + } else { + throw error; + } + } + + if (before_head) { + try { + assert.htmlEqual(head.innerHTML, fs.readFileSync(`${cwd}/_after_head.html`, 'utf-8')); + } catch (error) { + if (shouldUpdateExpected()) { + fs.writeFileSync(`${cwd}/_after_head.html`, head.innerHTML); + console.log(`Updated ${cwd}/_after_head.html.`); + } else { + throw error; + } + } + } if (config.test) { config.test(assert, target, snapshot, component, window); @@ -96,7 +128,7 @@ describe('hydration', () => { }); } - fs.readdirSync('test/hydration/samples').forEach(dir => { + fs.readdirSync(`${__dirname}/samples`).forEach(dir => { runTest(dir, null); }); }); diff --git a/test/hydration/samples/each-else/_after.html b/test/hydration/samples/each-else/_after.html new file mode 100644 index 0000000000..7920500ec3 --- /dev/null +++ b/test/hydration/samples/each-else/_after.html @@ -0,0 +1,4 @@ +

Hello, world

+

+ weird +

\ No newline at end of file diff --git a/test/hydration/samples/each-else/_before.html b/test/hydration/samples/each-else/_before.html new file mode 100644 index 0000000000..7920500ec3 --- /dev/null +++ b/test/hydration/samples/each-else/_before.html @@ -0,0 +1,4 @@ +

Hello, world

+

+ weird +

\ No newline at end of file diff --git a/test/hydration/samples/each-else/main.svelte b/test/hydration/samples/each-else/main.svelte new file mode 100644 index 0000000000..64d3a37c58 --- /dev/null +++ b/test/hydration/samples/each-else/main.svelte @@ -0,0 +1,15 @@ + + +

Hello, {name}

+{#each array as elem} +

+ item +

+{:else} +

+ weird +

+{/each} diff --git a/test/hydration/samples/element-attribute-removed/_before.html b/test/hydration/samples/element-attribute-removed/_before.html index c6a8a8c95d..80c0591a4d 100644 --- a/test/hydration/samples/element-attribute-removed/_before.html +++ b/test/hydration/samples/element-attribute-removed/_before.html @@ -1 +1 @@ -
\ No newline at end of file +
\ No newline at end of file diff --git a/test/hydration/samples/head-meta-hydrate-duplicate/_after.html b/test/hydration/samples/head-meta-hydrate-duplicate/_after.html new file mode 100644 index 0000000000..3e5b375f0a --- /dev/null +++ b/test/hydration/samples/head-meta-hydrate-duplicate/_after.html @@ -0,0 +1 @@ +
Just a dummy page.
\ No newline at end of file diff --git a/test/hydration/samples/head-meta-hydrate-duplicate/_after_head.html b/test/hydration/samples/head-meta-hydrate-duplicate/_after_head.html new file mode 100644 index 0000000000..10cf2c8b9a --- /dev/null +++ b/test/hydration/samples/head-meta-hydrate-duplicate/_after_head.html @@ -0,0 +1,4 @@ +Some Title + + + \ No newline at end of file diff --git a/test/hydration/samples/head-meta-hydrate-duplicate/_before.html b/test/hydration/samples/head-meta-hydrate-duplicate/_before.html new file mode 100644 index 0000000000..3e5b375f0a --- /dev/null +++ b/test/hydration/samples/head-meta-hydrate-duplicate/_before.html @@ -0,0 +1 @@ +
Just a dummy page.
\ No newline at end of file diff --git a/test/hydration/samples/head-meta-hydrate-duplicate/_before_head.html b/test/hydration/samples/head-meta-hydrate-duplicate/_before_head.html new file mode 100644 index 0000000000..107753cdd0 --- /dev/null +++ b/test/hydration/samples/head-meta-hydrate-duplicate/_before_head.html @@ -0,0 +1,4 @@ +Some Title + + + \ No newline at end of file diff --git a/test/hydration/samples/head-meta-hydrate-duplicate/_config.js b/test/hydration/samples/head-meta-hydrate-duplicate/_config.js new file mode 100644 index 0000000000..482efd564d --- /dev/null +++ b/test/hydration/samples/head-meta-hydrate-duplicate/_config.js @@ -0,0 +1,5 @@ +export default { + test(assert, target, snapshot, component, window) { + assert.equal(window.document.querySelectorAll('meta').length, 2); + } +}; diff --git a/test/hydration/samples/head-meta-hydrate-duplicate/main.svelte b/test/hydration/samples/head-meta-hydrate-duplicate/main.svelte new file mode 100644 index 0000000000..1a8b125dd2 --- /dev/null +++ b/test/hydration/samples/head-meta-hydrate-duplicate/main.svelte @@ -0,0 +1,8 @@ + + Some Title + + + + + +
Just a dummy page.
\ No newline at end of file diff --git a/test/js/index.js b/test/js/index.js index 14d73d6c65..d4ea13ad98 100644 --- a/test/js/index.js +++ b/test/js/index.js @@ -1,10 +1,11 @@ import * as assert from "assert"; import * as fs from "fs"; import * as path from "path"; -import { loadConfig, svelte } from "../helpers.js"; +import * as colors from "kleur"; +import { loadConfig, svelte, shouldUpdateExpected } from "../helpers.js"; describe("js", () => { - fs.readdirSync("test/js/samples").forEach(dir => { + fs.readdirSync(`${__dirname}/samples`).forEach(dir => { if (dir[0] === ".") return; // add .solo to a sample directory name to only run that test @@ -14,11 +15,17 @@ describe("js", () => { throw new Error("Forgot to remove `solo: true` from test"); } + const resolved = path.resolve(`${__dirname}/samples`, dir); + + if (!fs.existsSync(`${resolved}/input.svelte`)) { + console.log(colors.red().bold(`Missing file ${dir}/input.svelte. If you recently switched branches you may need to delete this directory`)); + return; + } + (solo ? it.only : it)(dir, () => { - dir = path.resolve("test/js/samples", dir); - const config = loadConfig(`${dir}/_config.js`); + const config = loadConfig(`${resolved}/_config.js`); - const input = fs.readFileSync(`${dir}/input.svelte`, "utf-8").replace(/\s+$/, ""); + const input = fs.readFileSync(`${resolved}/input.svelte`, "utf-8").replace(/\s+$/, ""); let actual; @@ -31,15 +38,35 @@ describe("js", () => { throw err; } - const output = `${dir}/_actual.js`; + const output = `${resolved}/_actual.js`; fs.writeFileSync(output, actual); - const expected = fs.readFileSync(`${dir}/expected.js`, "utf-8"); + const expectedPath = `${resolved}/expected.js`; + + let expected = ''; + try { + expected = fs.readFileSync(expectedPath, "utf-8"); + } catch (error) { + console.log(error); + if (error.code === 'ENOENT') { + // missing expected.js + fs.writeFileSync(expectedPath, actual); + } + } - assert.equal( - actual.trim().replace(/^[ \t]+$/gm, ""), - expected.trim().replace(/^[ \t]+$/gm, "") - ); + try { + assert.equal( + actual.trim().replace(/^[ \t]+$/gm, ""), + expected.trim().replace(/^[ \t]+$/gm, "") + ); + } catch (error) { + if (shouldUpdateExpected()) { + fs.writeFileSync(expectedPath, actual); + console.log(`Updated ${expectedPath}.`); + } else { + throw error; + } + } }); }); }); diff --git a/test/js/samples/action-custom-event-handler/expected.js b/test/js/samples/action-custom-event-handler/expected.js index 34d5ca10aa..ead6d90e06 100644 --- a/test/js/samples/action-custom-event-handler/expected.js +++ b/test/js/samples/action-custom-event-handler/expected.js @@ -1,43 +1,38 @@ /* generated by Svelte vX.Y.Z */ import { SvelteComponent, + action_destroyer, detach, element, init, insert, + is_function, noop, safe_not_equal } from "svelte/internal"; function create_fragment(ctx) { - var button, foo_action; + let button; + let foo_action; + let dispose; return { c() { button = element("button"); button.textContent = "foo"; }, - m(target, anchor) { insert(target, button, anchor); - foo_action = foo.call(null, button, ctx.foo_function) || {}; + dispose = action_destroyer(foo_action = foo.call(null, button, /*foo_function*/ ctx[1])); }, - - p(changed, ctx) { - if (typeof foo_action.update === 'function' && changed.bar) { - foo_action.update.call(null, ctx.foo_function); - } + p(ctx, [dirty]) { + if (foo_action && is_function(foo_action.update) && dirty & /*bar*/ 1) foo_action.update.call(null, /*foo_function*/ ctx[1]); }, - i: noop, o: noop, - d(detaching) { - if (detaching) { - detach(button); - } - - if (foo_action && typeof foo_action.destroy === 'function') foo_action.destroy(); + if (detaching) detach(button); + dispose(); } }; } @@ -47,25 +42,24 @@ function handleFoo(bar) { } function foo(node, callback) { - // code goes here -} + +} // code goes here function instance($$self, $$props, $$invalidate) { let { bar } = $$props; - const foo_function = () => handleFoo(bar); $$self.$set = $$props => { - if ('bar' in $$props) $$invalidate('bar', bar = $$props.bar); + if ("bar" in $$props) $$invalidate(0, bar = $$props.bar); }; - return { bar, foo_function }; + return [bar, foo_function]; } class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, instance, create_fragment, safe_not_equal, ["bar"]); + init(this, options, instance, create_fragment, safe_not_equal, { bar: 0 }); } } diff --git a/test/js/samples/action/expected.js b/test/js/samples/action/expected.js index ed0a0a7430..22d9cd939c 100644 --- a/test/js/samples/action/expected.js +++ b/test/js/samples/action/expected.js @@ -1,6 +1,7 @@ /* generated by Svelte vX.Y.Z */ import { SvelteComponent, + action_destroyer, attr, detach, element, @@ -11,7 +12,9 @@ import { } from "svelte/internal"; function create_fragment(ctx) { - var a, link_action; + let a; + let link_action; + let dispose; return { c() { @@ -19,45 +22,39 @@ function create_fragment(ctx) { a.textContent = "Test"; attr(a, "href", "#"); }, - m(target, anchor) { insert(target, a, anchor); - link_action = link.call(null, a) || {}; + dispose = action_destroyer(link_action = link.call(null, a)); }, - p: noop, i: noop, o: noop, - d(detaching) { - if (detaching) { - detach(a); - } - - if (link_action && typeof link_action.destroy === 'function') link_action.destroy(); + if (detaching) detach(a); + dispose(); } }; } function link(node) { - function onClick(event) { - event.preventDefault(); - history.pushState(null, null, event.target.href); - } + function onClick(event) { + event.preventDefault(); + history.pushState(null, null, event.target.href); + } - node.addEventListener('click', onClick); + node.addEventListener("click", onClick); - return { - destroy() { - node.removeEventListener('click', onClick); - } - } + return { + destroy() { + node.removeEventListener("click", onClick); + } + }; } class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, null, create_fragment, safe_not_equal, []); + init(this, options, null, create_fragment, safe_not_equal, {}); } } diff --git a/test/js/samples/bind-online/expected.js b/test/js/samples/bind-online/expected.js index 0c9faa3ef6..e129e66d71 100644 --- a/test/js/samples/bind-online/expected.js +++ b/test/js/samples/bind-online/expected.js @@ -10,23 +10,20 @@ import { } from "svelte/internal"; function create_fragment(ctx) { - var dispose; - - add_render_callback(ctx.onlinestatuschanged); + let dispose; + add_render_callback(/*onlinestatuschanged*/ ctx[1]); return { - c() { + c: noop, + m(target, anchor) { dispose = [ - listen(window, "online", ctx.onlinestatuschanged), - listen(window, "offline", ctx.onlinestatuschanged) + listen(window, "online", /*onlinestatuschanged*/ ctx[1]), + listen(window, "offline", /*onlinestatuschanged*/ ctx[1]) ]; }, - - m: noop, p: noop, i: noop, o: noop, - d(detaching) { run_all(dispose); } @@ -37,16 +34,16 @@ function instance($$self, $$props, $$invalidate) { let online; function onlinestatuschanged() { - online = navigator.onLine; $$invalidate('online', online); + $$invalidate(0, online = navigator.onLine); } - return { online, onlinestatuschanged }; + return [online, onlinestatuschanged]; } class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, instance, create_fragment, safe_not_equal, []); + init(this, options, instance, create_fragment, safe_not_equal, {}); } } diff --git a/test/js/samples/bind-open/expected.js b/test/js/samples/bind-open/expected.js index 7f739aec8b..7d66145f0a 100644 --- a/test/js/samples/bind-open/expected.js +++ b/test/js/samples/bind-open/expected.js @@ -11,34 +11,30 @@ import { } from "svelte/internal"; function create_fragment(ctx) { - var details, dispose; + let details; + let dispose; return { c() { details = element("details"); + details.innerHTML = `summarycontent - `; - dispose = listen(details, "toggle", ctx.details_toggle_handler); +`; }, - m(target, anchor) { insert(target, details, anchor); - - details.open = ctx.open; + details.open = /*open*/ ctx[0]; + dispose = listen(details, "toggle", /*details_toggle_handler*/ ctx[1]); }, - - p(changed, ctx) { - if (changed.open) details.open = ctx.open; + p(ctx, [dirty]) { + if (dirty & /*open*/ 1) { + details.open = /*open*/ ctx[0]; + } }, - i: noop, o: noop, - d(detaching) { - if (detaching) { - detach(details); - } - + if (detaching) detach(details); dispose(); } }; @@ -49,20 +45,20 @@ function instance($$self, $$props, $$invalidate) { function details_toggle_handler() { open = this.open; - $$invalidate('open', open); + $$invalidate(0, open); } $$self.$set = $$props => { - if ('open' in $$props) $$invalidate('open', open = $$props.open); + if ("open" in $$props) $$invalidate(0, open = $$props.open); }; - return { open, details_toggle_handler }; + return [open, details_toggle_handler]; } class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, instance, create_fragment, safe_not_equal, ["open"]); + init(this, options, instance, create_fragment, safe_not_equal, { open: 0 }); } } diff --git a/test/js/samples/bind-width-height/expected.js b/test/js/samples/bind-width-height/expected.js index 2ef190588f..5c1888b7db 100644 --- a/test/js/samples/bind-width-height/expected.js +++ b/test/js/samples/bind-width-height/expected.js @@ -12,56 +12,52 @@ import { } from "svelte/internal"; function create_fragment(ctx) { - var div, div_resize_listener; + let div; + let div_resize_listener; return { c() { div = element("div"); div.textContent = "some content"; - add_render_callback(() => ctx.div_resize_handler.call(div)); + add_render_callback(() => /*div_elementresize_handler*/ ctx[2].call(div)); }, - m(target, anchor) { insert(target, div, anchor); - div_resize_listener = add_resize_listener(div, ctx.div_resize_handler.bind(div)); + div_resize_listener = add_resize_listener(div, /*div_elementresize_handler*/ ctx[2].bind(div)); }, - p: noop, i: noop, o: noop, - d(detaching) { - if (detaching) { - detach(div); - } - + if (detaching) detach(div); div_resize_listener.cancel(); } }; } function instance($$self, $$props, $$invalidate) { - let { w, h } = $$props; + let { w } = $$props; + let { h } = $$props; - function div_resize_handler() { + function div_elementresize_handler() { w = this.offsetWidth; h = this.offsetHeight; - $$invalidate('w', w); - $$invalidate('h', h); + $$invalidate(0, w); + $$invalidate(1, h); } $$self.$set = $$props => { - if ('w' in $$props) $$invalidate('w', w = $$props.w); - if ('h' in $$props) $$invalidate('h', h = $$props.h); + if ("w" in $$props) $$invalidate(0, w = $$props.w); + if ("h" in $$props) $$invalidate(1, h = $$props.h); }; - return { w, h, div_resize_handler }; + return [w, h, div_elementresize_handler]; } class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, instance, create_fragment, safe_not_equal, ["w", "h"]); + init(this, options, instance, create_fragment, safe_not_equal, { w: 0, h: 1 }); } } diff --git a/test/js/samples/bindings-readonly-order/expected.js b/test/js/samples/bindings-readonly-order/expected.js new file mode 100644 index 0000000000..db0e7cb007 --- /dev/null +++ b/test/js/samples/bindings-readonly-order/expected.js @@ -0,0 +1,79 @@ +/* generated by Svelte vX.Y.Z */ +import { + SvelteComponent, + attr, + detach, + element, + init, + insert, + listen, + noop, + run_all, + safe_not_equal, + space +} from "svelte/internal"; + +function create_fragment(ctx) { + let input0; + let t; + let input1; + let dispose; + + return { + c() { + input0 = element("input"); + t = space(); + input1 = element("input"); + attr(input0, "type", "file"); + attr(input1, "type", "file"); + }, + m(target, anchor) { + insert(target, input0, anchor); + insert(target, t, anchor); + insert(target, input1, anchor); + + dispose = [ + listen(input0, "change", /*input0_change_handler*/ ctx[1]), + listen(input1, "change", /*input1_change_handler*/ ctx[2]) + ]; + }, + p: noop, + i: noop, + o: noop, + d(detaching) { + if (detaching) detach(input0); + if (detaching) detach(t); + if (detaching) detach(input1); + run_all(dispose); + } + }; +} + +function instance($$self, $$props, $$invalidate) { + let { files } = $$props; + + function input0_change_handler() { + files = this.files; + $$invalidate(0, files); + } + + function input1_change_handler() { + files = this.files; + $$invalidate(0, files); + } + + $$self.$set = $$props => { + if ("files" in $$props) $$invalidate(0, files = $$props.files); + }; + + return [files, input0_change_handler, input1_change_handler]; +} + +class Component extends SvelteComponent { + constructor(options) { + super(); + init(this, options, instance, create_fragment, safe_not_equal, { files: 0 }); + } +} + +export default Component; \ No newline at end of file diff --git a/test/js/samples/bindings-readonly-order/input.svelte b/test/js/samples/bindings-readonly-order/input.svelte new file mode 100644 index 0000000000..9a133b90f2 --- /dev/null +++ b/test/js/samples/bindings-readonly-order/input.svelte @@ -0,0 +1,6 @@ + + + + diff --git a/test/js/samples/capture-inject-dev-only/expected.js b/test/js/samples/capture-inject-dev-only/expected.js index 8ed14d6cd5..a314b0cff3 100644 --- a/test/js/samples/capture-inject-dev-only/expected.js +++ b/test/js/samples/capture-inject-dev-only/expected.js @@ -16,44 +16,40 @@ import { } from "svelte/internal"; function create_fragment(ctx) { - var p, t0, t1, input, dispose; + let p; + let t0; + let t1; + let input; + let dispose; return { c() { p = element("p"); - t0 = text(ctx.foo); + t0 = text(/*foo*/ ctx[0]); t1 = space(); input = element("input"); - dispose = listen(input, "input", ctx.input_input_handler); }, - m(target, anchor) { insert(target, p, anchor); append(p, t0); insert(target, t1, anchor); insert(target, input, anchor); - - set_input_value(input, ctx.foo); + set_input_value(input, /*foo*/ ctx[0]); + dispose = listen(input, "input", /*input_input_handler*/ ctx[1]); }, + p(ctx, [dirty]) { + if (dirty & /*foo*/ 1) set_data(t0, /*foo*/ ctx[0]); - p(changed, ctx) { - if (changed.foo) { - set_data(t0, ctx.foo); + if (dirty & /*foo*/ 1 && input.value !== /*foo*/ ctx[0]) { + set_input_value(input, /*foo*/ ctx[0]); } - - if (changed.foo && (input.value !== ctx.foo)) set_input_value(input, ctx.foo); }, - i: noop, o: noop, - d(detaching) { - if (detaching) { - detach(p); - detach(t1); - detach(input); - } - + if (detaching) detach(p); + if (detaching) detach(t1); + if (detaching) detach(input); dispose(); } }; @@ -64,16 +60,16 @@ function instance($$self, $$props, $$invalidate) { function input_input_handler() { foo = this.value; - $$invalidate('foo', foo); + $$invalidate(0, foo); } - return { foo, input_input_handler }; + return [foo, input_input_handler]; } class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, instance, create_fragment, safe_not_equal, []); + init(this, options, instance, create_fragment, safe_not_equal, {}); } } diff --git a/test/js/samples/capture-inject-state/_config.js b/test/js/samples/capture-inject-state/_config.js new file mode 100644 index 0000000000..414b026a97 --- /dev/null +++ b/test/js/samples/capture-inject-state/_config.js @@ -0,0 +1,5 @@ +export default { + options: { + dev: true + } +}; diff --git a/test/js/samples/capture-inject-state/expected.js b/test/js/samples/capture-inject-state/expected.js new file mode 100644 index 0000000000..8593145565 --- /dev/null +++ b/test/js/samples/capture-inject-state/expected.js @@ -0,0 +1,197 @@ +/* generated by Svelte vX.Y.Z */ +import { + SvelteComponentDev, + add_location, + append_dev, + detach_dev, + dispatch_dev, + element, + init, + insert_dev, + noop, + safe_not_equal, + set_data_dev, + space, + subscribe, + text, + validate_store +} from "svelte/internal"; + +const file = undefined; + +function create_fragment(ctx) { + let p; + let t0; + let t1; + let t2; + let t3; + let t4; + let t5; + let t6; + let t7; + let t8; + let t9; + let t10; + + const block = { + c: function create() { + p = element("p"); + t0 = text(/*prop*/ ctx[0]); + t1 = space(); + t2 = text(/*realName*/ ctx[1]); + t3 = space(); + t4 = text(/*local*/ ctx[3]); + t5 = space(); + t6 = text(priv); + t7 = space(); + t8 = text(/*$prop*/ ctx[2]); + t9 = space(); + t10 = text(/*shadowedByModule*/ ctx[4]); + add_location(p, file, 22, 0, 430); + }, + l: function claim(nodes) { + throw new Error("options.hydrate only works if the component was compiled with the `hydratable: true` option"); + }, + m: function mount(target, anchor) { + insert_dev(target, p, anchor); + append_dev(p, t0); + append_dev(p, t1); + append_dev(p, t2); + append_dev(p, t3); + append_dev(p, t4); + append_dev(p, t5); + append_dev(p, t6); + append_dev(p, t7); + append_dev(p, t8); + append_dev(p, t9); + append_dev(p, t10); + }, + p: function update(ctx, [dirty]) { + if (dirty & /*prop*/ 1) set_data_dev(t0, /*prop*/ ctx[0]); + if (dirty & /*realName*/ 2) set_data_dev(t2, /*realName*/ ctx[1]); + if (dirty & /*$prop*/ 4) set_data_dev(t8, /*$prop*/ ctx[2]); + }, + i: noop, + o: noop, + d: function destroy(detaching) { + if (detaching) detach_dev(p); + } + }; + + dispatch_dev("SvelteRegisterBlock", { + block, + id: create_fragment.name, + type: "component", + source: "", + ctx + }); + + return block; +} + +let moduleLiveBinding; +const moduleContantProps = 4; +let moduleLet; +const moduleConst = 2; +let shadowedByModule; +const priv = "priv"; + +function instance($$self, $$props, $$invalidate) { + let $prop, + $$unsubscribe_prop = noop, + $$subscribe_prop = () => ($$unsubscribe_prop(), $$unsubscribe_prop = subscribe(prop, $$value => $$invalidate(2, $prop = $$value)), prop); + + $$self.$$.on_destroy.push(() => $$unsubscribe_prop()); + let { prop } = $$props; + validate_store(prop, "prop"); + $$subscribe_prop(); + let { alias: realName } = $$props; + let local; + let shadowedByModule; + const writable_props = ["prop", "alias"]; + + Object.keys($$props).forEach(key => { + if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(` was created with unknown prop '${key}'`); + }); + + $$self.$set = $$props => { + if ("prop" in $$props) $$subscribe_prop($$invalidate(0, prop = $$props.prop)); + if ("alias" in $$props) $$invalidate(1, realName = $$props.alias); + }; + + $$self.$capture_state = () => ({ + moduleLiveBinding, + moduleContantProps, + moduleLet, + moduleConst, + shadowedByModule, + prop, + realName, + local, + priv, + shadowedByModule, + computed, + $prop + }); + + $$self.$inject_state = $$props => { + if ("prop" in $$props) $$subscribe_prop($$invalidate(0, prop = $$props.prop)); + if ("realName" in $$props) $$invalidate(1, realName = $$props.realName); + if ("local" in $$props) $$invalidate(3, local = $$props.local); + if ("shadowedByModule" in $$props) $$invalidate(4, shadowedByModule = $$props.shadowedByModule); + if ("computed" in $$props) computed = $$props.computed; + }; + + let computed; + + if ($$props && "$$inject" in $$props) { + $$self.$inject_state($$props.$$inject); + } + + $: computed = local * 2; + return [prop, realName, $prop, local, shadowedByModule]; +} + +class Component extends SvelteComponentDev { + constructor(options) { + super(options); + init(this, options, instance, create_fragment, safe_not_equal, { prop: 0, alias: 1 }); + + dispatch_dev("SvelteRegisterComponent", { + component: this, + tagName: "Component", + options, + id: create_fragment.name + }); + + const { ctx } = this.$$; + const props = options.props || {}; + + if (/*prop*/ ctx[0] === undefined && !("prop" in props)) { + console.warn(" was created without expected prop 'prop'"); + } + + if (/*realName*/ ctx[1] === undefined && !("alias" in props)) { + console.warn(" was created without expected prop 'alias'"); + } + } + + get prop() { + throw new Error(": Props cannot be read directly from the component instance unless compiling with 'accessors: true' or ''"); + } + + set prop(value) { + throw new Error(": Props cannot be set directly on the component instance unless compiling with 'accessors: true' or ''"); + } + + get alias() { + throw new Error(": Props cannot be read directly from the component instance unless compiling with 'accessors: true' or ''"); + } + + set alias(value) { + throw new Error(": Props cannot be set directly on the component instance unless compiling with 'accessors: true' or ''"); + } +} + +export default Component; +export { moduleLiveBinding, moduleContantProps }; \ No newline at end of file diff --git a/test/js/samples/capture-inject-state/input.svelte b/test/js/samples/capture-inject-state/input.svelte new file mode 100644 index 0000000000..a1051bc147 --- /dev/null +++ b/test/js/samples/capture-inject-state/input.svelte @@ -0,0 +1,23 @@ + + + +

{prop} {realName} {local} {priv} {$prop} {shadowedByModule}

diff --git a/test/js/samples/collapses-text-around-comments/expected.js b/test/js/samples/collapses-text-around-comments/expected.js index 09b40a1e98..6fef0f9490 100644 --- a/test/js/samples/collapses-text-around-comments/expected.js +++ b/test/js/samples/collapses-text-around-comments/expected.js @@ -15,39 +15,32 @@ import { function add_css() { var style = element("style"); - style.id = 'svelte-1a7i8ec-style'; + style.id = "svelte-1a7i8ec-style"; style.textContent = "p.svelte-1a7i8ec{color:red}"; append(document.head, style); } function create_fragment(ctx) { - var p, t; + let p; + let t; return { c() { p = element("p"); - t = text(ctx.foo); + t = text(/*foo*/ ctx[0]); attr(p, "class", "svelte-1a7i8ec"); }, - m(target, anchor) { insert(target, p, anchor); append(p, t); }, - - p(changed, ctx) { - if (changed.foo) { - set_data(t, ctx.foo); - } + p(ctx, [dirty]) { + if (dirty & /*foo*/ 1) set_data(t, /*foo*/ ctx[0]); }, - i: noop, o: noop, - d(detaching) { - if (detaching) { - detach(p); - } + if (detaching) detach(p); } }; } @@ -56,17 +49,17 @@ function instance($$self, $$props, $$invalidate) { let { foo = 42 } = $$props; $$self.$set = $$props => { - if ('foo' in $$props) $$invalidate('foo', foo = $$props.foo); + if ("foo" in $$props) $$invalidate(0, foo = $$props.foo); }; - return { foo }; + return [foo]; } class Component extends SvelteComponent { constructor(options) { super(); if (!document.getElementById("svelte-1a7i8ec-style")) add_css(); - init(this, options, instance, create_fragment, safe_not_equal, ["foo"]); + init(this, options, instance, create_fragment, safe_not_equal, { foo: 0 }); } } diff --git a/test/js/samples/component-static-array/expected.js b/test/js/samples/component-static-array/expected.js index 6997f431dd..44e8dbfe33 100644 --- a/test/js/samples/component-static-array/expected.js +++ b/test/js/samples/component-static-array/expected.js @@ -1,6 +1,7 @@ /* generated by Svelte vX.Y.Z */ import { SvelteComponent, + create_component, destroy_component, init, mount_component, @@ -11,34 +12,27 @@ import { } from "svelte/internal"; function create_fragment(ctx) { - var current; - - var nested = new ctx.Nested({ props: { foo: [1, 2, 3] } }); + let current; + const nested = new /*Nested*/ ctx[0]({ props: { foo: [1, 2, 3] } }); return { c() { - nested.$$.fragment.c(); + create_component(nested.$$.fragment); }, - m(target, anchor) { mount_component(nested, target, anchor); current = true; }, - p: noop, - i(local) { if (current) return; transition_in(nested.$$.fragment, local); - current = true; }, - o(local) { transition_out(nested.$$.fragment, local); current = false; }, - d(detaching) { destroy_component(nested, detaching); } @@ -47,14 +41,13 @@ function create_fragment(ctx) { function instance($$self) { const Nested = window.Nested; - - return { Nested }; + return [Nested]; } class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, instance, create_fragment, safe_not_equal, []); + init(this, options, instance, create_fragment, safe_not_equal, {}); } } diff --git a/test/js/samples/component-static-immutable/expected.js b/test/js/samples/component-static-immutable/expected.js index 4b33d537ca..a7dd8128fa 100644 --- a/test/js/samples/component-static-immutable/expected.js +++ b/test/js/samples/component-static-immutable/expected.js @@ -1,6 +1,7 @@ /* generated by Svelte vX.Y.Z */ import { SvelteComponent, + create_component, destroy_component, init, mount_component, @@ -11,34 +12,27 @@ import { } from "svelte/internal"; function create_fragment(ctx) { - var current; - - var nested = new ctx.Nested({ props: { foo: "bar" } }); + let current; + const nested = new /*Nested*/ ctx[0]({ props: { foo: "bar" } }); return { c() { - nested.$$.fragment.c(); + create_component(nested.$$.fragment); }, - m(target, anchor) { mount_component(nested, target, anchor); current = true; }, - p: noop, - i(local) { if (current) return; transition_in(nested.$$.fragment, local); - current = true; }, - o(local) { transition_out(nested.$$.fragment, local); current = false; }, - d(detaching) { destroy_component(nested, detaching); } @@ -47,14 +41,13 @@ function create_fragment(ctx) { function instance($$self) { const Nested = window.Nested; - - return { Nested }; + return [Nested]; } class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, instance, create_fragment, not_equal, []); + init(this, options, instance, create_fragment, not_equal, {}); } } diff --git a/test/js/samples/component-static-immutable2/expected.js b/test/js/samples/component-static-immutable2/expected.js index 4b33d537ca..a7dd8128fa 100644 --- a/test/js/samples/component-static-immutable2/expected.js +++ b/test/js/samples/component-static-immutable2/expected.js @@ -1,6 +1,7 @@ /* generated by Svelte vX.Y.Z */ import { SvelteComponent, + create_component, destroy_component, init, mount_component, @@ -11,34 +12,27 @@ import { } from "svelte/internal"; function create_fragment(ctx) { - var current; - - var nested = new ctx.Nested({ props: { foo: "bar" } }); + let current; + const nested = new /*Nested*/ ctx[0]({ props: { foo: "bar" } }); return { c() { - nested.$$.fragment.c(); + create_component(nested.$$.fragment); }, - m(target, anchor) { mount_component(nested, target, anchor); current = true; }, - p: noop, - i(local) { if (current) return; transition_in(nested.$$.fragment, local); - current = true; }, - o(local) { transition_out(nested.$$.fragment, local); current = false; }, - d(detaching) { destroy_component(nested, detaching); } @@ -47,14 +41,13 @@ function create_fragment(ctx) { function instance($$self) { const Nested = window.Nested; - - return { Nested }; + return [Nested]; } class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, instance, create_fragment, not_equal, []); + init(this, options, instance, create_fragment, not_equal, {}); } } diff --git a/test/js/samples/component-static-var/expected.js b/test/js/samples/component-static-var/expected.js index 2f6521f87e..a65d9186a7 100644 --- a/test/js/samples/component-static-var/expected.js +++ b/test/js/samples/component-static-var/expected.js @@ -1,6 +1,7 @@ /* generated by Svelte vX.Y.Z */ import { SvelteComponent, + create_component, destroy_component, detach, element, @@ -14,75 +15,63 @@ import { transition_in, transition_out } from "svelte/internal"; + import Foo from "./Foo.svelte"; import Bar from "./Bar.svelte"; function create_fragment(ctx) { - var t0, t1, input, current, dispose; - - var foo = new Foo({ props: { x: y } }); - - var bar = new Bar({ props: { x: ctx.z } }); + let t0; + let t1; + let input; + let current; + let dispose; + const foo = new Foo({ props: { x: y } }); + const bar = new Bar({ props: { x: /*z*/ ctx[0] } }); return { c() { - foo.$$.fragment.c(); + create_component(foo.$$.fragment); t0 = space(); - bar.$$.fragment.c(); + create_component(bar.$$.fragment); t1 = space(); input = element("input"); - dispose = listen(input, "input", ctx.input_input_handler); }, - m(target, anchor) { mount_component(foo, target, anchor); insert(target, t0, anchor); mount_component(bar, target, anchor); insert(target, t1, anchor); insert(target, input, anchor); - - set_input_value(input, ctx.z); - + set_input_value(input, /*z*/ ctx[0]); current = true; + dispose = listen(input, "input", /*input_input_handler*/ ctx[1]); }, - - p(changed, ctx) { - var bar_changes = {}; - if (changed.z) bar_changes.x = ctx.z; + p(ctx, [dirty]) { + const bar_changes = {}; + if (dirty & /*z*/ 1) bar_changes.x = /*z*/ ctx[0]; bar.$set(bar_changes); - if (changed.z && (input.value !== ctx.z)) set_input_value(input, ctx.z); + if (dirty & /*z*/ 1 && input.value !== /*z*/ ctx[0]) { + set_input_value(input, /*z*/ ctx[0]); + } }, - i(local) { if (current) return; transition_in(foo.$$.fragment, local); - transition_in(bar.$$.fragment, local); - current = true; }, - o(local) { transition_out(foo.$$.fragment, local); transition_out(bar.$$.fragment, local); current = false; }, - d(detaching) { destroy_component(foo, detaching); - - if (detaching) { - detach(t0); - } - + if (detaching) detach(t0); destroy_component(bar, detaching); - - if (detaching) { - detach(t1); - detach(input); - } - + if (detaching) detach(t1); + if (detaching) detach(input); dispose(); } }; @@ -91,21 +80,20 @@ function create_fragment(ctx) { let y = 1; function instance($$self, $$props, $$invalidate) { - let z = 2; function input_input_handler() { z = this.value; - $$invalidate('z', z); + $$invalidate(0, z); } - return { z, input_input_handler }; + return [z, input_input_handler]; } class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, instance, create_fragment, safe_not_equal, []); + init(this, options, instance, create_fragment, safe_not_equal, {}); } } diff --git a/test/js/samples/component-static/expected.js b/test/js/samples/component-static/expected.js index 5a031a32a4..26c63f550b 100644 --- a/test/js/samples/component-static/expected.js +++ b/test/js/samples/component-static/expected.js @@ -1,6 +1,7 @@ /* generated by Svelte vX.Y.Z */ import { SvelteComponent, + create_component, destroy_component, init, mount_component, @@ -11,34 +12,27 @@ import { } from "svelte/internal"; function create_fragment(ctx) { - var current; - - var nested = new ctx.Nested({ props: { foo: "bar" } }); + let current; + const nested = new /*Nested*/ ctx[0]({ props: { foo: "bar" } }); return { c() { - nested.$$.fragment.c(); + create_component(nested.$$.fragment); }, - m(target, anchor) { mount_component(nested, target, anchor); current = true; }, - p: noop, - i(local) { if (current) return; transition_in(nested.$$.fragment, local); - current = true; }, - o(local) { transition_out(nested.$$.fragment, local); current = false; }, - d(detaching) { destroy_component(nested, detaching); } @@ -47,14 +41,13 @@ function create_fragment(ctx) { function instance($$self) { const Nested = window.Nested; - - return { Nested }; + return [Nested]; } class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, instance, create_fragment, safe_not_equal, []); + init(this, options, instance, create_fragment, safe_not_equal, {}); } } diff --git a/test/js/samples/component-store-access-invalidate/expected.js b/test/js/samples/component-store-access-invalidate/expected.js new file mode 100644 index 0000000000..4c7bfd7009 --- /dev/null +++ b/test/js/samples/component-store-access-invalidate/expected.js @@ -0,0 +1,56 @@ +/* generated by Svelte vX.Y.Z */ +import { + SvelteComponent, + append, + component_subscribe, + detach, + element, + init, + insert, + noop, + safe_not_equal, + set_data, + text +} from "svelte/internal"; + +import { writable } from "svelte/store"; + +function create_fragment(ctx) { + let h1; + let t; + + return { + c() { + h1 = element("h1"); + t = text(/*$foo*/ ctx[0]); + }, + m(target, anchor) { + insert(target, h1, anchor); + append(h1, t); + }, + p(ctx, [dirty]) { + if (dirty & /*$foo*/ 1) set_data(t, /*$foo*/ ctx[0]); + }, + i: noop, + o: noop, + d(detaching) { + if (detaching) detach(h1); + } + }; +} + +function instance($$self, $$props, $$invalidate) { + let $foo; + const foo = writable(0); + component_subscribe($$self, foo, value => $$invalidate(0, $foo = value)); + return [$foo, foo]; +} + +class Component extends SvelteComponent { + constructor(options) { + super(); + init(this, options, instance, create_fragment, safe_not_equal, {}); + } +} + +export default Component; \ No newline at end of file diff --git a/test/js/samples/component-store-access-invalidate/input.svelte b/test/js/samples/component-store-access-invalidate/input.svelte new file mode 100644 index 0000000000..f42bbe295c --- /dev/null +++ b/test/js/samples/component-store-access-invalidate/input.svelte @@ -0,0 +1,6 @@ + + +

{$foo}

\ No newline at end of file diff --git a/test/js/samples/component-store-file-invalidate/expected.js b/test/js/samples/component-store-file-invalidate/expected.js new file mode 100644 index 0000000000..d2fb3d0be4 --- /dev/null +++ b/test/js/samples/component-store-file-invalidate/expected.js @@ -0,0 +1,34 @@ +/* generated by Svelte vX.Y.Z */ +import { + SvelteComponent, + component_subscribe, + init, + safe_not_equal, + set_store_value +} from "svelte/internal"; + +import { count } from "./store.js"; + +function instance($$self, $$props, $$invalidate) { + let $count; + component_subscribe($$self, count, $$value => $$invalidate(1, $count = $$value)); + + function increment() { + set_store_value(count, $count++, $count); + } + + return [increment]; +} + +class Component extends SvelteComponent { + constructor(options) { + super(); + init(this, options, instance, null, safe_not_equal, { increment: 0 }); + } + + get increment() { + return this.$$.ctx[0]; + } +} + +export default Component; \ No newline at end of file diff --git a/test/js/samples/component-store-file-invalidate/input.svelte b/test/js/samples/component-store-file-invalidate/input.svelte new file mode 100644 index 0000000000..3c2fca2e80 --- /dev/null +++ b/test/js/samples/component-store-file-invalidate/input.svelte @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/test/js/samples/component-store-file-invalidate/store.js b/test/js/samples/component-store-file-invalidate/store.js new file mode 100644 index 0000000000..99e27e5584 --- /dev/null +++ b/test/js/samples/component-store-file-invalidate/store.js @@ -0,0 +1,3 @@ +import { writable } from '../../../../store'; + +export const count = writable(0); \ No newline at end of file diff --git a/test/js/samples/component-store-reassign-invalidate/expected.js b/test/js/samples/component-store-reassign-invalidate/expected.js new file mode 100644 index 0000000000..771b20dec4 --- /dev/null +++ b/test/js/samples/component-store-reassign-invalidate/expected.js @@ -0,0 +1,75 @@ +/* generated by Svelte vX.Y.Z */ +import { + SvelteComponent, + append, + detach, + element, + init, + insert, + listen, + noop, + safe_not_equal, + set_data, + space, + subscribe, + text +} from "svelte/internal"; + +import { writable } from "svelte/store"; + +function create_fragment(ctx) { + let h1; + let t0; + let t1; + let button; + let dispose; + + return { + c() { + h1 = element("h1"); + t0 = text(/*$foo*/ ctx[1]); + t1 = space(); + button = element("button"); + button.textContent = "reset"; + }, + m(target, anchor) { + insert(target, h1, anchor); + append(h1, t0); + insert(target, t1, anchor); + insert(target, button, anchor); + dispose = listen(button, "click", /*click_handler*/ ctx[2]); + }, + p(ctx, [dirty]) { + if (dirty & /*$foo*/ 2) set_data(t0, /*$foo*/ ctx[1]); + }, + i: noop, + o: noop, + d(detaching) { + if (detaching) detach(h1); + if (detaching) detach(t1); + if (detaching) detach(button); + dispose(); + } + }; +} + +function instance($$self, $$props, $$invalidate) { + let $foo, + $$unsubscribe_foo = noop, + $$subscribe_foo = () => ($$unsubscribe_foo(), $$unsubscribe_foo = subscribe(foo, $$value => $$invalidate(1, $foo = $$value)), foo); + + $$self.$$.on_destroy.push(() => $$unsubscribe_foo()); + let foo = writable(0); + $$subscribe_foo(); + const click_handler = () => $$subscribe_foo($$invalidate(0, foo = writable(0))); + return [foo, $foo, click_handler]; +} + +class Component extends SvelteComponent { + constructor(options) { + super(); + init(this, options, instance, create_fragment, safe_not_equal, {}); + } +} + +export default Component; \ No newline at end of file diff --git a/test/js/samples/component-store-reassign-invalidate/input.svelte b/test/js/samples/component-store-reassign-invalidate/input.svelte new file mode 100644 index 0000000000..bbb52b9669 --- /dev/null +++ b/test/js/samples/component-store-reassign-invalidate/input.svelte @@ -0,0 +1,7 @@ + + +

{$foo}

+ \ No newline at end of file diff --git a/test/js/samples/computed-collapsed-if/expected.js b/test/js/samples/computed-collapsed-if/expected.js index bc7c383319..8e5964f8a6 100644 --- a/test/js/samples/computed-collapsed-if/expected.js +++ b/test/js/samples/computed-collapsed-if/expected.js @@ -1,21 +1,5 @@ /* generated by Svelte vX.Y.Z */ -import { - SvelteComponent, - init, - noop, - safe_not_equal -} from "svelte/internal"; - -function create_fragment(ctx) { - return { - c: noop, - m: noop, - p: noop, - i: noop, - o: noop, - d: noop - }; -} +import { SvelteComponent, init, safe_not_equal } from "svelte/internal"; function instance($$self, $$props, $$invalidate) { let { x } = $$props; @@ -29,24 +13,24 @@ function instance($$self, $$props, $$invalidate) { } $$self.$set = $$props => { - if ('x' in $$props) $$invalidate('x', x = $$props.x); + if ("x" in $$props) $$invalidate(0, x = $$props.x); }; - return { x, a, b }; + return [x, a, b]; } class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, instance, create_fragment, safe_not_equal, ["x", "a", "b"]); + init(this, options, instance, null, safe_not_equal, { x: 0, a: 1, b: 2 }); } get a() { - return this.$$.ctx.a; + return this.$$.ctx[1]; } get b() { - return this.$$.ctx.b; + return this.$$.ctx[2]; } } diff --git a/test/js/samples/css-media-query/expected.js b/test/js/samples/css-media-query/expected.js index 82b7c5dfc8..f477670059 100644 --- a/test/js/samples/css-media-query/expected.js +++ b/test/js/samples/css-media-query/expected.js @@ -13,32 +13,27 @@ import { function add_css() { var style = element("style"); - style.id = 'svelte-1slhpfn-style'; + style.id = "svelte-1slhpfn-style"; style.textContent = "@media(min-width: 1px){div.svelte-1slhpfn{color:red}}"; append(document.head, style); } function create_fragment(ctx) { - var div; + let div; return { c() { div = element("div"); attr(div, "class", "svelte-1slhpfn"); }, - m(target, anchor) { insert(target, div, anchor); }, - p: noop, i: noop, o: noop, - d(detaching) { - if (detaching) { - detach(div); - } + if (detaching) detach(div); } }; } @@ -47,7 +42,7 @@ class Component extends SvelteComponent { constructor(options) { super(); if (!document.getElementById("svelte-1slhpfn-style")) add_css(); - init(this, options, null, create_fragment, safe_not_equal, []); + init(this, options, null, create_fragment, safe_not_equal, {}); } } diff --git a/test/js/samples/css-shadow-dom-keyframes/expected.js b/test/js/samples/css-shadow-dom-keyframes/expected.js index 9f70b8ec66..a0a0ebe021 100644 --- a/test/js/samples/css-shadow-dom-keyframes/expected.js +++ b/test/js/samples/css-shadow-dom-keyframes/expected.js @@ -10,7 +10,7 @@ import { } from "svelte/internal"; function create_fragment(ctx) { - var div; + let div; return { c() { @@ -18,19 +18,14 @@ function create_fragment(ctx) { div.textContent = "fades in"; this.c = noop; }, - m(target, anchor) { insert(target, div, anchor); }, - p: noop, i: noop, o: noop, - d(detaching) { - if (detaching) { - detach(div); - } + if (detaching) detach(div); } }; } @@ -38,10 +33,8 @@ function create_fragment(ctx) { class Component extends SvelteElement { constructor(options) { super(); - this.shadowRoot.innerHTML = ``; - - init(this, { target: this.shadowRoot }, null, create_fragment, safe_not_equal, []); + init(this, { target: this.shadowRoot }, null, create_fragment, safe_not_equal, {}); if (options) { if (options.target) { @@ -52,5 +45,4 @@ class Component extends SvelteElement { } customElements.define("custom-element", Component); - export default Component; \ No newline at end of file diff --git a/test/js/samples/data-attribute/expected.js b/test/js/samples/data-attribute/expected.js index 12ba50e69f..49ad2f2626 100644 --- a/test/js/samples/data-attribute/expected.js +++ b/test/js/samples/data-attribute/expected.js @@ -12,7 +12,9 @@ import { } from "svelte/internal"; function create_fragment(ctx) { - var div0, t, div1; + let div0; + let t; + let div1; return { c() { @@ -20,30 +22,24 @@ function create_fragment(ctx) { t = space(); div1 = element("div"); attr(div0, "data-foo", "bar"); - attr(div1, "data-foo", ctx.bar); + attr(div1, "data-foo", /*bar*/ ctx[0]); }, - m(target, anchor) { insert(target, div0, anchor); insert(target, t, anchor); insert(target, div1, anchor); }, - - p(changed, ctx) { - if (changed.bar) { - attr(div1, "data-foo", ctx.bar); + p(ctx, [dirty]) { + if (dirty & /*bar*/ 1) { + attr(div1, "data-foo", /*bar*/ ctx[0]); } }, - i: noop, o: noop, - d(detaching) { - if (detaching) { - detach(div0); - detach(t); - detach(div1); - } + if (detaching) detach(div0); + if (detaching) detach(t); + if (detaching) detach(div1); } }; } @@ -52,16 +48,16 @@ function instance($$self, $$props, $$invalidate) { let { bar } = $$props; $$self.$set = $$props => { - if ('bar' in $$props) $$invalidate('bar', bar = $$props.bar); + if ("bar" in $$props) $$invalidate(0, bar = $$props.bar); }; - return { bar }; + return [bar]; } class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, instance, create_fragment, safe_not_equal, ["bar"]); + init(this, options, instance, create_fragment, safe_not_equal, { bar: 0 }); } } diff --git a/test/js/samples/debug-empty/expected.js b/test/js/samples/debug-empty/expected.js index e0988b6222..87d78bd698 100644 --- a/test/js/samples/debug-empty/expected.js +++ b/test/js/samples/debug-empty/expected.js @@ -18,23 +18,25 @@ import { const file = undefined; function create_fragment(ctx) { - var h1, t0, t1, t2, t3; + let h1; + let t0; + let t1; + let t2; + let t3; const block = { c: function create() { h1 = element("h1"); t0 = text("Hello "); - t1 = text(ctx.name); + t1 = text(/*name*/ ctx[0]); t2 = text("!"); t3 = space(); debugger; add_location(h1, file, 4, 0, 38); }, - l: function claim(nodes) { throw new Error("options.hydrate only works if the component was compiled with the `hydratable: true` option"); }, - m: function mount(target, anchor) { insert_dev(target, h1, anchor); append_dev(h1, t0); @@ -42,61 +44,70 @@ function create_fragment(ctx) { append_dev(h1, t2); insert_dev(target, t3, anchor); }, - - p: function update(changed, ctx) { - if (changed.name) { - set_data_dev(t1, ctx.name); - } - + p: function update(ctx, [dirty]) { + if (dirty & /*name*/ 1) set_data_dev(t1, /*name*/ ctx[0]); debugger; }, - i: noop, o: noop, - d: function destroy(detaching) { - if (detaching) { - detach_dev(h1); - detach_dev(t3); - } + if (detaching) detach_dev(h1); + if (detaching) detach_dev(t3); } }; - dispatch_dev("SvelteRegisterBlock", { block, id: create_fragment.name, type: "component", source: "", ctx }); + + dispatch_dev("SvelteRegisterBlock", { + block, + id: create_fragment.name, + type: "component", + source: "", + ctx + }); + return block; } function instance($$self, $$props, $$invalidate) { let { name } = $$props; + const writable_props = ["name"]; - const writable_props = ['name']; Object.keys($$props).forEach(key => { - if (!writable_props.includes(key) && !key.startsWith('$$')) console.warn(` was created with unknown prop '${key}'`); + if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(` was created with unknown prop '${key}'`); }); $$self.$set = $$props => { - if ('name' in $$props) $$invalidate('name', name = $$props.name); + if ("name" in $$props) $$invalidate(0, name = $$props.name); }; - $$self.$capture_state = () => { - return { name }; - }; + $$self.$capture_state = () => ({ name }); $$self.$inject_state = $$props => { - if ('name' in $$props) $$invalidate('name', name = $$props.name); + if ("name" in $$props) $$invalidate(0, name = $$props.name); }; - return { name }; + if ($$props && "$$inject" in $$props) { + $$self.$inject_state($$props.$$inject); + } + + return [name]; } class Component extends SvelteComponentDev { constructor(options) { super(options); - init(this, options, instance, create_fragment, safe_not_equal, ["name"]); - dispatch_dev("SvelteRegisterComponent", { component: this, tagName: "Component", options, id: create_fragment.name }); + init(this, options, instance, create_fragment, safe_not_equal, { name: 0 }); + + dispatch_dev("SvelteRegisterComponent", { + component: this, + tagName: "Component", + options, + id: create_fragment.name + }); const { ctx } = this.$$; const props = options.props || {}; - if (ctx.name === undefined && !('name' in props)) { + + if (/*name*/ ctx[0] === undefined && !("name" in props)) { console.warn(" was created without expected prop 'name'"); } } diff --git a/test/js/samples/debug-foo-bar-baz-things/expected.js b/test/js/samples/debug-foo-bar-baz-things/expected.js index 15d953f6bc..589c4a7832 100644 --- a/test/js/samples/debug-foo-bar-baz-things/expected.js +++ b/test/js/samples/debug-foo-bar-baz-things/expected.js @@ -13,20 +13,24 @@ import { safe_not_equal, set_data_dev, space, - text + text, + validate_each_argument } from "svelte/internal"; const file = undefined; function get_each_context(ctx, list, i) { - const child_ctx = Object.create(ctx); - child_ctx.thing = list[i]; + const child_ctx = ctx.slice(); + child_ctx[4] = list[i]; return child_ctx; } // (8:0) {#each things as thing} function create_each_block(ctx) { - var span, t0_value = ctx.thing.name + "", t0, t1; + let span; + let t0_value = /*thing*/ ctx[4].name + ""; + let t0; + let t1; const block = { c: function create() { @@ -35,47 +39,57 @@ function create_each_block(ctx) { t1 = space(); { - const { foo, bar, baz, thing } = ctx; + const foo = /*foo*/ ctx[1]; + const bar = /*bar*/ ctx[2]; + const baz = /*baz*/ ctx[3]; + const thing = /*thing*/ ctx[4]; console.log({ foo, bar, baz, thing }); debugger; } + add_location(span, file, 8, 1, 116); }, - m: function mount(target, anchor) { insert_dev(target, span, anchor); append_dev(span, t0); insert_dev(target, t1, anchor); }, - - p: function update(changed, ctx) { - if ((changed.things) && t0_value !== (t0_value = ctx.thing.name + "")) { - set_data_dev(t0, t0_value); - } - - if (changed.foo || changed.bar || changed.baz || changed.things) { - const { foo, bar, baz, thing } = ctx; + p: function update(ctx, dirty) { + if (dirty & /*things*/ 1 && t0_value !== (t0_value = /*thing*/ ctx[4].name + "")) set_data_dev(t0, t0_value); + + if (dirty & /*foo, bar, baz, things*/ 15) { + const foo = /*foo*/ ctx[1]; + const bar = /*bar*/ ctx[2]; + const baz = /*baz*/ ctx[3]; + const thing = /*thing*/ ctx[4]; console.log({ foo, bar, baz, thing }); debugger; } }, - d: function destroy(detaching) { - if (detaching) { - detach_dev(span); - detach_dev(t1); - } + if (detaching) detach_dev(span); + if (detaching) detach_dev(t1); } }; - dispatch_dev("SvelteRegisterBlock", { block, id: create_each_block.name, type: "each", source: "(8:0) {#each things as thing}", ctx }); + + dispatch_dev("SvelteRegisterBlock", { + block, + id: create_each_block.name, + type: "each", + source: "(8:0) {#each things as thing}", + ctx + }); + return block; } function create_fragment(ctx) { - var t0, p, t1, t2; - - let each_value = ctx.things; - + let t0; + let p; + let t1; + let t2; + let each_value = /*things*/ ctx[0]; + validate_each_argument(each_value); let each_blocks = []; for (let i = 0; i < each_value.length; i += 1) { @@ -91,14 +105,12 @@ function create_fragment(ctx) { t0 = space(); p = element("p"); t1 = text("foo: "); - t2 = text(ctx.foo); + t2 = text(/*foo*/ ctx[1]); add_location(p, file, 12, 0, 182); }, - l: function claim(nodes) { throw new Error("options.hydrate only works if the component was compiled with the `hydratable: true` option"); }, - m: function mount(target, anchor) { for (let i = 0; i < each_blocks.length; i += 1) { each_blocks[i].m(target, anchor); @@ -109,17 +121,17 @@ function create_fragment(ctx) { append_dev(p, t1); append_dev(p, t2); }, - - p: function update(changed, ctx) { - if (changed.things) { - each_value = ctx.things; - + p: function update(ctx, [dirty]) { + if (dirty & /*things*/ 1) { + each_value = /*things*/ ctx[0]; + validate_each_argument(each_value); let i; + for (i = 0; i < each_value.length; i += 1) { const child_ctx = get_each_context(ctx, each_value, i); if (each_blocks[i]) { - each_blocks[i].p(changed, child_ctx); + each_blocks[i].p(child_ctx, dirty); } else { each_blocks[i] = create_each_block(child_ctx); each_blocks[i].c(); @@ -130,77 +142,94 @@ function create_fragment(ctx) { for (; i < each_blocks.length; i += 1) { each_blocks[i].d(1); } + each_blocks.length = each_value.length; } - if (changed.foo) { - set_data_dev(t2, ctx.foo); - } + if (dirty & /*foo*/ 2) set_data_dev(t2, /*foo*/ ctx[1]); }, - i: noop, o: noop, - d: function destroy(detaching) { destroy_each(each_blocks, detaching); - - if (detaching) { - detach_dev(t0); - detach_dev(p); - } + if (detaching) detach_dev(t0); + if (detaching) detach_dev(p); } }; - dispatch_dev("SvelteRegisterBlock", { block, id: create_fragment.name, type: "component", source: "", ctx }); + + dispatch_dev("SvelteRegisterBlock", { + block, + id: create_fragment.name, + type: "component", + source: "", + ctx + }); + return block; } function instance($$self, $$props, $$invalidate) { - let { things, foo, bar, baz } = $$props; + let { things } = $$props; + let { foo } = $$props; + let { bar } = $$props; + let { baz } = $$props; + const writable_props = ["things", "foo", "bar", "baz"]; - const writable_props = ['things', 'foo', 'bar', 'baz']; Object.keys($$props).forEach(key => { - if (!writable_props.includes(key) && !key.startsWith('$$')) console.warn(` was created with unknown prop '${key}'`); + if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(` was created with unknown prop '${key}'`); }); $$self.$set = $$props => { - if ('things' in $$props) $$invalidate('things', things = $$props.things); - if ('foo' in $$props) $$invalidate('foo', foo = $$props.foo); - if ('bar' in $$props) $$invalidate('bar', bar = $$props.bar); - if ('baz' in $$props) $$invalidate('baz', baz = $$props.baz); + if ("things" in $$props) $$invalidate(0, things = $$props.things); + if ("foo" in $$props) $$invalidate(1, foo = $$props.foo); + if ("bar" in $$props) $$invalidate(2, bar = $$props.bar); + if ("baz" in $$props) $$invalidate(3, baz = $$props.baz); }; - $$self.$capture_state = () => { - return { things, foo, bar, baz }; - }; + $$self.$capture_state = () => ({ things, foo, bar, baz }); $$self.$inject_state = $$props => { - if ('things' in $$props) $$invalidate('things', things = $$props.things); - if ('foo' in $$props) $$invalidate('foo', foo = $$props.foo); - if ('bar' in $$props) $$invalidate('bar', bar = $$props.bar); - if ('baz' in $$props) $$invalidate('baz', baz = $$props.baz); + if ("things" in $$props) $$invalidate(0, things = $$props.things); + if ("foo" in $$props) $$invalidate(1, foo = $$props.foo); + if ("bar" in $$props) $$invalidate(2, bar = $$props.bar); + if ("baz" in $$props) $$invalidate(3, baz = $$props.baz); }; - return { things, foo, bar, baz }; + if ($$props && "$$inject" in $$props) { + $$self.$inject_state($$props.$$inject); + } + + return [things, foo, bar, baz]; } class Component extends SvelteComponentDev { constructor(options) { super(options); - init(this, options, instance, create_fragment, safe_not_equal, ["things", "foo", "bar", "baz"]); - dispatch_dev("SvelteRegisterComponent", { component: this, tagName: "Component", options, id: create_fragment.name }); + init(this, options, instance, create_fragment, safe_not_equal, { things: 0, foo: 1, bar: 2, baz: 3 }); + + dispatch_dev("SvelteRegisterComponent", { + component: this, + tagName: "Component", + options, + id: create_fragment.name + }); const { ctx } = this.$$; const props = options.props || {}; - if (ctx.things === undefined && !('things' in props)) { + + if (/*things*/ ctx[0] === undefined && !("things" in props)) { console.warn(" was created without expected prop 'things'"); } - if (ctx.foo === undefined && !('foo' in props)) { + + if (/*foo*/ ctx[1] === undefined && !("foo" in props)) { console.warn(" was created without expected prop 'foo'"); } - if (ctx.bar === undefined && !('bar' in props)) { + + if (/*bar*/ ctx[2] === undefined && !("bar" in props)) { console.warn(" was created without expected prop 'bar'"); } - if (ctx.baz === undefined && !('baz' in props)) { + + if (/*baz*/ ctx[3] === undefined && !("baz" in props)) { console.warn(" was created without expected prop 'baz'"); } } diff --git a/test/js/samples/debug-foo/expected.js b/test/js/samples/debug-foo/expected.js index 08a92171d1..10129e1b28 100644 --- a/test/js/samples/debug-foo/expected.js +++ b/test/js/samples/debug-foo/expected.js @@ -13,20 +13,24 @@ import { safe_not_equal, set_data_dev, space, - text + text, + validate_each_argument } from "svelte/internal"; const file = undefined; function get_each_context(ctx, list, i) { - const child_ctx = Object.create(ctx); - child_ctx.thing = list[i]; + const child_ctx = ctx.slice(); + child_ctx[2] = list[i]; return child_ctx; } // (6:0) {#each things as thing} function create_each_block(ctx) { - var span, t0_value = ctx.thing.name + "", t0, t1; + let span; + let t0_value = /*thing*/ ctx[2].name + ""; + let t0; + let t1; const block = { c: function create() { @@ -35,47 +39,51 @@ function create_each_block(ctx) { t1 = space(); { - const { foo } = ctx; + const foo = /*foo*/ ctx[1]; console.log({ foo }); debugger; } + add_location(span, file, 6, 1, 82); }, - m: function mount(target, anchor) { insert_dev(target, span, anchor); append_dev(span, t0); insert_dev(target, t1, anchor); }, + p: function update(ctx, dirty) { + if (dirty & /*things*/ 1 && t0_value !== (t0_value = /*thing*/ ctx[2].name + "")) set_data_dev(t0, t0_value); - p: function update(changed, ctx) { - if ((changed.things) && t0_value !== (t0_value = ctx.thing.name + "")) { - set_data_dev(t0, t0_value); - } - - if (changed.foo) { - const { foo } = ctx; + if (dirty & /*foo*/ 2) { + const foo = /*foo*/ ctx[1]; console.log({ foo }); debugger; } }, - d: function destroy(detaching) { - if (detaching) { - detach_dev(span); - detach_dev(t1); - } + if (detaching) detach_dev(span); + if (detaching) detach_dev(t1); } }; - dispatch_dev("SvelteRegisterBlock", { block, id: create_each_block.name, type: "each", source: "(6:0) {#each things as thing}", ctx }); + + dispatch_dev("SvelteRegisterBlock", { + block, + id: create_each_block.name, + type: "each", + source: "(6:0) {#each things as thing}", + ctx + }); + return block; } function create_fragment(ctx) { - var t0, p, t1, t2; - - let each_value = ctx.things; - + let t0; + let p; + let t1; + let t2; + let each_value = /*things*/ ctx[0]; + validate_each_argument(each_value); let each_blocks = []; for (let i = 0; i < each_value.length; i += 1) { @@ -91,14 +99,12 @@ function create_fragment(ctx) { t0 = space(); p = element("p"); t1 = text("foo: "); - t2 = text(ctx.foo); + t2 = text(/*foo*/ ctx[1]); add_location(p, file, 10, 0, 131); }, - l: function claim(nodes) { throw new Error("options.hydrate only works if the component was compiled with the `hydratable: true` option"); }, - m: function mount(target, anchor) { for (let i = 0; i < each_blocks.length; i += 1) { each_blocks[i].m(target, anchor); @@ -109,17 +115,17 @@ function create_fragment(ctx) { append_dev(p, t1); append_dev(p, t2); }, - - p: function update(changed, ctx) { - if (changed.things) { - each_value = ctx.things; - + p: function update(ctx, [dirty]) { + if (dirty & /*things*/ 1) { + each_value = /*things*/ ctx[0]; + validate_each_argument(each_value); let i; + for (i = 0; i < each_value.length; i += 1) { const child_ctx = get_each_context(ctx, each_value, i); if (each_blocks[i]) { - each_blocks[i].p(changed, child_ctx); + each_blocks[i].p(child_ctx, dirty); } else { each_blocks[i] = create_each_block(child_ctx); each_blocks[i].c(); @@ -130,67 +136,80 @@ function create_fragment(ctx) { for (; i < each_blocks.length; i += 1) { each_blocks[i].d(1); } + each_blocks.length = each_value.length; } - if (changed.foo) { - set_data_dev(t2, ctx.foo); - } + if (dirty & /*foo*/ 2) set_data_dev(t2, /*foo*/ ctx[1]); }, - i: noop, o: noop, - d: function destroy(detaching) { destroy_each(each_blocks, detaching); - - if (detaching) { - detach_dev(t0); - detach_dev(p); - } + if (detaching) detach_dev(t0); + if (detaching) detach_dev(p); } }; - dispatch_dev("SvelteRegisterBlock", { block, id: create_fragment.name, type: "component", source: "", ctx }); + + dispatch_dev("SvelteRegisterBlock", { + block, + id: create_fragment.name, + type: "component", + source: "", + ctx + }); + return block; } function instance($$self, $$props, $$invalidate) { - let { things, foo } = $$props; + let { things } = $$props; + let { foo } = $$props; + const writable_props = ["things", "foo"]; - const writable_props = ['things', 'foo']; Object.keys($$props).forEach(key => { - if (!writable_props.includes(key) && !key.startsWith('$$')) console.warn(` was created with unknown prop '${key}'`); + if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(` was created with unknown prop '${key}'`); }); $$self.$set = $$props => { - if ('things' in $$props) $$invalidate('things', things = $$props.things); - if ('foo' in $$props) $$invalidate('foo', foo = $$props.foo); + if ("things" in $$props) $$invalidate(0, things = $$props.things); + if ("foo" in $$props) $$invalidate(1, foo = $$props.foo); }; - $$self.$capture_state = () => { - return { things, foo }; - }; + $$self.$capture_state = () => ({ things, foo }); $$self.$inject_state = $$props => { - if ('things' in $$props) $$invalidate('things', things = $$props.things); - if ('foo' in $$props) $$invalidate('foo', foo = $$props.foo); + if ("things" in $$props) $$invalidate(0, things = $$props.things); + if ("foo" in $$props) $$invalidate(1, foo = $$props.foo); }; - return { things, foo }; + if ($$props && "$$inject" in $$props) { + $$self.$inject_state($$props.$$inject); + } + + return [things, foo]; } class Component extends SvelteComponentDev { constructor(options) { super(options); - init(this, options, instance, create_fragment, safe_not_equal, ["things", "foo"]); - dispatch_dev("SvelteRegisterComponent", { component: this, tagName: "Component", options, id: create_fragment.name }); + init(this, options, instance, create_fragment, safe_not_equal, { things: 0, foo: 1 }); + + dispatch_dev("SvelteRegisterComponent", { + component: this, + tagName: "Component", + options, + id: create_fragment.name + }); const { ctx } = this.$$; const props = options.props || {}; - if (ctx.things === undefined && !('things' in props)) { + + if (/*things*/ ctx[0] === undefined && !("things" in props)) { console.warn(" was created without expected prop 'things'"); } - if (ctx.foo === undefined && !('foo' in props)) { + + if (/*foo*/ ctx[1] === undefined && !("foo" in props)) { console.warn(" was created without expected prop 'foo'"); } } diff --git a/test/js/samples/debug-hoisted/expected.js b/test/js/samples/debug-hoisted/expected.js index 62327860e2..c77168ef4f 100644 --- a/test/js/samples/debug-hoisted/expected.js +++ b/test/js/samples/debug-hoisted/expected.js @@ -13,56 +13,68 @@ function create_fragment(ctx) { const block = { c: function create() { { - const { obj } = ctx; + const obj = /*obj*/ ctx[0]; + const kobzol = /*kobzol*/ ctx[1]; console.log({ obj, kobzol }); debugger; } }, - l: function claim(nodes) { throw new Error("options.hydrate only works if the component was compiled with the `hydratable: true` option"); }, - m: noop, - - p: function update(changed, ctx) { - if (changed.obj || changed.kobzol) { - const { obj } = ctx; + p: function update(ctx, [dirty]) { + if (dirty & /*obj, kobzol*/ 3) { + const obj = /*obj*/ ctx[0]; + const kobzol = /*kobzol*/ ctx[1]; console.log({ obj, kobzol }); debugger; } }, - i: noop, o: noop, d: noop }; - dispatch_dev("SvelteRegisterBlock", { block, id: create_fragment.name, type: "component", source: "", ctx }); + + dispatch_dev("SvelteRegisterBlock", { + block, + id: create_fragment.name, + type: "component", + source: "", + ctx + }); + return block; } -let kobzol = 5; - -function instance($$self) { +function instance($$self, $$props, $$invalidate) { let obj = { x: 5 }; - - $$self.$capture_state = () => { - return {}; - }; + let kobzol = 5; + $$self.$capture_state = () => ({ obj, kobzol }); $$self.$inject_state = $$props => { - if ('obj' in $$props) $$invalidate('obj', obj = $$props.obj); - if ('kobzol' in $$props) $$invalidate('kobzol', kobzol = $$props.kobzol); + if ("obj" in $$props) $$invalidate(0, obj = $$props.obj); + if ("kobzol" in $$props) $$invalidate(1, kobzol = $$props.kobzol); }; - return { obj }; + if ($$props && "$$inject" in $$props) { + $$self.$inject_state($$props.$$inject); + } + + return [obj, kobzol]; } class Component extends SvelteComponentDev { constructor(options) { super(options); - init(this, options, instance, create_fragment, safe_not_equal, []); - dispatch_dev("SvelteRegisterComponent", { component: this, tagName: "Component", options, id: create_fragment.name }); + init(this, options, instance, create_fragment, safe_not_equal, {}); + + dispatch_dev("SvelteRegisterComponent", { + component: this, + tagName: "Component", + options, + id: create_fragment.name + }); } } diff --git a/test/js/samples/debug-no-dependencies/_config.js b/test/js/samples/debug-no-dependencies/_config.js new file mode 100644 index 0000000000..b1f2518e8a --- /dev/null +++ b/test/js/samples/debug-no-dependencies/_config.js @@ -0,0 +1,5 @@ +export default { + options: { + dev: true + } +}; \ No newline at end of file diff --git a/test/js/samples/debug-no-dependencies/expected.js b/test/js/samples/debug-no-dependencies/expected.js new file mode 100644 index 0000000000..9985c814a2 --- /dev/null +++ b/test/js/samples/debug-no-dependencies/expected.js @@ -0,0 +1,151 @@ +/* generated by Svelte vX.Y.Z */ +import { + SvelteComponentDev, + destroy_each, + detach_dev, + dispatch_dev, + empty, + init, + insert_dev, + noop, + safe_not_equal, + space, + text, + validate_each_argument +} from "svelte/internal"; + +const file = undefined; + +function get_each_context(ctx, list, i) { + const child_ctx = ctx.slice(); + child_ctx[0] = list[i]; + child_ctx[2] = i; + return child_ctx; +} + +// (4:0) {#each things as thing, index} +function create_each_block(ctx) { + let t0; + let t1_value = /*thing*/ ctx[0] + ""; + let t1; + + const block = { + c: function create() { + { + const index = /*index*/ ctx[2]; + console.log({ index }); + debugger; + } + + t0 = space(); + t1 = text(t1_value); + }, + m: function mount(target, anchor) { + insert_dev(target, t0, anchor); + insert_dev(target, t1, anchor); + }, + p: noop, + d: function destroy(detaching) { + if (detaching) detach_dev(t0); + if (detaching) detach_dev(t1); + } + }; + + dispatch_dev("SvelteRegisterBlock", { + block, + id: create_each_block.name, + type: "each", + source: "(4:0) {#each things as thing, index}", + ctx + }); + + return block; +} + +function create_fragment(ctx) { + let each_1_anchor; + let each_value = things; + validate_each_argument(each_value); + let each_blocks = []; + + for (let i = 0; i < each_value.length; i += 1) { + each_blocks[i] = create_each_block(get_each_context(ctx, each_value, i)); + } + + const block = { + c: function create() { + for (let i = 0; i < each_blocks.length; i += 1) { + each_blocks[i].c(); + } + + each_1_anchor = empty(); + }, + l: function claim(nodes) { + throw new Error("options.hydrate only works if the component was compiled with the `hydratable: true` option"); + }, + m: function mount(target, anchor) { + for (let i = 0; i < each_blocks.length; i += 1) { + each_blocks[i].m(target, anchor); + } + + insert_dev(target, each_1_anchor, anchor); + }, + p: function update(ctx, [dirty]) { + if (dirty & /*things*/ 0) { + each_value = things; + validate_each_argument(each_value); + let i; + + for (i = 0; i < each_value.length; i += 1) { + const child_ctx = get_each_context(ctx, each_value, i); + + if (each_blocks[i]) { + each_blocks[i].p(child_ctx, dirty); + } else { + each_blocks[i] = create_each_block(child_ctx); + each_blocks[i].c(); + each_blocks[i].m(each_1_anchor.parentNode, each_1_anchor); + } + } + + for (; i < each_blocks.length; i += 1) { + each_blocks[i].d(1); + } + + each_blocks.length = each_value.length; + } + }, + i: noop, + o: noop, + d: function destroy(detaching) { + destroy_each(each_blocks, detaching); + if (detaching) detach_dev(each_1_anchor); + } + }; + + dispatch_dev("SvelteRegisterBlock", { + block, + id: create_fragment.name, + type: "component", + source: "", + ctx + }); + + return block; +} + +class Component extends SvelteComponentDev { + constructor(options) { + super(options); + init(this, options, null, create_fragment, safe_not_equal, {}); + + dispatch_dev("SvelteRegisterComponent", { + component: this, + tagName: "Component", + options, + id: create_fragment.name + }); + } +} + +export default Component; \ No newline at end of file diff --git a/test/js/samples/debug-no-dependencies/input.svelte b/test/js/samples/debug-no-dependencies/input.svelte new file mode 100644 index 0000000000..b2f0200be0 --- /dev/null +++ b/test/js/samples/debug-no-dependencies/input.svelte @@ -0,0 +1,7 @@ + + +{#each things as thing, index} + {@debug index} + {thing} +{/each} \ No newline at end of file diff --git a/test/js/samples/debug-ssr-foo/expected.js b/test/js/samples/debug-ssr-foo/expected.js index 1b51af2592..fe34a6a4fd 100644 --- a/test/js/samples/debug-ssr-foo/expected.js +++ b/test/js/samples/debug-ssr-foo/expected.js @@ -1,21 +1,16 @@ /* generated by Svelte vX.Y.Z */ -import { - create_ssr_component, - debug, - each, - escape -} from "svelte/internal"; +import { create_ssr_component, debug, each, escape } from "svelte/internal"; const Component = create_ssr_component(($$result, $$props, $$bindings, $$slots) => { - let { things, foo } = $$props; - + let { things } = $$props; + let { foo } = $$props; if ($$props.things === void 0 && $$bindings.things && things !== void 0) $$bindings.things(things); if ($$props.foo === void 0 && $$bindings.foo && foo !== void 0) $$bindings.foo(foo); - return `${each(things, (thing) => `${escape(thing.name)} - ${debug(null, 7, 2, { foo })}`)} + return `${each(things, thing => `${escape(thing.name)} + ${debug(null, 7, 2, { foo })}`)} -

foo: ${escape(foo)}

`; +

foo: ${escape(foo)}

`; }); export default Component; \ No newline at end of file diff --git a/test/js/samples/deconflict-builtins/expected.js b/test/js/samples/deconflict-builtins/expected.js index 6609fcccf7..fb98844ef7 100644 --- a/test/js/samples/deconflict-builtins/expected.js +++ b/test/js/samples/deconflict-builtins/expected.js @@ -15,45 +15,38 @@ import { } from "svelte/internal"; function get_each_context(ctx, list, i) { - const child_ctx = Object.create(ctx); - child_ctx.node = list[i]; + const child_ctx = ctx.slice(); + child_ctx[1] = list[i]; return child_ctx; } // (5:0) {#each createElement as node} function create_each_block(ctx) { - var span, t_value = ctx.node + "", t; + let span; + let t_value = /*node*/ ctx[1] + ""; + let t; return { c() { span = element("span"); t = text(t_value); }, - m(target, anchor) { insert(target, span, anchor); append(span, t); }, - - p(changed, ctx) { - if ((changed.createElement) && t_value !== (t_value = ctx.node + "")) { - set_data(t, t_value); - } + p(ctx, dirty) { + if (dirty & /*createElement*/ 1 && t_value !== (t_value = /*node*/ ctx[1] + "")) set_data(t, t_value); }, - d(detaching) { - if (detaching) { - detach(span); - } + if (detaching) detach(span); } }; } function create_fragment(ctx) { - var each_1_anchor; - - let each_value = ctx.createElement; - + let each_1_anchor; + let each_value = /*createElement*/ ctx[0]; let each_blocks = []; for (let i = 0; i < each_value.length; i += 1) { @@ -68,7 +61,6 @@ function create_fragment(ctx) { each_1_anchor = empty(); }, - m(target, anchor) { for (let i = 0; i < each_blocks.length; i += 1) { each_blocks[i].m(target, anchor); @@ -76,17 +68,16 @@ function create_fragment(ctx) { insert(target, each_1_anchor, anchor); }, - - p(changed, ctx) { - if (changed.createElement) { - each_value = ctx.createElement; - + p(ctx, [dirty]) { + if (dirty & /*createElement*/ 1) { + each_value = /*createElement*/ ctx[0]; let i; + for (i = 0; i < each_value.length; i += 1) { const child_ctx = get_each_context(ctx, each_value, i); if (each_blocks[i]) { - each_blocks[i].p(changed, child_ctx); + each_blocks[i].p(child_ctx, dirty); } else { each_blocks[i] = create_each_block(child_ctx); each_blocks[i].c(); @@ -97,19 +88,15 @@ function create_fragment(ctx) { for (; i < each_blocks.length; i += 1) { each_blocks[i].d(1); } + each_blocks.length = each_value.length; } }, - i: noop, o: noop, - d(detaching) { destroy_each(each_blocks, detaching); - - if (detaching) { - detach(each_1_anchor); - } + if (detaching) detach(each_1_anchor); } }; } @@ -118,16 +105,16 @@ function instance($$self, $$props, $$invalidate) { let { createElement } = $$props; $$self.$set = $$props => { - if ('createElement' in $$props) $$invalidate('createElement', createElement = $$props.createElement); + if ("createElement" in $$props) $$invalidate(0, createElement = $$props.createElement); }; - return { createElement }; + return [createElement]; } class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, instance, create_fragment, safe_not_equal, ["createElement"]); + init(this, options, instance, create_fragment, safe_not_equal, { createElement: 0 }); } } diff --git a/test/js/samples/deconflict-globals/expected.js b/test/js/samples/deconflict-globals/expected.js index 347d0417ec..7e83c21f0e 100644 --- a/test/js/samples/deconflict-globals/expected.js +++ b/test/js/samples/deconflict-globals/expected.js @@ -1,41 +1,26 @@ /* generated by Svelte vX.Y.Z */ -import { - SvelteComponent, - init, - noop, - safe_not_equal -} from "svelte/internal"; -import { onMount } from "svelte"; +import { SvelteComponent, init, safe_not_equal } from "svelte/internal"; -function create_fragment(ctx) { - return { - c: noop, - m: noop, - p: noop, - i: noop, - o: noop, - d: noop - }; -} +import { onMount } from "svelte"; function instance($$self, $$props, $$invalidate) { - let { foo = 'bar' } = $$props; + let { foo = "bar" } = $$props; onMount(() => { alert(JSON.stringify(data())); }); $$self.$set = $$props => { - if ('foo' in $$props) $$invalidate('foo', foo = $$props.foo); + if ("foo" in $$props) $$invalidate(0, foo = $$props.foo); }; - return { foo }; + return [foo]; } class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, instance, create_fragment, safe_not_equal, ["foo"]); + init(this, options, instance, null, safe_not_equal, { foo: 0 }); } } diff --git a/test/js/samples/dev-warning-missing-data-computed/expected.js b/test/js/samples/dev-warning-missing-data-computed/expected.js index ad0cbc8aba..9c28e04064 100644 --- a/test/js/samples/dev-warning-missing-data-computed/expected.js +++ b/test/js/samples/dev-warning-missing-data-computed/expected.js @@ -18,90 +18,100 @@ import { const file = undefined; function create_fragment(ctx) { - var p, t0_value = Math.max(0, ctx.foo) + "", t0, t1, t2; + let p; + let t0_value = Math.max(0, /*foo*/ ctx[0]) + ""; + let t0; + let t1; + let t2; const block = { c: function create() { p = element("p"); t0 = text(t0_value); t1 = space(); - t2 = text(ctx.bar); + t2 = text(/*bar*/ ctx[1]); add_location(p, file, 7, 0, 67); }, - l: function claim(nodes) { throw new Error("options.hydrate only works if the component was compiled with the `hydratable: true` option"); }, - m: function mount(target, anchor) { insert_dev(target, p, anchor); append_dev(p, t0); append_dev(p, t1); append_dev(p, t2); }, - - p: function update(changed, ctx) { - if ((changed.foo) && t0_value !== (t0_value = Math.max(0, ctx.foo) + "")) { - set_data_dev(t0, t0_value); - } - - if (changed.bar) { - set_data_dev(t2, ctx.bar); - } + p: function update(ctx, [dirty]) { + if (dirty & /*foo*/ 1 && t0_value !== (t0_value = Math.max(0, /*foo*/ ctx[0]) + "")) set_data_dev(t0, t0_value); + if (dirty & /*bar*/ 2) set_data_dev(t2, /*bar*/ ctx[1]); }, - i: noop, o: noop, - d: function destroy(detaching) { - if (detaching) { - detach_dev(p); - } + if (detaching) detach_dev(p); } }; - dispatch_dev("SvelteRegisterBlock", { block, id: create_fragment.name, type: "component", source: "", ctx }); + + dispatch_dev("SvelteRegisterBlock", { + block, + id: create_fragment.name, + type: "component", + source: "", + ctx + }); + return block; } function instance($$self, $$props, $$invalidate) { let { foo } = $$props; - let bar; + const writable_props = ["foo"]; - const writable_props = ['foo']; Object.keys($$props).forEach(key => { - if (!writable_props.includes(key) && !key.startsWith('$$')) console.warn(` was created with unknown prop '${key}'`); + if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(` was created with unknown prop '${key}'`); }); $$self.$set = $$props => { - if ('foo' in $$props) $$invalidate('foo', foo = $$props.foo); + if ("foo" in $$props) $$invalidate(0, foo = $$props.foo); }; - $$self.$capture_state = () => { - return { foo, bar }; - }; + $$self.$capture_state = () => ({ foo, bar }); $$self.$inject_state = $$props => { - if ('foo' in $$props) $$invalidate('foo', foo = $$props.foo); - if ('bar' in $$props) $$invalidate('bar', bar = $$props.bar); + if ("foo" in $$props) $$invalidate(0, foo = $$props.foo); + if ("bar" in $$props) $$invalidate(1, bar = $$props.bar); }; - $$self.$$.update = ($$dirty = { foo: 1 }) => { - if ($$dirty.foo) { $$invalidate('bar', bar = foo * 2); } + if ($$props && "$$inject" in $$props) { + $$self.$inject_state($$props.$$inject); + } + + $$self.$$.update = () => { + if ($$self.$$.dirty & /*foo*/ 1) { + $: $$invalidate(1, bar = foo * 2); + } }; - return { foo, bar }; + return [foo, bar]; } class Component extends SvelteComponentDev { constructor(options) { super(options); - init(this, options, instance, create_fragment, safe_not_equal, ["foo"]); - dispatch_dev("SvelteRegisterComponent", { component: this, tagName: "Component", options, id: create_fragment.name }); + init(this, options, instance, create_fragment, safe_not_equal, { foo: 0 }); + + dispatch_dev("SvelteRegisterComponent", { + component: this, + tagName: "Component", + options, + id: create_fragment.name + }); const { ctx } = this.$$; const props = options.props || {}; - if (ctx.foo === undefined && !('foo' in props)) { + + if (/*foo*/ ctx[0] === undefined && !("foo" in props)) { console.warn(" was created without expected prop 'foo'"); } } diff --git a/test/js/samples/dont-invalidate-this/expected.js b/test/js/samples/dont-invalidate-this/expected.js index 92033148eb..f5f6d07812 100644 --- a/test/js/samples/dont-invalidate-this/expected.js +++ b/test/js/samples/dont-invalidate-this/expected.js @@ -11,27 +11,22 @@ import { } from "svelte/internal"; function create_fragment(ctx) { - var input, dispose; + let input; + let dispose; return { c() { input = element("input"); - dispose = listen(input, "input", make_uppercase); }, - m(target, anchor) { insert(target, input, anchor); + dispose = listen(input, "input", make_uppercase); }, - p: noop, i: noop, o: noop, - d(detaching) { - if (detaching) { - detach(input); - } - + if (detaching) detach(input); dispose(); } }; @@ -44,7 +39,7 @@ function make_uppercase() { class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, null, create_fragment, safe_not_equal, []); + init(this, options, null, create_fragment, safe_not_equal, {}); } } diff --git a/test/js/samples/dynamic-import/expected.js b/test/js/samples/dynamic-import/expected.js index 8692cd89b2..4394e7d8a9 100644 --- a/test/js/samples/dynamic-import/expected.js +++ b/test/js/samples/dynamic-import/expected.js @@ -1,6 +1,7 @@ /* generated by Svelte vX.Y.Z */ import { SvelteComponent, + create_component, destroy_component, init, mount_component, @@ -9,49 +10,43 @@ import { transition_in, transition_out } from "svelte/internal"; + import LazyLoad from "./LazyLoad.svelte"; function create_fragment(ctx) { - var current; - - var lazyload = new LazyLoad({ props: { load: func } }); + let current; + const lazyload = new LazyLoad({ props: { load: func } }); return { c() { - lazyload.$$.fragment.c(); + create_component(lazyload.$$.fragment); }, - m(target, anchor) { mount_component(lazyload, target, anchor); current = true; }, - p: noop, - i(local) { if (current) return; transition_in(lazyload.$$.fragment, local); - current = true; }, - o(local) { transition_out(lazyload.$$.fragment, local); current = false; }, - d(detaching) { destroy_component(lazyload, detaching); } }; } -const func = () => import('./Foo.svelte'); +const func = () => import("./Foo.svelte"); class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, null, create_fragment, safe_not_equal, []); + init(this, options, null, create_fragment, safe_not_equal, {}); } } diff --git a/test/js/samples/each-block-array-literal/expected.js b/test/js/samples/each-block-array-literal/expected.js index 6ca6773f6b..10d835cf78 100644 --- a/test/js/samples/each-block-array-literal/expected.js +++ b/test/js/samples/each-block-array-literal/expected.js @@ -15,45 +15,38 @@ import { } from "svelte/internal"; function get_each_context(ctx, list, i) { - const child_ctx = Object.create(ctx); - child_ctx.num = list[i]; + const child_ctx = ctx.slice(); + child_ctx[5] = list[i]; return child_ctx; } // (9:0) {#each [a, b, c, d, e] as num} function create_each_block(ctx) { - var span, t_value = ctx.num + "", t; + let span; + let t_value = /*num*/ ctx[5] + ""; + let t; return { c() { span = element("span"); t = text(t_value); }, - m(target, anchor) { insert(target, span, anchor); append(span, t); }, - - p(changed, ctx) { - if ((changed.a || changed.b || changed.c || changed.d || changed.e) && t_value !== (t_value = ctx.num + "")) { - set_data(t, t_value); - } + p(ctx, dirty) { + if (dirty & /*a, b, c, d, e*/ 31 && t_value !== (t_value = /*num*/ ctx[5] + "")) set_data(t, t_value); }, - d(detaching) { - if (detaching) { - detach(span); - } + if (detaching) detach(span); } }; } function create_fragment(ctx) { - var each_1_anchor; - - let each_value = [ctx.a, ctx.b, ctx.c, ctx.d, ctx.e]; - + let each_1_anchor; + let each_value = [/*a*/ ctx[0], /*b*/ ctx[1], /*c*/ ctx[2], /*d*/ ctx[3], /*e*/ ctx[4]]; let each_blocks = []; for (let i = 0; i < 5; i += 1) { @@ -68,7 +61,6 @@ function create_fragment(ctx) { each_1_anchor = empty(); }, - m(target, anchor) { for (let i = 0; i < 5; i += 1) { each_blocks[i].m(target, anchor); @@ -76,17 +68,16 @@ function create_fragment(ctx) { insert(target, each_1_anchor, anchor); }, - - p(changed, ctx) { - if (changed.a || changed.b || changed.c || changed.d || changed.e) { - each_value = [ctx.a, ctx.b, ctx.c, ctx.d, ctx.e]; - + p(ctx, [dirty]) { + if (dirty & /*a, b, c, d, e*/ 31) { + each_value = [/*a*/ ctx[0], /*b*/ ctx[1], /*c*/ ctx[2], /*d*/ ctx[3], /*e*/ ctx[4]]; let i; - for (i = 0; i < each_value.length; i += 1) { + + for (i = 0; i < 5; i += 1) { const child_ctx = get_each_context(ctx, each_value, i); if (each_blocks[i]) { - each_blocks[i].p(changed, child_ctx); + each_blocks[i].p(child_ctx, dirty); } else { each_blocks[i] = create_each_block(child_ctx); each_blocks[i].c(); @@ -99,38 +90,37 @@ function create_fragment(ctx) { } } }, - i: noop, o: noop, - d(detaching) { destroy_each(each_blocks, detaching); - - if (detaching) { - detach(each_1_anchor); - } + if (detaching) detach(each_1_anchor); } }; } function instance($$self, $$props, $$invalidate) { - let { a, b, c, d, e } = $$props; + let { a } = $$props; + let { b } = $$props; + let { c } = $$props; + let { d } = $$props; + let { e } = $$props; $$self.$set = $$props => { - if ('a' in $$props) $$invalidate('a', a = $$props.a); - if ('b' in $$props) $$invalidate('b', b = $$props.b); - if ('c' in $$props) $$invalidate('c', c = $$props.c); - if ('d' in $$props) $$invalidate('d', d = $$props.d); - if ('e' in $$props) $$invalidate('e', e = $$props.e); + if ("a" in $$props) $$invalidate(0, a = $$props.a); + if ("b" in $$props) $$invalidate(1, b = $$props.b); + if ("c" in $$props) $$invalidate(2, c = $$props.c); + if ("d" in $$props) $$invalidate(3, d = $$props.d); + if ("e" in $$props) $$invalidate(4, e = $$props.e); }; - return { a, b, c, d, e }; + return [a, b, c, d, e]; } class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, instance, create_fragment, safe_not_equal, ["a", "b", "c", "d", "e"]); + init(this, options, instance, create_fragment, safe_not_equal, { a: 0, b: 1, c: 2, d: 3, e: 4 }); } } diff --git a/test/js/samples/each-block-changed-check/expected.js b/test/js/samples/each-block-changed-check/expected.js index 0601c31334..5d88032b87 100644 --- a/test/js/samples/each-block-changed-check/expected.js +++ b/test/js/samples/each-block-changed-check/expected.js @@ -17,21 +17,34 @@ import { } from "svelte/internal"; function get_each_context(ctx, list, i) { - const child_ctx = Object.create(ctx); - child_ctx.comment = list[i]; - child_ctx.i = i; + const child_ctx = ctx.slice(); + child_ctx[4] = list[i]; + child_ctx[6] = i; return child_ctx; } // (8:0) {#each comments as comment, i} function create_each_block(ctx) { - var div, strong, t0, t1, span, t2_value = ctx.comment.author + "", t2, t3, t4_value = ctx.elapsed(ctx.comment.time, ctx.time) + "", t4, t5, t6, html_tag, raw_value = ctx.comment.html + ""; + let div; + let strong; + let t0; + let t1; + let span; + let t2_value = /*comment*/ ctx[4].author + ""; + let t2; + let t3; + let t4_value = /*elapsed*/ ctx[1](/*comment*/ ctx[4].time, /*time*/ ctx[2]) + ""; + let t4; + let t5; + let t6; + let html_tag; + let raw_value = /*comment*/ ctx[4].html + ""; return { c() { div = element("div"); strong = element("strong"); - t0 = text(ctx.i); + t0 = text(/*i*/ ctx[6]); t1 = space(); span = element("span"); t2 = text(t2_value); @@ -43,7 +56,6 @@ function create_each_block(ctx) { html_tag = new HtmlTag(raw_value, null); attr(div, "class", "comment"); }, - m(target, anchor) { insert(target, div, anchor); append(div, strong); @@ -57,34 +69,22 @@ function create_each_block(ctx) { append(div, t6); html_tag.m(div); }, - - p(changed, ctx) { - if ((changed.comments) && t2_value !== (t2_value = ctx.comment.author + "")) { - set_data(t2, t2_value); - } - - if ((changed.elapsed || changed.comments || changed.time) && t4_value !== (t4_value = ctx.elapsed(ctx.comment.time, ctx.time) + "")) { - set_data(t4, t4_value); - } - - if ((changed.comments) && raw_value !== (raw_value = ctx.comment.html + "")) { - html_tag.p(raw_value); - } + p(ctx, dirty) { + if (dirty & /*comments*/ 1 && t2_value !== (t2_value = /*comment*/ ctx[4].author + "")) set_data(t2, t2_value); + if (dirty & /*elapsed, comments, time*/ 7 && t4_value !== (t4_value = /*elapsed*/ ctx[1](/*comment*/ ctx[4].time, /*time*/ ctx[2]) + "")) set_data(t4, t4_value); + if (dirty & /*comments*/ 1 && raw_value !== (raw_value = /*comment*/ ctx[4].html + "")) html_tag.p(raw_value); }, - d(detaching) { - if (detaching) { - detach(div); - } + if (detaching) detach(div); } }; } function create_fragment(ctx) { - var t0, p, t1; - - let each_value = ctx.comments; - + let t0; + let p; + let t1; + let each_value = /*comments*/ ctx[0]; let each_blocks = []; for (let i = 0; i < each_value.length; i += 1) { @@ -99,9 +99,8 @@ function create_fragment(ctx) { t0 = space(); p = element("p"); - t1 = text(ctx.foo); + t1 = text(/*foo*/ ctx[3]); }, - m(target, anchor) { for (let i = 0; i < each_blocks.length; i += 1) { each_blocks[i].m(target, anchor); @@ -111,17 +110,16 @@ function create_fragment(ctx) { insert(target, p, anchor); append(p, t1); }, - - p(changed, ctx) { - if (changed.comments || changed.elapsed || changed.time) { - each_value = ctx.comments; - + p(ctx, [dirty]) { + if (dirty & /*comments, elapsed, time*/ 7) { + each_value = /*comments*/ ctx[0]; let i; + for (i = 0; i < each_value.length; i += 1) { const child_ctx = get_each_context(ctx, each_value, i); if (each_blocks[i]) { - each_blocks[i].p(changed, child_ctx); + each_blocks[i].p(child_ctx, dirty); } else { each_blocks[i] = create_each_block(child_ctx); each_blocks[i].c(); @@ -132,45 +130,42 @@ function create_fragment(ctx) { for (; i < each_blocks.length; i += 1) { each_blocks[i].d(1); } + each_blocks.length = each_value.length; } - if (changed.foo) { - set_data(t1, ctx.foo); - } + if (dirty & /*foo*/ 8) set_data(t1, /*foo*/ ctx[3]); }, - i: noop, o: noop, - d(detaching) { destroy_each(each_blocks, detaching); - - if (detaching) { - detach(t0); - detach(p); - } + if (detaching) detach(t0); + if (detaching) detach(p); } }; } function instance($$self, $$props, $$invalidate) { - let { comments, elapsed, time, foo } = $$props; + let { comments } = $$props; + let { elapsed } = $$props; + let { time } = $$props; + let { foo } = $$props; $$self.$set = $$props => { - if ('comments' in $$props) $$invalidate('comments', comments = $$props.comments); - if ('elapsed' in $$props) $$invalidate('elapsed', elapsed = $$props.elapsed); - if ('time' in $$props) $$invalidate('time', time = $$props.time); - if ('foo' in $$props) $$invalidate('foo', foo = $$props.foo); + if ("comments" in $$props) $$invalidate(0, comments = $$props.comments); + if ("elapsed" in $$props) $$invalidate(1, elapsed = $$props.elapsed); + if ("time" in $$props) $$invalidate(2, time = $$props.time); + if ("foo" in $$props) $$invalidate(3, foo = $$props.foo); }; - return { comments, elapsed, time, foo }; + return [comments, elapsed, time, foo]; } class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, instance, create_fragment, safe_not_equal, ["comments", "elapsed", "time", "foo"]); + init(this, options, instance, create_fragment, safe_not_equal, { comments: 0, elapsed: 1, time: 2, foo: 3 }); } } diff --git a/test/js/samples/each-block-keyed-animated/expected.js b/test/js/samples/each-block-keyed-animated/expected.js index 25aa1e5c5d..7fb81c27a2 100644 --- a/test/js/samples/each-block-keyed-animated/expected.js +++ b/test/js/samples/each-block-keyed-animated/expected.js @@ -18,65 +18,57 @@ import { } from "svelte/internal"; function get_each_context(ctx, list, i) { - const child_ctx = Object.create(ctx); - child_ctx.thing = list[i]; + const child_ctx = ctx.slice(); + child_ctx[1] = list[i]; return child_ctx; } // (19:0) {#each things as thing (thing.id)} function create_each_block(key_1, ctx) { - var div, t_value = ctx.thing.name + "", t, rect, stop_animation = noop; + let div; + let t_value = /*thing*/ ctx[1].name + ""; + let t; + let rect; + let stop_animation = noop; return { key: key_1, - first: null, - c() { div = element("div"); t = text(t_value); this.first = div; }, - m(target, anchor) { insert(target, div, anchor); append(div, t); }, - - p(changed, ctx) { - if ((changed.things) && t_value !== (t_value = ctx.thing.name + "")) { - set_data(t, t_value); - } + p(ctx, dirty) { + if (dirty & /*things*/ 1 && t_value !== (t_value = /*thing*/ ctx[1].name + "")) set_data(t, t_value); }, - r() { rect = div.getBoundingClientRect(); }, - f() { fix_position(div); stop_animation(); }, - a() { stop_animation(); stop_animation = create_animation(div, rect, foo, {}); }, - d(detaching) { - if (detaching) { - detach(div); - } + if (detaching) detach(div); } }; } function create_fragment(ctx) { - var each_blocks = [], each_1_lookup = new Map(), each_1_anchor; - - let each_value = ctx.things; - - const get_key = ctx => ctx.thing.id; + let each_blocks = []; + let each_1_lookup = new Map(); + let each_1_anchor; + let each_value = /*things*/ ctx[0]; + const get_key = ctx => /*thing*/ ctx[1].id; for (let i = 0; i < each_value.length; i += 1) { let child_ctx = get_each_context(ctx, each_value, i); @@ -92,7 +84,6 @@ function create_fragment(ctx) { each_1_anchor = empty(); }, - m(target, anchor) { for (let i = 0; i < each_blocks.length; i += 1) { each_blocks[i].m(target, anchor); @@ -100,25 +91,22 @@ function create_fragment(ctx) { insert(target, each_1_anchor, anchor); }, - - p(changed, ctx) { - const each_value = ctx.things; - for (let i = 0; i < each_blocks.length; i += 1) each_blocks[i].r(); - each_blocks = update_keyed_each(each_blocks, changed, get_key, 1, ctx, each_value, each_1_lookup, each_1_anchor.parentNode, fix_and_destroy_block, create_each_block, each_1_anchor, get_each_context); - for (let i = 0; i < each_blocks.length; i += 1) each_blocks[i].a(); + p(ctx, [dirty]) { + if (dirty & /*things*/ 1) { + const each_value = /*things*/ ctx[0]; + for (let i = 0; i < each_blocks.length; i += 1) each_blocks[i].r(); + each_blocks = update_keyed_each(each_blocks, dirty, get_key, 1, ctx, each_value, each_1_lookup, each_1_anchor.parentNode, fix_and_destroy_block, create_each_block, each_1_anchor, get_each_context); + for (let i = 0; i < each_blocks.length; i += 1) each_blocks[i].a(); + } }, - i: noop, o: noop, - d(detaching) { for (let i = 0; i < each_blocks.length; i += 1) { each_blocks[i].d(detaching); } - if (detaching) { - detach(each_1_anchor); - } + if (detaching) detach(each_1_anchor); } }; } @@ -141,16 +129,16 @@ function instance($$self, $$props, $$invalidate) { let { things } = $$props; $$self.$set = $$props => { - if ('things' in $$props) $$invalidate('things', things = $$props.things); + if ("things" in $$props) $$invalidate(0, things = $$props.things); }; - return { things }; + return [things]; } class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, instance, create_fragment, safe_not_equal, ["things"]); + init(this, options, instance, create_fragment, safe_not_equal, { things: 0 }); } } diff --git a/test/js/samples/each-block-keyed/expected.js b/test/js/samples/each-block-keyed/expected.js index ae20825344..ad8c074e99 100644 --- a/test/js/samples/each-block-keyed/expected.js +++ b/test/js/samples/each-block-keyed/expected.js @@ -16,51 +16,44 @@ import { } from "svelte/internal"; function get_each_context(ctx, list, i) { - const child_ctx = Object.create(ctx); - child_ctx.thing = list[i]; + const child_ctx = ctx.slice(); + child_ctx[1] = list[i]; return child_ctx; } // (5:0) {#each things as thing (thing.id)} function create_each_block(key_1, ctx) { - var div, t_value = ctx.thing.name + "", t; + let div; + let t_value = /*thing*/ ctx[1].name + ""; + let t; return { key: key_1, - first: null, - c() { div = element("div"); t = text(t_value); this.first = div; }, - m(target, anchor) { insert(target, div, anchor); append(div, t); }, - - p(changed, ctx) { - if ((changed.things) && t_value !== (t_value = ctx.thing.name + "")) { - set_data(t, t_value); - } + p(ctx, dirty) { + if (dirty & /*things*/ 1 && t_value !== (t_value = /*thing*/ ctx[1].name + "")) set_data(t, t_value); }, - d(detaching) { - if (detaching) { - detach(div); - } + if (detaching) detach(div); } }; } function create_fragment(ctx) { - var each_blocks = [], each_1_lookup = new Map(), each_1_anchor; - - let each_value = ctx.things; - - const get_key = ctx => ctx.thing.id; + let each_blocks = []; + let each_1_lookup = new Map(); + let each_1_anchor; + let each_value = /*things*/ ctx[0]; + const get_key = ctx => /*thing*/ ctx[1].id; for (let i = 0; i < each_value.length; i += 1) { let child_ctx = get_each_context(ctx, each_value, i); @@ -76,7 +69,6 @@ function create_fragment(ctx) { each_1_anchor = empty(); }, - m(target, anchor) { for (let i = 0; i < each_blocks.length; i += 1) { each_blocks[i].m(target, anchor); @@ -84,23 +76,20 @@ function create_fragment(ctx) { insert(target, each_1_anchor, anchor); }, - - p(changed, ctx) { - const each_value = ctx.things; - each_blocks = update_keyed_each(each_blocks, changed, get_key, 1, ctx, each_value, each_1_lookup, each_1_anchor.parentNode, destroy_block, create_each_block, each_1_anchor, get_each_context); + p(ctx, [dirty]) { + if (dirty & /*things*/ 1) { + const each_value = /*things*/ ctx[0]; + each_blocks = update_keyed_each(each_blocks, dirty, get_key, 1, ctx, each_value, each_1_lookup, each_1_anchor.parentNode, destroy_block, create_each_block, each_1_anchor, get_each_context); + } }, - i: noop, o: noop, - d(detaching) { for (let i = 0; i < each_blocks.length; i += 1) { each_blocks[i].d(detaching); } - if (detaching) { - detach(each_1_anchor); - } + if (detaching) detach(each_1_anchor); } }; } @@ -109,16 +98,16 @@ function instance($$self, $$props, $$invalidate) { let { things } = $$props; $$self.$set = $$props => { - if ('things' in $$props) $$invalidate('things', things = $$props.things); + if ("things" in $$props) $$invalidate(0, things = $$props.things); }; - return { things }; + return [things]; } class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, instance, create_fragment, safe_not_equal, ["things"]); + init(this, options, instance, create_fragment, safe_not_equal, { things: 0 }); } } diff --git a/test/js/samples/empty-dom/expected.js b/test/js/samples/empty-dom/expected.js new file mode 100644 index 0000000000..d5c80be696 --- /dev/null +++ b/test/js/samples/empty-dom/expected.js @@ -0,0 +1,16 @@ +/* generated by Svelte vX.Y.Z */ +import { SvelteComponent, init, safe_not_equal } from "svelte/internal"; + +function instance($$self) { + const a = 1 + 2; + return []; +} + +class Component extends SvelteComponent { + constructor(options) { + super(); + init(this, options, instance, null, safe_not_equal, {}); + } +} + +export default Component; \ No newline at end of file diff --git a/test/js/samples/empty-dom/input.svelte b/test/js/samples/empty-dom/input.svelte new file mode 100644 index 0000000000..3098443ea3 --- /dev/null +++ b/test/js/samples/empty-dom/input.svelte @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/test/js/samples/event-handler-dynamic/expected.js b/test/js/samples/event-handler-dynamic/expected.js new file mode 100644 index 0000000000..16b4a3f626 --- /dev/null +++ b/test/js/samples/event-handler-dynamic/expected.js @@ -0,0 +1,104 @@ +/* generated by Svelte vX.Y.Z */ +import { + SvelteComponent, + append, + detach, + element, + init, + insert, + is_function, + listen, + noop, + run_all, + safe_not_equal, + set_data, + space, + text +} from "svelte/internal"; + +function create_fragment(ctx) { + let p0; + let button0; + let t1; + let button1; + let t3; + let p1; + let t4; + let t5; + let button2; + let dispose; + + return { + c() { + p0 = element("p"); + button0 = element("button"); + button0.textContent = "set handler 1"; + t1 = space(); + button1 = element("button"); + button1.textContent = "set handler 2"; + t3 = space(); + p1 = element("p"); + t4 = text(/*number*/ ctx[1]); + t5 = space(); + button2 = element("button"); + button2.textContent = "click"; + }, + m(target, anchor) { + insert(target, p0, anchor); + append(p0, button0); + append(p0, t1); + append(p0, button1); + insert(target, t3, anchor); + insert(target, p1, anchor); + append(p1, t4); + insert(target, t5, anchor); + insert(target, button2, anchor); + + dispose = [ + listen(button0, "click", /*updateHandler1*/ ctx[2]), + listen(button1, "click", /*updateHandler2*/ ctx[3]), + listen(button2, "click", function () { + if (is_function(/*clickHandler*/ ctx[0])) /*clickHandler*/ ctx[0].apply(this, arguments); + }) + ]; + }, + p(new_ctx, [dirty]) { + ctx = new_ctx; + if (dirty & /*number*/ 2) set_data(t4, /*number*/ ctx[1]); + }, + i: noop, + o: noop, + d(detaching) { + if (detaching) detach(p0); + if (detaching) detach(t3); + if (detaching) detach(p1); + if (detaching) detach(t5); + if (detaching) detach(button2); + run_all(dispose); + } + }; +} + +function instance($$self, $$props, $$invalidate) { + let clickHandler; + let number = 0; + + function updateHandler1() { + $$invalidate(0, clickHandler = () => $$invalidate(1, number = 1)); + } + + function updateHandler2() { + $$invalidate(0, clickHandler = () => $$invalidate(1, number = 2)); + } + + return [clickHandler, number, updateHandler1, updateHandler2]; +} + +class Component extends SvelteComponent { + constructor(options) { + super(); + init(this, options, instance, create_fragment, safe_not_equal, {}); + } +} + +export default Component; \ No newline at end of file diff --git a/test/js/samples/event-handler-dynamic/input.svelte b/test/js/samples/event-handler-dynamic/input.svelte new file mode 100644 index 0000000000..17c9ae6cf0 --- /dev/null +++ b/test/js/samples/event-handler-dynamic/input.svelte @@ -0,0 +1,23 @@ + + +

+ + +

+ +

{ number }

+ + \ No newline at end of file diff --git a/test/js/samples/event-handler-no-passive/expected.js b/test/js/samples/event-handler-no-passive/expected.js index 69285a29c6..c519fac668 100644 --- a/test/js/samples/event-handler-no-passive/expected.js +++ b/test/js/samples/event-handler-no-passive/expected.js @@ -12,40 +12,35 @@ import { } from "svelte/internal"; function create_fragment(ctx) { - var a, dispose; + let a; + let dispose; return { c() { a = element("a"); a.textContent = "this should not navigate to example.com"; attr(a, "href", "https://example.com"); - dispose = listen(a, "touchstart", touchstart_handler); }, - m(target, anchor) { insert(target, a, anchor); + dispose = listen(a, "touchstart", touchstart_handler); }, - p: noop, i: noop, o: noop, - d(detaching) { - if (detaching) { - detach(a); - } - + if (detaching) detach(a); dispose(); } }; } -const touchstart_handler = (e) => e.preventDefault(); +const touchstart_handler = e => e.preventDefault(); class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, null, create_fragment, safe_not_equal, []); + init(this, options, null, create_fragment, safe_not_equal, {}); } } diff --git a/test/js/samples/event-modifiers/expected.js b/test/js/samples/event-modifiers/expected.js index bd449ea5a4..c12c3523a0 100644 --- a/test/js/samples/event-modifiers/expected.js +++ b/test/js/samples/event-modifiers/expected.js @@ -16,7 +16,13 @@ import { } from "svelte/internal"; function create_fragment(ctx) { - var div, button0, t1, button1, t3, button2, dispose; + let div; + let button0; + let t1; + let button1; + let t3; + let button2; + let dispose; return { c() { @@ -29,14 +35,7 @@ function create_fragment(ctx) { t3 = space(); button2 = element("button"); button2.textContent = "or me!"; - dispose = [ - listen(button0, "click", stop_propagation(prevent_default(handleClick))), - listen(button1, "click", handleClick, { once: true, capture: true }), - listen(button2, "click", handleClick, true), - listen(div, "touchstart", handleTouchstart, { passive: true }) - ]; }, - m(target, anchor) { insert(target, div, anchor); append(div, button0); @@ -44,34 +43,36 @@ function create_fragment(ctx) { append(div, button1); append(div, t3); append(div, button2); - }, + dispose = [ + listen(button0, "click", stop_propagation(prevent_default(handleClick))), + listen(button1, "click", handleClick, { once: true, capture: true }), + listen(button2, "click", handleClick, true), + listen(div, "touchstart", handleTouchstart, { passive: true }) + ]; + }, p: noop, i: noop, o: noop, - d(detaching) { - if (detaching) { - detach(div); - } - + if (detaching) detach(div); run_all(dispose); } }; } function handleTouchstart() { - // ... -} + +} // ... function handleClick() { - // ... -} + +} // ... class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, null, create_fragment, safe_not_equal, []); + init(this, options, null, create_fragment, safe_not_equal, {}); } } diff --git a/test/js/samples/head-no-whitespace/expected.js b/test/js/samples/head-no-whitespace/expected.js index 457df77dc8..444bad3fd4 100644 --- a/test/js/samples/head-no-whitespace/expected.js +++ b/test/js/samples/head-no-whitespace/expected.js @@ -11,7 +11,8 @@ import { } from "svelte/internal"; function create_fragment(ctx) { - var meta0, meta1; + let meta0; + let meta1; return { c() { @@ -22,16 +23,13 @@ function create_fragment(ctx) { attr(meta1, "name", "twitter:title"); attr(meta1, "content", "Svelte"); }, - m(target, anchor) { append(document.head, meta0); append(document.head, meta1); }, - p: noop, i: noop, o: noop, - d(detaching) { detach(meta0); detach(meta1); @@ -42,7 +40,7 @@ function create_fragment(ctx) { class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, null, create_fragment, safe_not_equal, []); + init(this, options, null, create_fragment, safe_not_equal, {}); } } diff --git a/test/js/samples/hoisted-const/expected.js b/test/js/samples/hoisted-const/expected.js index ccd0b3c480..2842b54751 100644 --- a/test/js/samples/hoisted-const/expected.js +++ b/test/js/samples/hoisted-const/expected.js @@ -1,50 +1,44 @@ /* generated by Svelte vX.Y.Z */ import { SvelteComponent, - append, detach, element, init, insert, noop, - safe_not_equal, - text + safe_not_equal } from "svelte/internal"; function create_fragment(ctx) { - var b, t_value = get_answer() + "", t; + let b; return { c() { b = element("b"); - t = text(t_value); + b.textContent = `${get_answer()}`; }, - m(target, anchor) { insert(target, b, anchor); - append(b, t); }, - p: noop, i: noop, o: noop, - d(detaching) { - if (detaching) { - detach(b); - } + if (detaching) detach(b); } }; } const ANSWER = 42; -function get_answer() { return ANSWER; } +function get_answer() { + return ANSWER; +} class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, null, create_fragment, safe_not_equal, []); + init(this, options, null, create_fragment, safe_not_equal, {}); } } diff --git a/test/js/samples/hoisted-let/expected.js b/test/js/samples/hoisted-let/expected.js index e2a9186dbd..285b124118 100644 --- a/test/js/samples/hoisted-let/expected.js +++ b/test/js/samples/hoisted-let/expected.js @@ -1,50 +1,44 @@ /* generated by Svelte vX.Y.Z */ import { SvelteComponent, - append, detach, element, init, insert, noop, - safe_not_equal, - text + safe_not_equal } from "svelte/internal"; function create_fragment(ctx) { - var b, t_value = get_answer() + "", t; + let b; return { c() { b = element("b"); - t = text(t_value); + b.textContent = `${get_answer()}`; }, - m(target, anchor) { insert(target, b, anchor); - append(b, t); }, - p: noop, i: noop, o: noop, - d(detaching) { - if (detaching) { - detach(b); - } + if (detaching) detach(b); } }; } let ANSWER = 42; -function get_answer() { return ANSWER; } +function get_answer() { + return ANSWER; +} class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, null, create_fragment, safe_not_equal, []); + init(this, options, null, create_fragment, safe_not_equal, {}); } } diff --git a/test/js/samples/hydrated-void-element/_config.js b/test/js/samples/hydrated-void-element/_config.js new file mode 100644 index 0000000000..84c0d733ef --- /dev/null +++ b/test/js/samples/hydrated-void-element/_config.js @@ -0,0 +1,5 @@ +export default { + options: { + hydratable: true + } +}; \ No newline at end of file diff --git a/test/js/samples/hydrated-void-element/expected.js b/test/js/samples/hydrated-void-element/expected.js new file mode 100644 index 0000000000..e53d16d925 --- /dev/null +++ b/test/js/samples/hydrated-void-element/expected.js @@ -0,0 +1,64 @@ +/* generated by Svelte vX.Y.Z */ +import { + SvelteComponent, + attr, + children, + claim_element, + claim_space, + detach, + element, + init, + insert, + noop, + safe_not_equal, + space +} from "svelte/internal"; + +function create_fragment(ctx) { + let img; + let img_src_value; + let t; + let div; + + return { + c() { + img = element("img"); + t = space(); + div = element("div"); + this.h(); + }, + l(nodes) { + img = claim_element(nodes, "IMG", { src: true, alt: true }); + t = claim_space(nodes); + div = claim_element(nodes, "DIV", {}); + children(div).forEach(detach); + this.h(); + }, + h() { + if (img.src !== (img_src_value = "donuts.jpg")) attr(img, "src", img_src_value); + attr(img, "alt", "donuts"); + }, + m(target, anchor) { + insert(target, img, anchor); + insert(target, t, anchor); + insert(target, div, anchor); + }, + p: noop, + i: noop, + o: noop, + d(detaching) { + if (detaching) detach(img); + if (detaching) detach(t); + if (detaching) detach(div); + } + }; +} + +class Component extends SvelteComponent { + constructor(options) { + super(); + init(this, options, null, create_fragment, safe_not_equal, {}); + } +} + +export default Component; \ No newline at end of file diff --git a/test/js/samples/hydrated-void-element/input.svelte b/test/js/samples/hydrated-void-element/input.svelte new file mode 100644 index 0000000000..d70b3eaf12 --- /dev/null +++ b/test/js/samples/hydrated-void-element/input.svelte @@ -0,0 +1,2 @@ +donuts +
\ No newline at end of file diff --git a/test/js/samples/if-block-complex/expected.js b/test/js/samples/if-block-complex/expected.js index 67d537f343..a8244de8b0 100644 --- a/test/js/samples/if-block-complex/expected.js +++ b/test/js/samples/if-block-complex/expected.js @@ -11,70 +11,56 @@ import { safe_not_equal } from "svelte/internal"; -// (7:0) {#if (item.divider && item.divider.includes(1))} function create_if_block(ctx) { - var div; + let div; return { c() { div = element("div"); attr(div, "class", "divider"); }, - m(target, anchor) { insert(target, div, anchor); }, - d(detaching) { - if (detaching) { - detach(div); - } + if (detaching) detach(div); } }; } function create_fragment(ctx) { - var show_if = (ctx.item.divider && ctx.item.divider.includes(1)), if_block_anchor; - - var if_block = (show_if) && create_if_block(ctx); + let show_if = /*item*/ ctx[0].divider && /*item*/ ctx[0].divider.includes(1); + let if_block_anchor; + let if_block = show_if && create_if_block(ctx); return { c() { if (if_block) if_block.c(); if_block_anchor = empty(); }, - m(target, anchor) { if (if_block) if_block.m(target, anchor); insert(target, if_block_anchor, anchor); }, - p: noop, i: noop, o: noop, - d(detaching) { if (if_block) if_block.d(detaching); - - if (detaching) { - detach(if_block_anchor); - } + if (detaching) detach(if_block_anchor); } }; } function instance($$self) { - let item = { - divider: [1] - } - - return { item }; + let item = { divider: [1] }; + return [item]; } class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, instance, create_fragment, safe_not_equal, []); + init(this, options, instance, create_fragment, safe_not_equal, {}); } } diff --git a/test/js/samples/if-block-no-update/expected.js b/test/js/samples/if-block-no-update/expected.js index 5cb29e8593..f225c221bf 100644 --- a/test/js/samples/if-block-no-update/expected.js +++ b/test/js/samples/if-block-no-update/expected.js @@ -10,92 +10,77 @@ import { safe_not_equal } from "svelte/internal"; -// (7:0) {:else} function create_else_block(ctx) { - var p; + let p; return { c() { p = element("p"); p.textContent = "not foo!"; }, - m(target, anchor) { insert(target, p, anchor); }, - d(detaching) { - if (detaching) { - detach(p); - } + if (detaching) detach(p); } }; } // (5:0) {#if foo} function create_if_block(ctx) { - var p; + let p; return { c() { p = element("p"); p.textContent = "foo!"; }, - m(target, anchor) { insert(target, p, anchor); }, - d(detaching) { - if (detaching) { - detach(p); - } + if (detaching) detach(p); } }; } function create_fragment(ctx) { - var if_block_anchor; + let if_block_anchor; - function select_block_type(changed, ctx) { - if (ctx.foo) return create_if_block; + function select_block_type(ctx, dirty) { + if (/*foo*/ ctx[0]) return create_if_block; return create_else_block; } - var current_block_type = select_block_type(null, ctx); - var if_block = current_block_type(ctx); + let current_block_type = select_block_type(ctx, -1); + let if_block = current_block_type(ctx); return { c() { if_block.c(); if_block_anchor = empty(); }, - m(target, anchor) { if_block.m(target, anchor); insert(target, if_block_anchor, anchor); }, - - p(changed, ctx) { - if (current_block_type !== (current_block_type = select_block_type(changed, ctx))) { + p(ctx, [dirty]) { + if (current_block_type !== (current_block_type = select_block_type(ctx, dirty))) { if_block.d(1); if_block = current_block_type(ctx); + if (if_block) { if_block.c(); if_block.m(if_block_anchor.parentNode, if_block_anchor); } } }, - i: noop, o: noop, - d(detaching) { if_block.d(detaching); - - if (detaching) { - detach(if_block_anchor); - } + if (detaching) detach(if_block_anchor); } }; } @@ -104,16 +89,16 @@ function instance($$self, $$props, $$invalidate) { let { foo } = $$props; $$self.$set = $$props => { - if ('foo' in $$props) $$invalidate('foo', foo = $$props.foo); + if ("foo" in $$props) $$invalidate(0, foo = $$props.foo); }; - return { foo }; + return [foo]; } class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, instance, create_fragment, safe_not_equal, ["foo"]); + init(this, options, instance, create_fragment, safe_not_equal, { foo: 0 }); } } diff --git a/test/js/samples/if-block-simple/expected.js b/test/js/samples/if-block-simple/expected.js index 94b0f37f31..b9fad863e2 100644 --- a/test/js/samples/if-block-simple/expected.js +++ b/test/js/samples/if-block-simple/expected.js @@ -10,66 +10,55 @@ import { safe_not_equal } from "svelte/internal"; -// (5:0) {#if foo} function create_if_block(ctx) { - var p; + let p; return { c() { p = element("p"); p.textContent = "foo!"; }, - m(target, anchor) { insert(target, p, anchor); }, - d(detaching) { - if (detaching) { - detach(p); - } + if (detaching) detach(p); } }; } function create_fragment(ctx) { - var if_block_anchor; - - var if_block = (ctx.foo) && create_if_block(ctx); + let if_block_anchor; + let if_block = /*foo*/ ctx[0] && create_if_block(ctx); return { c() { if (if_block) if_block.c(); if_block_anchor = empty(); }, - m(target, anchor) { if (if_block) if_block.m(target, anchor); insert(target, if_block_anchor, anchor); }, - - p(changed, ctx) { - if (ctx.foo) { + p(ctx, [dirty]) { + if (/*foo*/ ctx[0]) { if (!if_block) { if_block = create_if_block(ctx); if_block.c(); if_block.m(if_block_anchor.parentNode, if_block_anchor); + } else { + } } else if (if_block) { if_block.d(1); if_block = null; } }, - i: noop, o: noop, - d(detaching) { if (if_block) if_block.d(detaching); - - if (detaching) { - detach(if_block_anchor); - } + if (detaching) detach(if_block_anchor); } }; } @@ -78,16 +67,16 @@ function instance($$self, $$props, $$invalidate) { let { foo } = $$props; $$self.$set = $$props => { - if ('foo' in $$props) $$invalidate('foo', foo = $$props.foo); + if ("foo" in $$props) $$invalidate(0, foo = $$props.foo); }; - return { foo }; + return [foo]; } class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, instance, create_fragment, safe_not_equal, ["foo"]); + init(this, options, instance, create_fragment, safe_not_equal, { foo: 0 }); } } diff --git a/test/js/samples/inline-style-optimized-multiple/expected.js b/test/js/samples/inline-style-optimized-multiple/expected.js index ea1d90e831..84a38abd7b 100644 --- a/test/js/samples/inline-style-optimized-multiple/expected.js +++ b/test/js/samples/inline-style-optimized-multiple/expected.js @@ -11,56 +11,52 @@ import { } from "svelte/internal"; function create_fragment(ctx) { - var div; + let div; return { c() { div = element("div"); - set_style(div, "color", ctx.color); - set_style(div, "transform", "translate(" + ctx.x + "px," + ctx.y + "px)"); + set_style(div, "color", /*color*/ ctx[0]); + set_style(div, "transform", "translate(" + /*x*/ ctx[1] + "px," + /*y*/ ctx[2] + "px)"); }, - m(target, anchor) { insert(target, div, anchor); }, - - p(changed, ctx) { - if (changed.color) { - set_style(div, "color", ctx.color); + p(ctx, [dirty]) { + if (dirty & /*color*/ 1) { + set_style(div, "color", /*color*/ ctx[0]); } - if (changed.x || changed.y) { - set_style(div, "transform", "translate(" + ctx.x + "px," + ctx.y + "px)"); + if (dirty & /*x, y*/ 6) { + set_style(div, "transform", "translate(" + /*x*/ ctx[1] + "px," + /*y*/ ctx[2] + "px)"); } }, - i: noop, o: noop, - d(detaching) { - if (detaching) { - detach(div); - } + if (detaching) detach(div); } }; } function instance($$self, $$props, $$invalidate) { - let { color, x, y } = $$props; + let { color } = $$props; + let { x } = $$props; + let { y } = $$props; $$self.$set = $$props => { - if ('color' in $$props) $$invalidate('color', color = $$props.color); - if ('x' in $$props) $$invalidate('x', x = $$props.x); - if ('y' in $$props) $$invalidate('y', y = $$props.y); + if ("color" in $$props) $$invalidate(0, color = $$props.color); + if ("x" in $$props) $$invalidate(1, x = $$props.x); + if ("y" in $$props) $$invalidate(2, y = $$props.y); }; - return { color, x, y }; + return [color, x, y]; } class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, instance, create_fragment, safe_not_equal, ["color", "x", "y"]); + init(this, options, instance, create_fragment, safe_not_equal, { color: 0, x: 1, y: 2 }); } } diff --git a/test/js/samples/inline-style-optimized-url/expected.js b/test/js/samples/inline-style-optimized-url/expected.js index 8dfc48447d..77870348a5 100644 --- a/test/js/samples/inline-style-optimized-url/expected.js +++ b/test/js/samples/inline-style-optimized-url/expected.js @@ -11,31 +11,25 @@ import { } from "svelte/internal"; function create_fragment(ctx) { - var div; + let div; return { c() { div = element("div"); - set_style(div, "background", "url(data:image/png;base64," + ctx.data + ")"); + set_style(div, "background", "url(data:image/png;base64," + /*data*/ ctx[0] + ")"); }, - m(target, anchor) { insert(target, div, anchor); }, - - p(changed, ctx) { - if (changed.data) { - set_style(div, "background", "url(data:image/png;base64," + ctx.data + ")"); + p(ctx, [dirty]) { + if (dirty & /*data*/ 1) { + set_style(div, "background", "url(data:image/png;base64," + /*data*/ ctx[0] + ")"); } }, - i: noop, o: noop, - d(detaching) { - if (detaching) { - detach(div); - } + if (detaching) detach(div); } }; } @@ -44,16 +38,16 @@ function instance($$self, $$props, $$invalidate) { let { data } = $$props; $$self.$set = $$props => { - if ('data' in $$props) $$invalidate('data', data = $$props.data); + if ("data" in $$props) $$invalidate(0, data = $$props.data); }; - return { data }; + return [data]; } class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, instance, create_fragment, safe_not_equal, ["data"]); + init(this, options, instance, create_fragment, safe_not_equal, { data: 0 }); } } diff --git a/test/js/samples/inline-style-optimized/expected.js b/test/js/samples/inline-style-optimized/expected.js index 1170c25458..5bef284f09 100644 --- a/test/js/samples/inline-style-optimized/expected.js +++ b/test/js/samples/inline-style-optimized/expected.js @@ -11,31 +11,25 @@ import { } from "svelte/internal"; function create_fragment(ctx) { - var div; + let div; return { c() { div = element("div"); - set_style(div, "color", ctx.color); + set_style(div, "color", /*color*/ ctx[0]); }, - m(target, anchor) { insert(target, div, anchor); }, - - p(changed, ctx) { - if (changed.color) { - set_style(div, "color", ctx.color); + p(ctx, [dirty]) { + if (dirty & /*color*/ 1) { + set_style(div, "color", /*color*/ ctx[0]); } }, - i: noop, o: noop, - d(detaching) { - if (detaching) { - detach(div); - } + if (detaching) detach(div); } }; } @@ -44,16 +38,16 @@ function instance($$self, $$props, $$invalidate) { let { color } = $$props; $$self.$set = $$props => { - if ('color' in $$props) $$invalidate('color', color = $$props.color); + if ("color" in $$props) $$invalidate(0, color = $$props.color); }; - return { color }; + return [color]; } class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, instance, create_fragment, safe_not_equal, ["color"]); + init(this, options, instance, create_fragment, safe_not_equal, { color: 0 }); } } diff --git a/test/js/samples/inline-style-unoptimized/expected.js b/test/js/samples/inline-style-unoptimized/expected.js index 9349ade12c..fdff685ead 100644 --- a/test/js/samples/inline-style-unoptimized/expected.js +++ b/test/js/samples/inline-style-unoptimized/expected.js @@ -12,62 +12,61 @@ import { } from "svelte/internal"; function create_fragment(ctx) { - var div0, t, div1, div1_style_value; + let div0; + let t; + let div1; + let div1_style_value; return { c() { div0 = element("div"); t = space(); div1 = element("div"); - attr(div0, "style", ctx.style); - attr(div1, "style", div1_style_value = "" + ctx.key + ": " + ctx.value); + attr(div0, "style", /*style*/ ctx[0]); + attr(div1, "style", div1_style_value = "" + (/*key*/ ctx[1] + ": " + /*value*/ ctx[2])); }, - m(target, anchor) { insert(target, div0, anchor); insert(target, t, anchor); insert(target, div1, anchor); }, - - p(changed, ctx) { - if (changed.style) { - attr(div0, "style", ctx.style); + p(ctx, [dirty]) { + if (dirty & /*style*/ 1) { + attr(div0, "style", /*style*/ ctx[0]); } - if ((changed.key || changed.value) && div1_style_value !== (div1_style_value = "" + ctx.key + ": " + ctx.value)) { + if (dirty & /*key, value*/ 6 && div1_style_value !== (div1_style_value = "" + (/*key*/ ctx[1] + ": " + /*value*/ ctx[2]))) { attr(div1, "style", div1_style_value); } }, - i: noop, o: noop, - d(detaching) { - if (detaching) { - detach(div0); - detach(t); - detach(div1); - } + if (detaching) detach(div0); + if (detaching) detach(t); + if (detaching) detach(div1); } }; } function instance($$self, $$props, $$invalidate) { - let { style, key, value } = $$props; + let { style } = $$props; + let { key } = $$props; + let { value } = $$props; $$self.$set = $$props => { - if ('style' in $$props) $$invalidate('style', style = $$props.style); - if ('key' in $$props) $$invalidate('key', key = $$props.key); - if ('value' in $$props) $$invalidate('value', value = $$props.value); + if ("style" in $$props) $$invalidate(0, style = $$props.style); + if ("key" in $$props) $$invalidate(1, key = $$props.key); + if ("value" in $$props) $$invalidate(2, value = $$props.value); }; - return { style, key, value }; + return [style, key, value]; } class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, instance, create_fragment, safe_not_equal, ["style", "key", "value"]); + init(this, options, instance, create_fragment, safe_not_equal, { style: 0, key: 1, value: 2 }); } } diff --git a/test/js/samples/inline-style-without-updates/expected.js b/test/js/samples/inline-style-without-updates/expected.js index 73995c4755..375896f259 100644 --- a/test/js/samples/inline-style-without-updates/expected.js +++ b/test/js/samples/inline-style-without-updates/expected.js @@ -11,36 +11,31 @@ import { } from "svelte/internal"; function create_fragment(ctx) { - var div; + let div; return { c() { div = element("div"); set_style(div, "color", color); }, - m(target, anchor) { insert(target, div, anchor); }, - p: noop, i: noop, o: noop, - d(detaching) { - if (detaching) { - detach(div); - } + if (detaching) detach(div); } }; } -let color = 'red'; +let color = "red"; class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, null, create_fragment, safe_not_equal, []); + init(this, options, null, create_fragment, safe_not_equal, {}); } } diff --git a/test/js/samples/input-files/expected.js b/test/js/samples/input-files/expected.js index d4442d57ee..2a2254fbd7 100644 --- a/test/js/samples/input-files/expected.js +++ b/test/js/samples/input-files/expected.js @@ -12,29 +12,24 @@ import { } from "svelte/internal"; function create_fragment(ctx) { - var input, dispose; + let input; + let dispose; return { c() { input = element("input"); attr(input, "type", "file"); input.multiple = true; - dispose = listen(input, "change", ctx.input_change_handler); }, - m(target, anchor) { insert(target, input, anchor); + dispose = listen(input, "change", /*input_change_handler*/ ctx[1]); }, - p: noop, i: noop, o: noop, - d(detaching) { - if (detaching) { - detach(input); - } - + if (detaching) detach(input); dispose(); } }; @@ -45,20 +40,20 @@ function instance($$self, $$props, $$invalidate) { function input_change_handler() { files = this.files; - $$invalidate('files', files); + $$invalidate(0, files); } $$self.$set = $$props => { - if ('files' in $$props) $$invalidate('files', files = $$props.files); + if ("files" in $$props) $$invalidate(0, files = $$props.files); }; - return { files, input_change_handler }; + return [files, input_change_handler]; } class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, instance, create_fragment, safe_not_equal, ["files"]); + init(this, options, instance, create_fragment, safe_not_equal, { files: 0 }); } } diff --git a/test/js/samples/input-no-initial-value/expected.js b/test/js/samples/input-no-initial-value/expected.js index a651d72059..d588f0bf73 100644 --- a/test/js/samples/input-no-initial-value/expected.js +++ b/test/js/samples/input-no-initial-value/expected.js @@ -16,46 +16,43 @@ import { } from "svelte/internal"; function create_fragment(ctx) { - var form, input, t, button, dispose; + let form; + let input; + let t0; + let button; + let dispose; return { c() { form = element("form"); input = element("input"); - t = space(); + t0 = space(); button = element("button"); button.textContent = "Store"; attr(input, "type", "text"); input.required = true; - - dispose = [ - listen(input, "input", ctx.input_input_handler), - listen(form, "submit", ctx.handleSubmit) - ]; }, - m(target, anchor) { insert(target, form, anchor); append(form, input); - - set_input_value(input, ctx.test); - - append(form, t); + set_input_value(input, /*test*/ ctx[0]); + append(form, t0); append(form, button); - }, - p(changed, ctx) { - if (changed.test && (input.value !== ctx.test)) set_input_value(input, ctx.test); + dispose = [ + listen(input, "input", /*input_input_handler*/ ctx[2]), + listen(form, "submit", /*handleSubmit*/ ctx[1]) + ]; + }, + p(ctx, [dirty]) { + if (dirty & /*test*/ 1 && input.value !== /*test*/ ctx[0]) { + set_input_value(input, /*test*/ ctx[0]); + } }, - i: noop, o: noop, - d(detaching) { - if (detaching) { - detach(form); - } - + if (detaching) detach(form); run_all(dispose); } }; @@ -66,21 +63,21 @@ function instance($$self, $$props, $$invalidate) { function handleSubmit(event) { event.preventDefault(); - console.log('value', test); + console.log("value", test); } function input_input_handler() { test = this.value; - $$invalidate('test', test); + $$invalidate(0, test); } - return { test, handleSubmit, input_input_handler }; + return [test, handleSubmit, input_input_handler]; } class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, instance, create_fragment, safe_not_equal, []); + init(this, options, instance, create_fragment, safe_not_equal, {}); } } diff --git a/test/js/samples/input-range/expected.js b/test/js/samples/input-range/expected.js index 04552d20cd..12dfd3e90e 100644 --- a/test/js/samples/input-range/expected.js +++ b/test/js/samples/input-range/expected.js @@ -15,37 +15,32 @@ import { } from "svelte/internal"; function create_fragment(ctx) { - var input, dispose; + let input; + let dispose; return { c() { input = element("input"); attr(input, "type", "range"); - - dispose = [ - listen(input, "change", ctx.input_change_input_handler), - listen(input, "input", ctx.input_change_input_handler) - ]; }, - m(target, anchor) { insert(target, input, anchor); + set_input_value(input, /*value*/ ctx[0]); - set_input_value(input, ctx.value); + dispose = [ + listen(input, "change", /*input_change_input_handler*/ ctx[1]), + listen(input, "input", /*input_change_input_handler*/ ctx[1]) + ]; }, - - p(changed, ctx) { - if (changed.value) set_input_value(input, ctx.value); + p(ctx, [dirty]) { + if (dirty & /*value*/ 1) { + set_input_value(input, /*value*/ ctx[0]); + } }, - i: noop, o: noop, - d(detaching) { - if (detaching) { - detach(input); - } - + if (detaching) detach(input); run_all(dispose); } }; @@ -56,20 +51,20 @@ function instance($$self, $$props, $$invalidate) { function input_change_input_handler() { value = to_number(this.value); - $$invalidate('value', value); + $$invalidate(0, value); } $$self.$set = $$props => { - if ('value' in $$props) $$invalidate('value', value = $$props.value); + if ("value" in $$props) $$invalidate(0, value = $$props.value); }; - return { value, input_change_input_handler }; + return [value, input_change_input_handler]; } class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, instance, create_fragment, safe_not_equal, ["value"]); + init(this, options, instance, create_fragment, safe_not_equal, { value: 0 }); } } diff --git a/test/js/samples/input-value/expected.js b/test/js/samples/input-value/expected.js new file mode 100644 index 0000000000..21c7bfc83b --- /dev/null +++ b/test/js/samples/input-value/expected.js @@ -0,0 +1,77 @@ +/* generated by Svelte vX.Y.Z */ +import { + SvelteComponent, + append, + detach, + element, + init, + insert, + listen, + noop, + safe_not_equal, + set_data, + space, + text +} from "svelte/internal"; + +function create_fragment(ctx) { + let input; + let t0; + let h1; + let t1; + let t2; + let dispose; + + return { + c() { + input = element("input"); + t0 = space(); + h1 = element("h1"); + t1 = text(/*name*/ ctx[0]); + t2 = text("!"); + input.value = /*name*/ ctx[0]; + }, + m(target, anchor) { + insert(target, input, anchor); + insert(target, t0, anchor); + insert(target, h1, anchor); + append(h1, t1); + append(h1, t2); + dispose = listen(input, "input", /*onInput*/ ctx[1]); + }, + p(ctx, [dirty]) { + if (dirty & /*name*/ 1 && input.value !== /*name*/ ctx[0]) { + input.value = /*name*/ ctx[0]; + } + + if (dirty & /*name*/ 1) set_data(t1, /*name*/ ctx[0]); + }, + i: noop, + o: noop, + d(detaching) { + if (detaching) detach(input); + if (detaching) detach(t0); + if (detaching) detach(h1); + dispose(); + } + }; +} + +function instance($$self, $$props, $$invalidate) { + let name = "change me"; + + function onInput(event) { + $$invalidate(0, name = event.target.value); + } + + return [name, onInput]; +} + +class Component extends SvelteComponent { + constructor(options) { + super(); + init(this, options, instance, create_fragment, safe_not_equal, {}); + } +} + +export default Component; \ No newline at end of file diff --git a/test/js/samples/input-value/input.svelte b/test/js/samples/input-value/input.svelte new file mode 100644 index 0000000000..476458a195 --- /dev/null +++ b/test/js/samples/input-value/input.svelte @@ -0,0 +1,11 @@ + + + + +

{name}!

\ No newline at end of file diff --git a/test/js/samples/input-without-blowback-guard/expected.js b/test/js/samples/input-without-blowback-guard/expected.js index d97326fcea..fefe867e14 100644 --- a/test/js/samples/input-without-blowback-guard/expected.js +++ b/test/js/samples/input-without-blowback-guard/expected.js @@ -12,33 +12,28 @@ import { } from "svelte/internal"; function create_fragment(ctx) { - var input, dispose; + let input; + let dispose; return { c() { input = element("input"); attr(input, "type", "checkbox"); - dispose = listen(input, "change", ctx.input_change_handler); }, - m(target, anchor) { insert(target, input, anchor); - - input.checked = ctx.foo; + input.checked = /*foo*/ ctx[0]; + dispose = listen(input, "change", /*input_change_handler*/ ctx[1]); }, - - p(changed, ctx) { - if (changed.foo) input.checked = ctx.foo; + p(ctx, [dirty]) { + if (dirty & /*foo*/ 1) { + input.checked = /*foo*/ ctx[0]; + } }, - i: noop, o: noop, - d(detaching) { - if (detaching) { - detach(input); - } - + if (detaching) detach(input); dispose(); } }; @@ -49,20 +44,20 @@ function instance($$self, $$props, $$invalidate) { function input_change_handler() { foo = this.checked; - $$invalidate('foo', foo); + $$invalidate(0, foo); } $$self.$set = $$props => { - if ('foo' in $$props) $$invalidate('foo', foo = $$props.foo); + if ("foo" in $$props) $$invalidate(0, foo = $$props.foo); }; - return { foo, input_change_handler }; + return [foo, input_change_handler]; } class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, instance, create_fragment, safe_not_equal, ["foo"]); + init(this, options, instance, create_fragment, safe_not_equal, { foo: 0 }); } } diff --git a/test/js/samples/instrumentation-script-if-no-block/expected.js b/test/js/samples/instrumentation-script-if-no-block/expected.js index ce5948de73..7634481a2d 100644 --- a/test/js/samples/instrumentation-script-if-no-block/expected.js +++ b/test/js/samples/instrumentation-script-if-no-block/expected.js @@ -15,7 +15,12 @@ import { } from "svelte/internal"; function create_fragment(ctx) { - var button, t1, p, t2, t3, dispose; + let button; + let t1; + let p; + let t2; + let t3; + let dispose; return { c() { @@ -24,34 +29,25 @@ function create_fragment(ctx) { t1 = space(); p = element("p"); t2 = text("x: "); - t3 = text(ctx.x); - dispose = listen(button, "click", ctx.foo); + t3 = text(/*x*/ ctx[0]); }, - m(target, anchor) { insert(target, button, anchor); insert(target, t1, anchor); insert(target, p, anchor); append(p, t2); append(p, t3); + dispose = listen(button, "click", /*foo*/ ctx[1]); }, - - p(changed, ctx) { - if (changed.x) { - set_data(t3, ctx.x); - } + p(ctx, [dirty]) { + if (dirty & /*x*/ 1) set_data(t3, /*x*/ ctx[0]); }, - i: noop, o: noop, - d(detaching) { - if (detaching) { - detach(button); - detach(t1); - detach(p); - } - + if (detaching) detach(button); + if (detaching) detach(t1); + if (detaching) detach(p); dispose(); } }; @@ -61,16 +57,16 @@ function instance($$self, $$props, $$invalidate) { let x = 0; function foo() { - if (true) $$invalidate('x', x += 1); + if (true) $$invalidate(0, x += 1); } - return { x, foo }; + return [x, foo]; } class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, instance, create_fragment, safe_not_equal, []); + init(this, options, instance, create_fragment, safe_not_equal, {}); } } diff --git a/test/js/samples/instrumentation-script-main-block/expected.js b/test/js/samples/instrumentation-script-main-block/expected.js new file mode 100644 index 0000000000..bc80924602 --- /dev/null +++ b/test/js/samples/instrumentation-script-main-block/expected.js @@ -0,0 +1,75 @@ +/* generated by Svelte vX.Y.Z */ +import { + SvelteComponent, + append, + detach, + element, + init, + insert, + noop, + safe_not_equal, + set_data, + text +} from "svelte/internal"; + +function create_fragment(ctx) { + let p; + let t0; + let t1; + + return { + c() { + p = element("p"); + t0 = text("x: "); + t1 = text(/*x*/ ctx[0]); + }, + m(target, anchor) { + insert(target, p, anchor); + append(p, t0); + append(p, t1); + }, + p(ctx, [dirty]) { + if (dirty & /*x*/ 1) set_data(t1, /*x*/ ctx[0]); + }, + i: noop, + o: noop, + d(detaching) { + if (detaching) detach(p); + } + }; +} + +function instance($$self, $$props, $$invalidate) { + let x = 0; + let y = 1; + x += 1; + + { + x += 2; + } + + setTimeout( + function foo() { + $$invalidate(0, x += 10); + $$invalidate(1, y += 20); + }, + 1000 + ); + + $$self.$$.update = () => { + if ($$self.$$.dirty & /*x, y*/ 3) { + $: $$invalidate(0, x += y); + } + }; + + return [x]; +} + +class Component extends SvelteComponent { + constructor(options) { + super(); + init(this, options, instance, create_fragment, safe_not_equal, {}); + } +} + +export default Component; \ No newline at end of file diff --git a/test/js/samples/instrumentation-script-main-block/input.svelte b/test/js/samples/instrumentation-script-main-block/input.svelte new file mode 100644 index 0000000000..8c01783710 --- /dev/null +++ b/test/js/samples/instrumentation-script-main-block/input.svelte @@ -0,0 +1,19 @@ + + +

x: {x}

diff --git a/test/js/samples/instrumentation-script-x-equals-x/expected.js b/test/js/samples/instrumentation-script-x-equals-x/expected.js index 0d7740b55d..c154608cd5 100644 --- a/test/js/samples/instrumentation-script-x-equals-x/expected.js +++ b/test/js/samples/instrumentation-script-x-equals-x/expected.js @@ -15,7 +15,13 @@ import { } from "svelte/internal"; function create_fragment(ctx) { - var button, t1, p, t2, t3_value = ctx.things.length + "", t3, dispose; + let button; + let t1; + let p; + let t2; + let t3_value = /*things*/ ctx[0].length + ""; + let t3; + let dispose; return { c() { @@ -25,33 +31,24 @@ function create_fragment(ctx) { p = element("p"); t2 = text("number of things: "); t3 = text(t3_value); - dispose = listen(button, "click", ctx.foo); }, - m(target, anchor) { insert(target, button, anchor); insert(target, t1, anchor); insert(target, p, anchor); append(p, t2); append(p, t3); + dispose = listen(button, "click", /*foo*/ ctx[1]); }, - - p(changed, ctx) { - if ((changed.things) && t3_value !== (t3_value = ctx.things.length + "")) { - set_data(t3, t3_value); - } + p(ctx, [dirty]) { + if (dirty & /*things*/ 1 && t3_value !== (t3_value = /*things*/ ctx[0].length + "")) set_data(t3, t3_value); }, - i: noop, o: noop, - d(detaching) { - if (detaching) { - detach(button); - detach(t1); - detach(p); - } - + if (detaching) detach(button); + if (detaching) detach(t1); + if (detaching) detach(p); dispose(); } }; @@ -62,16 +59,16 @@ function instance($$self, $$props, $$invalidate) { function foo() { things.push(1); - $$invalidate('things', things); + $$invalidate(0, things); } - return { things, foo }; + return [things, foo]; } class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, instance, create_fragment, safe_not_equal, []); + init(this, options, instance, create_fragment, safe_not_equal, {}); } } diff --git a/test/js/samples/instrumentation-template-if-no-block/expected.js b/test/js/samples/instrumentation-template-if-no-block/expected.js index 4591d8c797..77780baa99 100644 --- a/test/js/samples/instrumentation-template-if-no-block/expected.js +++ b/test/js/samples/instrumentation-template-if-no-block/expected.js @@ -15,7 +15,12 @@ import { } from "svelte/internal"; function create_fragment(ctx) { - var button, t1, p, t2, t3, dispose; + let button; + let t1; + let p; + let t2; + let t3; + let dispose; return { c() { @@ -24,34 +29,25 @@ function create_fragment(ctx) { t1 = space(); p = element("p"); t2 = text("x: "); - t3 = text(ctx.x); - dispose = listen(button, "click", ctx.click_handler); + t3 = text(/*x*/ ctx[0]); }, - m(target, anchor) { insert(target, button, anchor); insert(target, t1, anchor); insert(target, p, anchor); append(p, t2); append(p, t3); + dispose = listen(button, "click", /*click_handler*/ ctx[1]); }, - - p(changed, ctx) { - if (changed.x) { - set_data(t3, ctx.x); - } + p(ctx, [dirty]) { + if (dirty & /*x*/ 1) set_data(t3, /*x*/ ctx[0]); }, - i: noop, o: noop, - d(detaching) { - if (detaching) { - detach(button); - detach(t1); - detach(p); - } - + if (detaching) detach(button); + if (detaching) detach(t1); + if (detaching) detach(p); dispose(); } }; @@ -61,16 +57,16 @@ function instance($$self, $$props, $$invalidate) { let x = 0; const click_handler = () => { - if (true) $$invalidate('x', x += 1); + if (true) $$invalidate(0, x += 1); }; - return { x, click_handler }; + return [x, click_handler]; } class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, instance, create_fragment, safe_not_equal, []); + init(this, options, instance, create_fragment, safe_not_equal, {}); } } diff --git a/test/js/samples/instrumentation-template-x-equals-x/expected.js b/test/js/samples/instrumentation-template-x-equals-x/expected.js index b08130016b..4fe45616c7 100644 --- a/test/js/samples/instrumentation-template-x-equals-x/expected.js +++ b/test/js/samples/instrumentation-template-x-equals-x/expected.js @@ -15,7 +15,13 @@ import { } from "svelte/internal"; function create_fragment(ctx) { - var button, t1, p, t2, t3_value = ctx.things.length + "", t3, dispose; + let button; + let t1; + let p; + let t2; + let t3_value = /*things*/ ctx[0].length + ""; + let t3; + let dispose; return { c() { @@ -25,33 +31,24 @@ function create_fragment(ctx) { p = element("p"); t2 = text("number of things: "); t3 = text(t3_value); - dispose = listen(button, "click", ctx.click_handler); }, - m(target, anchor) { insert(target, button, anchor); insert(target, t1, anchor); insert(target, p, anchor); append(p, t2); append(p, t3); + dispose = listen(button, "click", /*click_handler*/ ctx[1]); }, - - p(changed, ctx) { - if ((changed.things) && t3_value !== (t3_value = ctx.things.length + "")) { - set_data(t3, t3_value); - } + p(ctx, [dirty]) { + if (dirty & /*things*/ 1 && t3_value !== (t3_value = /*things*/ ctx[0].length + "")) set_data(t3, t3_value); }, - i: noop, o: noop, - d(detaching) { - if (detaching) { - detach(button); - detach(t1); - detach(p); - } - + if (detaching) detach(button); + if (detaching) detach(t1); + if (detaching) detach(p); dispose(); } }; @@ -60,15 +57,18 @@ function create_fragment(ctx) { function instance($$self, $$props, $$invalidate) { let things = []; - const click_handler = () => { things.push(1); $$invalidate('things', things) }; + const click_handler = () => { + things.push(1); + $$invalidate(0, things); + }; - return { things, click_handler }; + return [things, click_handler]; } class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, instance, create_fragment, safe_not_equal, []); + init(this, options, instance, create_fragment, safe_not_equal, {}); } } diff --git a/test/js/samples/legacy-input-type/expected.js b/test/js/samples/legacy-input-type/expected.js index 4c77259a64..2b76a48522 100644 --- a/test/js/samples/legacy-input-type/expected.js +++ b/test/js/samples/legacy-input-type/expected.js @@ -11,26 +11,21 @@ import { } from "svelte/internal"; function create_fragment(ctx) { - var input; + let input; return { c() { input = element("input"); set_input_type(input, "search"); }, - m(target, anchor) { insert(target, input, anchor); }, - p: noop, i: noop, o: noop, - d(detaching) { - if (detaching) { - detach(input); - } + if (detaching) detach(input); } }; } @@ -38,7 +33,7 @@ function create_fragment(ctx) { class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, null, create_fragment, safe_not_equal, []); + init(this, options, null, create_fragment, safe_not_equal, {}); } } diff --git a/test/js/samples/loop-protect/_config.js b/test/js/samples/loop-protect/_config.js new file mode 100644 index 0000000000..fcbf8be09b --- /dev/null +++ b/test/js/samples/loop-protect/_config.js @@ -0,0 +1,6 @@ +export default { + options: { + dev: true, + loopGuardTimeout: 100, + }, +}; diff --git a/test/js/samples/loop-protect/expected.js b/test/js/samples/loop-protect/expected.js new file mode 100644 index 0000000000..4eccaae7cb --- /dev/null +++ b/test/js/samples/loop-protect/expected.js @@ -0,0 +1,156 @@ +/* generated by Svelte vX.Y.Z */ +import { + SvelteComponentDev, + add_location, + binding_callbacks, + detach_dev, + dispatch_dev, + element, + init, + insert_dev, + loop_guard, + noop, + safe_not_equal +} from "svelte/internal"; + +const file = undefined; + +function create_fragment(ctx) { + let div; + + const block = { + c: function create() { + div = element("div"); + add_location(div, file, 22, 0, 288); + }, + l: function claim(nodes) { + throw new Error("options.hydrate only works if the component was compiled with the `hydratable: true` option"); + }, + m: function mount(target, anchor) { + insert_dev(target, div, anchor); + /*div_binding*/ ctx[1](div); + }, + p: noop, + i: noop, + o: noop, + d: function destroy(detaching) { + if (detaching) detach_dev(div); + /*div_binding*/ ctx[1](null); + } + }; + + dispatch_dev("SvelteRegisterBlock", { + block, + id: create_fragment.name, + type: "component", + source: "", + ctx + }); + + return block; +} + +function foo() { + const guard = "foo"; + + { + const guard_1 = loop_guard(100); + + while (true) { + console.log(guard); + guard_1(); + } + } +} + +function instance($$self, $$props, $$invalidate) { + let node; + + { + const guard = loop_guard(100); + + while (true) { + foo(); + guard(); + } + } + + { + const guard_2 = loop_guard(100); + + for (; ; ) { + foo(); + guard_2(); + } + } + + { + const guard_3 = loop_guard(100); + + while (true) { + foo(); + guard_3(); + } + } + + { + const guard_5 = loop_guard(100); + + do { + foo(); + guard_5(); + } while (true); + } + + function div_binding($$value) { + binding_callbacks[$$value ? "unshift" : "push"](() => { + $$invalidate(0, node = $$value); + }); + } + + $$self.$capture_state = () => ({ node, foo }); + + $$self.$inject_state = $$props => { + if ("node" in $$props) $$invalidate(0, node = $$props.node); + }; + + if ($$props && "$$inject" in $$props) { + $$self.$inject_state($$props.$$inject); + } + + $: { + const guard_4 = loop_guard(100); + + while (true) { + foo(); + guard_4(); + } + } + + $: { + const guard_6 = loop_guard(100); + + do { + foo(); + guard_6(); + } while (true); + } + + return [node, div_binding]; +} + +class Component extends SvelteComponentDev { + constructor(options) { + super(options); + init(this, options, instance, create_fragment, safe_not_equal, {}); + + dispatch_dev("SvelteRegisterComponent", { + component: this, + tagName: "Component", + options, + id: create_fragment.name + }); + } +} + +export default Component; diff --git a/test/js/samples/loop-protect/input.svelte b/test/js/samples/loop-protect/input.svelte new file mode 100644 index 0000000000..daac6ab1c4 --- /dev/null +++ b/test/js/samples/loop-protect/input.svelte @@ -0,0 +1,23 @@ + + +
\ No newline at end of file diff --git a/test/js/samples/media-bindings/expected.js b/test/js/samples/media-bindings/expected.js index b67bc31ed3..52fef36792 100644 --- a/test/js/samples/media-bindings/expected.js +++ b/test/js/samples/media-bindings/expected.js @@ -15,120 +15,163 @@ import { } from "svelte/internal"; function create_fragment(ctx) { - var audio, audio_updating = false, audio_animationframe, audio_is_paused = true, dispose; + let audio; + let audio_updating = false; + let audio_animationframe; + let audio_is_paused = true; + let dispose; function audio_timeupdate_handler() { cancelAnimationFrame(audio_animationframe); + if (!audio.paused) { audio_animationframe = raf(audio_timeupdate_handler); audio_updating = true; } - ctx.audio_timeupdate_handler.call(audio); + + /*audio_timeupdate_handler*/ ctx[12].call(audio); } return { c() { audio = element("audio"); - if (ctx.played === void 0 || ctx.currentTime === void 0) add_render_callback(audio_timeupdate_handler); - if (ctx.duration === void 0) add_render_callback(() => ctx.audio_durationchange_handler.call(audio)); - if (ctx.buffered === void 0) add_render_callback(() => ctx.audio_progress_handler.call(audio)); - if (ctx.buffered === void 0 || ctx.seekable === void 0) add_render_callback(() => ctx.audio_loadedmetadata_handler.call(audio)); + if (/*buffered*/ ctx[0] === void 0) add_render_callback(() => /*audio_progress_handler*/ ctx[10].call(audio)); + if (/*buffered*/ ctx[0] === void 0 || /*seekable*/ ctx[1] === void 0) add_render_callback(() => /*audio_loadedmetadata_handler*/ ctx[11].call(audio)); + if (/*played*/ ctx[2] === void 0 || /*currentTime*/ ctx[3] === void 0 || /*ended*/ ctx[9] === void 0) add_render_callback(audio_timeupdate_handler); + if (/*duration*/ ctx[4] === void 0) add_render_callback(() => /*audio_durationchange_handler*/ ctx[13].call(audio)); + if (/*seeking*/ ctx[8] === void 0) add_render_callback(() => /*audio_seeking_seeked_handler*/ ctx[17].call(audio)); + if (/*ended*/ ctx[9] === void 0) add_render_callback(() => /*audio_ended_handler*/ ctx[18].call(audio)); + }, + m(target, anchor) { + insert(target, audio, anchor); + + if (!isNaN(/*volume*/ ctx[6])) { + audio.volume = /*volume*/ ctx[6]; + } + + if (!isNaN(/*playbackRate*/ ctx[7])) { + audio.playbackRate = /*playbackRate*/ ctx[7]; + } dispose = [ + listen(audio, "progress", /*audio_progress_handler*/ ctx[10]), + listen(audio, "loadedmetadata", /*audio_loadedmetadata_handler*/ ctx[11]), listen(audio, "timeupdate", audio_timeupdate_handler), - listen(audio, "durationchange", ctx.audio_durationchange_handler), - listen(audio, "play", ctx.audio_play_pause_handler), - listen(audio, "pause", ctx.audio_play_pause_handler), - listen(audio, "progress", ctx.audio_progress_handler), - listen(audio, "loadedmetadata", ctx.audio_loadedmetadata_handler), - listen(audio, "volumechange", ctx.audio_volumechange_handler), - listen(audio, "ratechange", ctx.audio_ratechange_handler) + listen(audio, "durationchange", /*audio_durationchange_handler*/ ctx[13]), + listen(audio, "play", /*audio_play_pause_handler*/ ctx[14]), + listen(audio, "pause", /*audio_play_pause_handler*/ ctx[14]), + listen(audio, "volumechange", /*audio_volumechange_handler*/ ctx[15]), + listen(audio, "ratechange", /*audio_ratechange_handler*/ ctx[16]), + listen(audio, "seeking", /*audio_seeking_seeked_handler*/ ctx[17]), + listen(audio, "seeked", /*audio_seeking_seeked_handler*/ ctx[17]), + listen(audio, "ended", /*audio_ended_handler*/ ctx[18]) ]; }, + p(ctx, [dirty]) { + if (!audio_updating && dirty & /*currentTime*/ 8 && !isNaN(/*currentTime*/ ctx[3])) { + audio.currentTime = /*currentTime*/ ctx[3]; + } - m(target, anchor) { - insert(target, audio, anchor); + audio_updating = false; - audio.volume = ctx.volume; + if (dirty & /*paused*/ 32 && audio_is_paused !== (audio_is_paused = /*paused*/ ctx[5])) { + audio[audio_is_paused ? "pause" : "play"](); + } - audio.playbackRate = ctx.playbackRate; - }, + if (dirty & /*volume*/ 64 && !isNaN(/*volume*/ ctx[6])) { + audio.volume = /*volume*/ ctx[6]; + } - p(changed, ctx) { - if (!audio_updating && changed.currentTime && !isNaN(ctx.currentTime)) audio.currentTime = ctx.currentTime; - if (changed.paused && audio_is_paused !== (audio_is_paused = ctx.paused)) audio[audio_is_paused ? "pause" : "play"](); - if (changed.volume && !isNaN(ctx.volume)) audio.volume = ctx.volume; - if (changed.playbackRate && !isNaN(ctx.playbackRate)) audio.playbackRate = ctx.playbackRate; - audio_updating = false; + if (dirty & /*playbackRate*/ 128 && !isNaN(/*playbackRate*/ ctx[7])) { + audio.playbackRate = /*playbackRate*/ ctx[7]; + } }, - i: noop, o: noop, - d(detaching) { - if (detaching) { - detach(audio); - } - + if (detaching) detach(audio); run_all(dispose); } }; } function instance($$self, $$props, $$invalidate) { - let { buffered, seekable, played, currentTime, duration, paused, volume, playbackRate } = $$props; + let { buffered } = $$props; + let { seekable } = $$props; + let { played } = $$props; + let { currentTime } = $$props; + let { duration } = $$props; + let { paused } = $$props; + let { volume } = $$props; + let { playbackRate } = $$props; + let { seeking } = $$props; + let { ended } = $$props; + + function audio_progress_handler() { + buffered = time_ranges_to_array(this.buffered); + $$invalidate(0, buffered); + } + + function audio_loadedmetadata_handler() { + buffered = time_ranges_to_array(this.buffered); + seekable = time_ranges_to_array(this.seekable); + $$invalidate(0, buffered); + $$invalidate(1, seekable); + } function audio_timeupdate_handler() { played = time_ranges_to_array(this.played); currentTime = this.currentTime; - $$invalidate('played', played); - $$invalidate('currentTime', currentTime); + ended = this.ended; + $$invalidate(2, played); + $$invalidate(3, currentTime); + $$invalidate(9, ended); } function audio_durationchange_handler() { duration = this.duration; - $$invalidate('duration', duration); + $$invalidate(4, duration); } function audio_play_pause_handler() { paused = this.paused; - $$invalidate('paused', paused); - } - - function audio_progress_handler() { - buffered = time_ranges_to_array(this.buffered); - $$invalidate('buffered', buffered); - } - - function audio_loadedmetadata_handler() { - buffered = time_ranges_to_array(this.buffered); - seekable = time_ranges_to_array(this.seekable); - $$invalidate('buffered', buffered); - $$invalidate('seekable', seekable); + $$invalidate(5, paused); } function audio_volumechange_handler() { volume = this.volume; - $$invalidate('volume', volume); + $$invalidate(6, volume); } function audio_ratechange_handler() { playbackRate = this.playbackRate; - $$invalidate('playbackRate', playbackRate); + $$invalidate(7, playbackRate); + } + + function audio_seeking_seeked_handler() { + seeking = this.seeking; + $$invalidate(8, seeking); + } + + function audio_ended_handler() { + ended = this.ended; + $$invalidate(9, ended); } $$self.$set = $$props => { - if ('buffered' in $$props) $$invalidate('buffered', buffered = $$props.buffered); - if ('seekable' in $$props) $$invalidate('seekable', seekable = $$props.seekable); - if ('played' in $$props) $$invalidate('played', played = $$props.played); - if ('currentTime' in $$props) $$invalidate('currentTime', currentTime = $$props.currentTime); - if ('duration' in $$props) $$invalidate('duration', duration = $$props.duration); - if ('paused' in $$props) $$invalidate('paused', paused = $$props.paused); - if ('volume' in $$props) $$invalidate('volume', volume = $$props.volume); - if ('playbackRate' in $$props) $$invalidate('playbackRate', playbackRate = $$props.playbackRate); + if ("buffered" in $$props) $$invalidate(0, buffered = $$props.buffered); + if ("seekable" in $$props) $$invalidate(1, seekable = $$props.seekable); + if ("played" in $$props) $$invalidate(2, played = $$props.played); + if ("currentTime" in $$props) $$invalidate(3, currentTime = $$props.currentTime); + if ("duration" in $$props) $$invalidate(4, duration = $$props.duration); + if ("paused" in $$props) $$invalidate(5, paused = $$props.paused); + if ("volume" in $$props) $$invalidate(6, volume = $$props.volume); + if ("playbackRate" in $$props) $$invalidate(7, playbackRate = $$props.playbackRate); + if ("seeking" in $$props) $$invalidate(8, seeking = $$props.seeking); + if ("ended" in $$props) $$invalidate(9, ended = $$props.ended); }; - return { + return [ buffered, seekable, played, @@ -137,20 +180,36 @@ function instance($$self, $$props, $$invalidate) { paused, volume, playbackRate, + seeking, + ended, + audio_progress_handler, + audio_loadedmetadata_handler, audio_timeupdate_handler, audio_durationchange_handler, audio_play_pause_handler, - audio_progress_handler, - audio_loadedmetadata_handler, audio_volumechange_handler, - audio_ratechange_handler - }; + audio_ratechange_handler, + audio_seeking_seeked_handler, + audio_ended_handler + ]; } class Component extends SvelteComponent { constructor(options) { super(); - init(this, options, instance, create_fragment, safe_not_equal, ["buffered", "seekable", "played", "currentTime", "duration", "paused", "volume", "playbackRate"]); + + init(this, options, instance, create_fragment, safe_not_equal, { + buffered: 0, + seekable: 1, + played: 2, + currentTime: 3, + duration: 4, + paused: 5, + volume: 6, + playbackRate: 7, + seeking: 8, + ended: 9 + }); } } diff --git a/test/js/samples/media-bindings/input.svelte b/test/js/samples/media-bindings/input.svelte index 4b5793ba93..a079a2e0e5 100644 --- a/test/js/samples/media-bindings/input.svelte +++ b/test/js/samples/media-bindings/input.svelte @@ -7,6 +7,8 @@ export let paused; export let volume; export let playbackRate; + export let seeking; + export let ended; -