diff --git a/.eslintrc.js b/.eslintrc.js index 2c7f2ed1b4..2023207f74 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'], diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000000..2488902b24 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,25 @@ +name: CI +on: [push, pull_request] +jobs: + Tests: + runs-on: ${{ matrix.os }} + strategy: + matrix: + node-version: [8, 10, 12] + os: [ubuntu-latest, windows-latest, macOS-latest] + steps: + - run: git config --global core.autocrlf false + - uses: actions/checkout@v1 + - uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + - 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' diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index a4603a26e2..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,20 +0,0 @@ -language: node_js -node_js: - - "8" - - "10" - - "12" -env: - global: - - BUILD_TIMEOUT=20000 - -addons: - apt: - packages: - - xvfb - -install: - - export DISPLAY=':99.0' - - Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & - - npm ci || npm install - -after_success: npm run codecov diff --git a/CHANGELOG.md b/CHANGELOG.md index 12ea328f9c..566fde5005 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,62 @@ # Svelte changelog +## 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 ``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 `` 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 `` 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 ` ``` +--- + +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). @@ -696,7 +718,7 @@ out:draw={params} Animates the stroke of an SVG element, like a snake in a tube. `in` transitions begin with the path invisible and draw the path to the screen over time. `out` transitions start in a visible state and gradually erase the path. `draw` only works with elements that have a `getTotalLength` method, like `` and ``. -`scale` accepts the following parameters: +`draw` accepts the following parameters: * `delay` (`number`, default 0) — milliseconds before starting * `speed` (`number`, default undefined) - the speed of the animation, see below. @@ -945,7 +967,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 `` [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 `` [element](docs#svelte_options). ```html @@ -1019,8 +1041,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 `` 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 f47fe564af..407b1dfc13 100644 --- a/site/content/docs/04-compile-time.md +++ b/site/content/docs/04-compile-time.md @@ -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` @@ -73,6 +74,7 @@ The following options can be passed to the compiler. None are required: | `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. | `outputFilename` | `null` | A `string` used for your JavaScript sourcemap. @@ -315,7 +317,7 @@ walk(ast: Node, { --- -The `walk` function provides a way to walk to abstract syntax trees generated by the parser, using the compiler's own built-in instance of [estree-walker](https://github.com/Rich-Harris/estree-walker). +The `walk` function provides a way to walk the abstract syntax trees generated by the parser, using the compiler's own built-in instance of [estree-walker](https://github.com/Rich-Harris/estree-walker). The walker takes an abstract syntax tree to walk and an object with two optional methods: `enter` and `leave`. For each node, `enter` is called (if present). Then, unless `this.skip()` is called during `enter`, each of the children are traversed, and then `leave` is called on the node. 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 @@ {format(duration)} - \ No newline at end of file + 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; } 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 - \ 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 @@ + + + + + + - - - - 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 @@ ``` -> 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/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..09bd67cf1e 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -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,23 @@ } }, "@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.13", + "resolved": "https://registry.npmjs.org/@sveltejs/svelte-repl/-/svelte-repl-0.1.13.tgz", + "integrity": "sha512-griMkrRRzAQq22awKaBN5cewGly4xeeo8qpDs8ZhQxmEk5TcX3dMhIGMLuPTSv3Yr0s2c6TDJXcN+ORJn//fpQ==", "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", "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 +1593,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": { @@ -3368,12 +3374,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 +3411,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 +3454,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 +3463,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": { diff --git a/site/package.json b/site/package.json index 3f362ac891..d08aa1f742 100644 --- a/site/package.json +++ b/site/package.json @@ -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.13", "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/src/routes/_components/WhosUsingSvelte.svelte b/site/src/routes/_components/WhosUsingSvelte.svelte index 1a0a80f4ac..2a944fe289 100644 --- a/site/src/routes/_components/WhosUsingSvelte.svelte +++ b/site/src/routes/_components/WhosUsingSvelte.svelte @@ -55,11 +55,14 @@ Deck logo Dextra logo Entriwise logo + Entur logo From-Now-On logo + FusionCharts logo GoDaddy logo Grainger logo HealthTree logo itslearning logo + Jacoux logo Metrovias logo Mustlab logo Nesta logo @@ -67,15 +70,18 @@ Neue Zürcher Zeitung logo The New York Times logo OberonSPACE logo + Ofof logo Open State Foundation logo Panascais logo + Pankod logo Razorpay logo Socialist Party logo + SQL Tribe logo Stone Payments logo Strix Cloud logoStrix Cloud Sucuri logo Thunderdome logo - Tokopedia logo + Tokopedia logo Webdesq logo Zevvle logo + your company? 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 `
${highlighted}
`; - }; + renderer.code = highlight; renderer.heading = (text, level, rawtext) => { const fragment = makeSlug(rawtext); 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/repl/[id]/_components/AppControls/index.svelte b/site/src/routes/repl/[id]/_components/AppControls/index.svelte index 4cfd5d43b2..007dba3461 100644 --- a/site/src/routes/repl/[id]/_components/AppControls/index.svelte +++ b/site/src/routes/repl/[id]/_components/AppControls/index.svelte @@ -140,12 +140,12 @@ if (imports.length > 0) { const idx = files.findIndex(({ path }) => path === 'package.json'); const pkg = JSON.parse(files[idx].data); - const deps = {}; + const { devDependencies } = pkg; imports.forEach(mod => { const match = /^(@[^/]+\/)?[^@/]+/.exec(mod); - deps[match[0]] = 'latest'; + devDependencies[match[0]] = 'latest'; }); - pkg.dependencies = deps; + pkg.devDependencies = devDependencies; files[idx].data = JSON.stringify(pkg, null, ' '); } diff --git a/site/src/routes/tutorial/[slug]/index.json.js b/site/src/routes/tutorial/[slug]/index.json.js index 291760bc6b..26f5d54b31 100644 --- a/site/src/routes/tutorial/[slug]/index.json.js +++ b/site/src/routes/tutorial/[slug]/index.json.js @@ -1,9 +1,9 @@ import * as fs from 'fs'; import * as path from 'path'; import marked from 'marked'; -import PrismJS from 'prismjs'; import send from '@polka/send'; -import { extract_frontmatter, extract_metadata, langs, link_renderer } from '@sveltejs/site-kit/utils/markdown'; +import { extract_frontmatter, extract_metadata, link_renderer } from '@sveltejs/site-kit/utils/markdown'; +import { highlight } from '../../../utils/highlight'; const cache = new Map(); @@ -57,14 +57,7 @@ function get_tutorial(slug) { } } - const plang = langs[lang]; - const highlighted = PrismJS.highlight( - source, - PrismJS.languages[plang], - lang - ); - - return `
${prefix}
${highlighted}
`; + return `
${prefix}${highlight(source, lang)}
`; }; let html = marked(content, { renderer }); diff --git a/site/src/routes/tutorial/[slug]/index.svelte b/site/src/routes/tutorial/[slug]/index.svelte index ec23906057..be59665970 100644 --- a/site/src/routes/tutorial/[slug]/index.svelte +++ b/site/src/routes/tutorial/[slug]/index.svelte @@ -218,17 +218,17 @@ } .show { - background: rgba(0,0,0,.4); + background: var(--prime); padding: .3em .7em; border-radius: var(--border-r); top: .1em; position: relative; font-size: var(--h5); font-weight: 300; + color: rgba(255,255,255,0.7); } .show:hover { - background: rgba(0,0,0,.65); color: white; } diff --git a/site/src/server.js b/site/src/server.js index 2425b51f54..c7cf93c3b5 100644 --- a/site/src/server.js +++ b/site/src/server.js @@ -14,9 +14,11 @@ const app = polka({ } }); -app.use( - authenticate(), +if (process.env.PGHOST) { + app.use(authenticate()); +} +app.use( sirv('static', { dev: process.env.NODE_ENV === 'development', setHeaders(res) { @@ -32,4 +34,4 @@ app.use( }) ); -app.listen(PORT); \ No newline at end of file +app.listen(PORT); diff --git a/site/src/utils/db.js b/site/src/utils/db.js index a4d398e181..069450b0f3 100644 --- a/site/src/utils/db.js +++ b/site/src/utils/db.js @@ -1,8 +1,7 @@ import { Pool } from 'pg'; -export const DB = new Pool({ - connectionString: process.env.DATABASE_URL -}); +// Uses `PG*` ENV vars +export const DB = process.env.PGHOST ? new Pool() : null; export function query(text, values=[]) { return DB.query(text, values).then(r => r.rows); diff --git a/site/src/utils/highlight.js b/site/src/utils/highlight.js new file mode 100644 index 0000000000..d8be46b3a6 --- /dev/null +++ b/site/src/utils/highlight.js @@ -0,0 +1,14 @@ +import { langs } from '@sveltejs/site-kit/utils/markdown.js'; +import PrismJS from 'prismjs'; +import 'prismjs/components/prism-bash'; + +export function highlight(source, lang) { + const plang = langs[lang] || ''; + const highlighted = plang ? PrismJS.highlight( + source, + PrismJS.languages[plang], + lang, + ) : source.replace(/[&<>]/g, c => ({ '&': '&', '<': '<', '>': '>' })[c]); + + return `
${highlighted}
`; +} diff --git a/site/static/favicon.png b/site/static/favicon.png index b8b26e3044..ddbebf3b4f 100644 Binary files a/site/static/favicon.png and b/site/static/favicon.png differ diff --git a/site/static/images/twitter-card.png b/site/static/images/twitter-card.png index 5e0a55e570..1e8271f655 100644 Binary files a/site/static/images/twitter-card.png and b/site/static/images/twitter-card.png differ diff --git a/site/static/logo-mask.svg b/site/static/logo-mask.svg deleted file mode 100644 index d7919a61ab..0000000000 --- a/site/static/logo-mask.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/site/static/organisations/bekchy.png b/site/static/organisations/bekchy.png index 737e3f95d9..011553cb42 100644 Binary files a/site/static/organisations/bekchy.png and b/site/static/organisations/bekchy.png differ diff --git a/site/static/organisations/dextra.png b/site/static/organisations/dextra.png index a550304adf..725f9bd511 100644 Binary files a/site/static/organisations/dextra.png and b/site/static/organisations/dextra.png differ diff --git a/site/static/organisations/entriwise.png b/site/static/organisations/entriwise.png index f8e3e80e91..be305e1300 100644 Binary files a/site/static/organisations/entriwise.png and b/site/static/organisations/entriwise.png differ diff --git a/site/static/organisations/entur.svg b/site/static/organisations/entur.svg new file mode 100644 index 0000000000..98bb5cc937 --- /dev/null +++ b/site/static/organisations/entur.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/site/static/organisations/fusioncharts.svg b/site/static/organisations/fusioncharts.svg new file mode 100644 index 0000000000..6712115de8 --- /dev/null +++ b/site/static/organisations/fusioncharts.svg @@ -0,0 +1,18 @@ + + + + logo colour + Created with Sketch. + + + + + + + + + + + + + \ No newline at end of file diff --git a/site/static/organisations/jacoux.png b/site/static/organisations/jacoux.png new file mode 100644 index 0000000000..6d3f52017c Binary files /dev/null and b/site/static/organisations/jacoux.png differ diff --git a/site/static/organisations/ofof.png b/site/static/organisations/ofof.png new file mode 100644 index 0000000000..5ecde9b0fd Binary files /dev/null and b/site/static/organisations/ofof.png differ diff --git a/site/static/organisations/pankod.svg b/site/static/organisations/pankod.svg new file mode 100644 index 0000000000..34578a7739 --- /dev/null +++ b/site/static/organisations/pankod.svg @@ -0,0 +1,33 @@ + + + + Dark + Created with Sketch. + + + + + + + + \ No newline at end of file diff --git a/site/static/organisations/sqltribe.svg b/site/static/organisations/sqltribe.svg new file mode 100644 index 0000000000..2a51dfc0a7 --- /dev/null +++ b/site/static/organisations/sqltribe.svg @@ -0,0 +1,106 @@ + +image/svg+xml \ No newline at end of file diff --git a/site/static/organisations/tokopedia.2x.png b/site/static/organisations/tokopedia.2x.png deleted file mode 100644 index 5ba45fdb2b..0000000000 Binary files a/site/static/organisations/tokopedia.2x.png and /dev/null differ diff --git a/site/static/organisations/tokopedia.3x.png b/site/static/organisations/tokopedia.3x.png deleted file mode 100644 index 52b34a0b91..0000000000 Binary files a/site/static/organisations/tokopedia.3x.png and /dev/null differ diff --git a/site/static/organisations/tokopedia.png b/site/static/organisations/tokopedia.png deleted file mode 100644 index 16fef7fe63..0000000000 Binary files a/site/static/organisations/tokopedia.png and /dev/null differ diff --git a/site/static/organisations/tokopedia.svg b/site/static/organisations/tokopedia.svg new file mode 100644 index 0000000000..d284f05d7b --- /dev/null +++ b/site/static/organisations/tokopedia.svg @@ -0,0 +1,4 @@ + + + + diff --git a/site/static/tutorial/kitten.png b/site/static/tutorial/kitten.png index 6ef37691bc..6b0cedc945 100644 Binary files a/site/static/tutorial/kitten.png and b/site/static/tutorial/kitten.png differ diff --git a/src/compiler/compile/Component.ts b/src/compiler/compile/Component.ts index fa8665ffde..2d696ad306 100644 --- a/src/compiler/compile/Component.ts +++ b/src/compiler/compile/Component.ts @@ -1,9 +1,7 @@ -import MagicString, { Bundle } from 'magic-string'; -// @ts-ignore import { walk, childKeys } from 'estree-walker'; import { getLocator } from 'locate-character'; import Stats from '../Stats'; -import { globals, reserved } from '../utils/names'; +import { globals, reserved, is_valid } from '../utils/names'; import { namespaces, valid_namespaces } from '../utils/namespaces'; import create_module from './create_module'; import { @@ -16,20 +14,20 @@ import Stylesheet from './css/Stylesheet'; import { test } from '../config'; import Fragment from './nodes/Fragment'; import internal_exports from './internal_exports'; -import { Node, Ast, CompileOptions, Var, Warning } from '../interfaces'; +import { Ast, CompileOptions, Var, Warning } from '../interfaces'; import error from '../utils/error'; import get_code_frame from '../utils/get_code_frame'; import flatten_reference from './utils/flatten_reference'; +import is_used_as_reference from './utils/is_used_as_reference'; import is_reference from 'is-reference'; import TemplateScope from './nodes/shared/TemplateScope'; import fuzzymatch from '../utils/fuzzymatch'; -import { remove_indentation, add_indentation } from '../utils/indentation'; import get_object from './utils/get_object'; -import unwrap_parens from './utils/unwrap_parens'; import Slot from './nodes/Slot'; -import { Node as ESTreeNode } from 'estree'; +import { Node, ImportDeclaration, Identifier, Program, ExpressionStatement, AssignmentExpression, Literal } from 'estree'; import add_to_set from './utils/add_to_set'; import check_graph_for_cycles from './utils/check_graph_for_cycles'; +import { print, x, b } from 'code-red'; interface ComponentOptions { namespace?: string; @@ -46,40 +44,6 @@ childKeys.EachBlock = childKeys.IfBlock = ['children', 'else']; childKeys.Attribute = ['value']; childKeys.ExportNamedDeclaration = ['declaration', 'specifiers']; -function remove_node( - code: MagicString, - start: number, - end: number, - body: Node, - node: Node -) { - const i = body.indexOf(node); - if (i === -1) throw new Error('node not in list'); - - let a; - let b; - - if (body.length === 1) { - // remove everything, leave {} - a = start; - b = end; - } else if (i === 0) { - // remove everything before second node, including comments - a = start; - while (/\s/.test(code.original[a])) a += 1; - - b = body[i].end; - while (/[\s,]/.test(code.original[b])) b += 1; - } else { - // remove the end of the previous node to the end of this one - a = body[i - 1].end; - b = node.end; - } - - code.remove(a, b); - return; -} - export default class Component { stats: Stats; warnings: Warning[]; @@ -87,9 +51,9 @@ export default class Component { ignore_stack: Array> = []; ast: Ast; + original_ast: Ast; source: string; - code: MagicString; - name: string; + name: Identifier; compile_options: CompileOptions; fragment: Fragment; module_scope: Scope; @@ -104,14 +68,12 @@ export default class Component { vars: Var[] = []; var_lookup: Map = new Map(); - imports: Node[] = []; - module_javascript: string; - javascript: string; + imports: ImportDeclaration[] = []; hoistable_nodes: Set = new Set(); node_for_declaration: Map = new Map(); - partly_hoisted: string[] = []; - fully_hoisted: string[] = []; + partly_hoisted: Array<(Node | Node[])> = []; + fully_hoisted: Array<(Node | Node[])> = []; reactive_declarations: Array<{ assignees: Set; dependencies: Set; @@ -121,26 +83,17 @@ export default class Component { reactive_declaration_nodes: Set = new Set(); has_reactive_assignments = false; injected_reactive_declaration_vars: Set = new Set(); - helpers: Map = new Map(); - globals: Map = new Map(); + helpers: Map = new Map(); + globals: Map = new Map(); indirect_dependencies: Map> = new Map(); file: string; locate: (c: number) => { line: number; column: number }; - // TODO this does the same as component.locate! remove one or the other - locator: ( - search: number, - startIndex?: number - ) => { - line: number; - column: number; - }; - stylesheet: Stylesheet; - aliases: Map = new Map(); + aliases: Map = new Map(); used_names: Set = new Set(); globally_used_names: Set = new Set(); @@ -155,7 +108,7 @@ export default class Component { stats: Stats, warnings: Warning[] ) { - this.name = name; + this.name = { type: 'Identifier', name }; this.stats = stats; this.warnings = warnings; @@ -163,6 +116,15 @@ export default class Component { this.source = source; this.compile_options = compile_options; + // the instance JS gets mutated, so we park + // a copy here for later. TODO this feels gross + this.original_ast = { + html: ast.html, + css: ast.css, + instance: ast.instance && JSON.parse(JSON.stringify(ast.instance)), + module: ast.module + }; + this.file = compile_options.filename && (typeof process !== 'undefined' @@ -170,9 +132,7 @@ export default class Component { .replace(process.cwd(), '') .replace(/^[/\\]/, '') : compile_options.filename); - this.locate = getLocator(this.source); - - this.code = new MagicString(source); + this.locate = getLocator(this.source, { offsetLine: 1 }); // styles this.stylesheet = new Stylesheet( @@ -206,15 +166,16 @@ export default class Component { } this.tag = this.component_options.tag || compile_options.tag; } else { - this.tag = this.name; + this.tag = this.name.name; } - this.walk_module_js(); + this.walk_module_js_pre_template(); this.walk_instance_js_pre_template(); this.fragment = new Fragment(this, ast.html); this.name = this.get_unique_name(name); + this.walk_module_js_post_template(); this.walk_instance_js_post_template(); if (!compile_options.customElement) this.stylesheet.reify(); @@ -257,15 +218,6 @@ export default class Component { } } - add_sourcemap_locations(node: Node) { - walk(node, { - enter: (node: Node) => { - this.code.addSourcemapLocation(node.start); - this.code.addSourcemapLocation(node.end); - }, - }); - } - alias(name: string) { if (!this.aliases.has(name)) { this.aliases.set(name, this.get_unique_name(name)); @@ -274,19 +226,13 @@ export default class Component { return this.aliases.get(name); } - helper(name: string) { - const alias = this.alias(name); - this.helpers.set(name, alias); - return alias; - } - global(name: string) { const alias = this.alias(name); this.globals.set(name, alias); return alias; } - generate(result: string) { + generate(result?: Node[]) { let js = null; let css = null; @@ -294,55 +240,65 @@ export default class Component { const { compile_options, name } = this; const { format = 'esm' } = compile_options; - const banner = `/* ${ - this.file ? `${this.file} ` : `` - }generated by Svelte v${'__VERSION__'} */`; - - result = result - .replace(/__svelte:self__/g, this.name) - .replace( - compile_options.generate === 'ssr' - ? /(@+|#+)(\w*(?:-\w*)?)/g - : /(@+)(\w*(?:-\w*)?)/g, - (_match: string, sigil: string, name: string) => { - if (sigil === '@') { - if (name[0] === '_') { - return this.global(name.slice(1)); - } + const banner = `${this.file ? `${this.file} ` : ``}generated by Svelte v${'__VERSION__'}`; - if (!internal_exports.has(name)) { - throw new Error( - `compiler error: this shouldn't happen! generated code is trying to use inexistent internal '${name}'` - ); + const program: any = { type: 'Program', body: result }; + + walk(program, { + enter: (node, parent, key) => { + if (node.type === 'Identifier') { + if (node.name[0] === '@') { + if (node.name[1] === '_') { + const alias = this.global(node.name.slice(2)); + node.name = alias.name; + } else { + let name = node.name.slice(1); + + if (compile_options.dev) { + if (internal_exports.has(`${name}_dev`)) { + name += '_dev'; + } else if (internal_exports.has(`${name}Dev`)) { + name += 'Dev'; + } + } + + const alias = this.alias(name); + this.helpers.set(name, alias); + node.name = alias.name; } + } - if (compile_options.dev) { - if (internal_exports.has(`${name}_dev`)) name = `${name}_dev`; - else if (internal_exports.has(`${name}Dev`)) - name = `${name}Dev`; + else if (node.name[0] !== '#' && !is_valid(node.name)) { + // this hack allows x`foo.${bar}` where bar could be invalid + const literal: Literal = { type: 'Literal', value: node.name }; + + if (parent.type === 'Property' && key === 'key') { + parent.key = literal; } - return this.helper(name); + else if (parent.type === 'MemberExpression' && key === 'property') { + parent.property = literal; + parent.computed = true; + } } - - return sigil.slice(1) + name; } - ); + } + }); const referenced_globals = Array.from( this.globals, - ([name, alias]) => name !== alias && { name, alias } + ([name, alias]) => name !== alias.name && { name, alias } ).filter(Boolean); if (referenced_globals.length) { - this.helper('globals'); + this.helpers.set('globals', this.alias('globals')); } const imported_helpers = Array.from(this.helpers, ([name, alias]) => ({ name, alias, })); - const module = create_module( - result, + create_module( + program, format, name, banner, @@ -355,67 +311,30 @@ export default class Component { .map(variable => ({ name: variable.name, as: variable.export_name, - })), - this.source + })) ); - const parts = module.split('✂]'); - const final_chunk = parts.pop(); - - const compiled = new Bundle({ separator: '' }); - - function add_string(str: string) { - compiled.addSource({ - content: new MagicString(str), - }); - } - - const { filename } = compile_options; - - // special case — the source file doesn't actually get used anywhere. we need - // to add an empty file to populate map.sources and map.sourcesContent - if (!parts.length) { - compiled.addSource({ - filename, - content: new MagicString(this.source).remove(0, this.source.length), - }); - } - - const pattern = /\[✂(\d+)-(\d+)$/; - - parts.forEach((str: string) => { - const chunk = str.replace(pattern, ''); - if (chunk) add_string(chunk); - - const match = pattern.exec(str); - - const snippet = this.code.snip(+match[1], +match[2]); - - compiled.addSource({ - filename, - content: snippet, - }); - }); - - add_string(final_chunk); - css = compile_options.customElement ? { code: null, map: null } : this.stylesheet.render(compile_options.cssOutputFilename, true); - js = { - code: compiled.toString(), - map: compiled.generateMap({ - includeContent: true, - file: compile_options.outputFilename, - }), - }; + js = print(program, { + sourceMapSource: compile_options.filename + }); + + js.map.sources = [ + compile_options.filename ? get_relative_path(compile_options.outputFilename || '', compile_options.filename) : null + ]; + + js.map.sourcesContent = [ + this.source + ]; } return { js, css, - ast: this.ast, + ast: this.original_ast, warnings: this.warnings, vars: this.vars .filter(v => !v.global && !v.internal) @@ -428,12 +347,13 @@ export default class Component { reassigned: v.reassigned || false, referenced: v.referenced || false, writable: v.writable || false, + referenced_from_script: v.referenced_from_script || false, })), stats: this.stats.render(), }; } - get_unique_name(name: string) { + get_unique_name(name: string): Identifier { if (test) name = `${name}$`; let alias = name; for ( @@ -445,7 +365,7 @@ export default class Component { alias = `${name}_${i++}` ); this.used_names.add(alias); - return alias; + return { type: 'Identifier', name: alias }; } get_unique_name_maker() { @@ -459,7 +379,7 @@ export default class Component { internal_exports.forEach(add); this.var_lookup.forEach((_value, key) => add(key)); - return (name: string) => { + return (name: string): Identifier => { if (test) name = `${name}$`; let alias = name; for ( @@ -469,7 +389,11 @@ export default class Component { ); local_used_names.add(alias); this.globally_used_names.add(alias); - return alias; + + return { + type: 'Identifier', + name: alias + }; }; } @@ -507,12 +431,8 @@ export default class Component { return; } - if (!this.locator) { - this.locator = getLocator(this.source, { offsetLine: 1 }); - } - - const start = this.locator(pos.start); - const end = this.locator(pos.end); + const start = this.locate(pos.start); + const end = this.locate(pos.end); const frame = get_code_frame(this.source, start.line - 1, start.column); @@ -525,74 +445,77 @@ export default class Component { pos: pos.start, filename: this.compile_options.filename, toString: () => - `${warning.message} (${start.line + 1}:${start.column})\n${frame}`, + `${warning.message} (${start.line}:${start.column})\n${frame}`, }); } - extract_imports(content) { - const { code } = this; - - content.body.forEach(node => { - if (node.type === 'ImportDeclaration') { - // imports need to be hoisted out of the IIFE - remove_node(code, content.start, content.end, content.body, node); - this.imports.push(node); - } - }); + extract_imports(node) { + this.imports.push(node); } - extract_exports(content) { - const { code } = this; + extract_exports(node) { + if (node.type === 'ExportDefaultDeclaration') { + this.error(node, { + code: `default-export`, + message: `A component cannot have a default export`, + }); + } - content.body.forEach(node => { - if (node.type === 'ExportDefaultDeclaration') { + if (node.type === 'ExportNamedDeclaration') { + if (node.source) { this.error(node, { - code: `default-export`, - message: `A component cannot have a default export`, + code: `not-implemented`, + message: `A component currently cannot have an export ... from`, }); } - - if (node.type === 'ExportNamedDeclaration') { - if (node.source) { - this.error(node, { - code: `not-implemented`, - message: `A component currently cannot have an export ... from`, + if (node.declaration) { + if (node.declaration.type === 'VariableDeclaration') { + node.declaration.declarations.forEach(declarator => { + extract_names(declarator.id).forEach(name => { + const variable = this.var_lookup.get(name); + variable.export_name = name; + if (variable.writable && !(variable.referenced || variable.referenced_from_script)) { + this.warn(declarator, { + code: `unused-export-let`, + message: `${this.name.name} has unused export property '${name}'. If it is for external reference only, please consider using \`export const '${name}'\`` + }); + } + }); }); + } else { + const { name } = node.declaration.id; + + const variable = this.var_lookup.get(name); + variable.export_name = name; } - if (node.declaration) { - if (node.declaration.type === 'VariableDeclaration') { - node.declaration.declarations.forEach(declarator => { - extract_names(declarator.id).forEach(name => { - const variable = this.var_lookup.get(name); - variable.export_name = name; - }); - }); - } else { - const { name } = node.declaration.id; - const variable = this.var_lookup.get(name); - variable.export_name = name; - } + return node.declaration; + } else { + node.specifiers.forEach(specifier => { + const variable = this.var_lookup.get(specifier.local.name); - code.remove(node.start, node.declaration.start); - } else { - remove_node(code, content.start, content.end, content.body, node); - node.specifiers.forEach(specifier => { - const variable = this.var_lookup.get(specifier.local.name); + if (variable) { + variable.export_name = specifier.exported.name; - if (variable) { - variable.export_name = specifier.exported.name; - } else { - // TODO what happens with `export { Math }` or some other global? + if (variable.writable && !(variable.referenced || variable.referenced_from_script)) { + this.warn(specifier, { + code: `unused-export-let`, + message: `${this.name.name} has unused export property '${specifier.exported.name}'. If it is for external reference only, please consider using \`export const '${specifier.exported.name}'\`` + }); } - }); - } + } + }); + + return null; } - }); + } } extract_javascript(script) { - const nodes_to_include = script.content.body.filter(node => { + if (!script) return null; + + return script.content.body.filter(node => { + if (!node) return false; if (this.hoistable_nodes.has(node)) return false; if (this.reactive_declaration_nodes.has(node)) return false; if (node.type === 'ImportDeclaration') return false; @@ -600,39 +523,9 @@ export default class Component { return false; return true; }); - - if (nodes_to_include.length === 0) return null; - - let a = script.content.start; - while (/\s/.test(this.source[a])) a += 1; - - let b = a; - - let result = ''; - - script.content.body.forEach(node => { - if ( - this.hoistable_nodes.has(node) || - this.reactive_declaration_nodes.has(node) - ) { - if (a !== b) result += `[✂${a}-${b}✂]`; - a = node.end; - } - - b = node.end; - }); - - // while (/\s/.test(this.source[a - 1])) a -= 1; - - b = script.content.end; - while (/\s/.test(this.source[b - 1])) b -= 1; - - if (a < b) result += `[✂${a}-${b}✂]`; - - return result || null; } - walk_module_js() { + walk_module_js_pre_template() { const component = this; const script = this.ast.module; if (!script) return; @@ -640,7 +533,7 @@ export default class Component { walk(script.content, { enter(node) { if (node.type === 'LabeledStatement' && node.label.name === '$') { - component.warn(node, { + component.warn(node as any, { code: 'module-script-reactive-declaration', message: '$: has no effect in a module script', }); @@ -648,30 +541,30 @@ export default class Component { }, }); - this.add_sourcemap_locations(script.content); - const { scope, globals } = create_scopes(script.content); this.module_scope = scope; scope.declarations.forEach((node, name) => { if (name[0] === '$') { - this.error(node, { + this.error(node as any, { code: 'illegal-declaration', message: `The $ prefix is reserved, and cannot be used for variable and import names`, }); } + const writable = node.type === 'VariableDeclaration' && (node.kind === 'var' || node.kind === 'let'); + this.add_var({ name, module: true, hoistable: true, - writable: node.kind === 'var' || node.kind === 'let', + writable }); }); globals.forEach((node, name) => { if (name[0] === '$') { - this.error(node, { + this.error(node as any, { code: 'illegal-subscription', message: `Cannot reference store value inside '; -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 +29,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); @@ -41,16 +42,19 @@ export default function read_script(parser: Parser, start: number, attributes: N repeat(' ', script_start) + parser.template.slice(script_start, script_end); parser.index = script_end + script_closing_tag.length; - let ast; + let ast: Program; try { - ast = acorn.parse(source); + ast = acorn.parse(source) as any as Program; } catch (err) { parser.acorn_error(err); } - ast.start = script_start; + // TODO is this necessary? + (ast as any).start = script_start; + return { + type: 'Script', start, end: parser.index, context: get_context(parser, attributes, start), diff --git a/src/compiler/parse/read/style.ts b/src/compiler/parse/read/style.ts index a14356e05b..dd9d1286f2 100644 --- a/src/compiler/parse/read/style.ts +++ b/src/compiler/parse/read/style.ts @@ -1,9 +1,10 @@ import parse from 'css-tree/lib/parser/index.js'; import { walk } from 'estree-walker'; import { Parser } from '../index'; -import { Node } from '../../interfaces'; +import { Node } from 'estree'; +import { Style } from '../../interfaces'; -export default function read_style(parser: Parser, start: number, attributes: Node[]) { +export default function read_style(parser: Parser, start: number, attributes: Node[]): Style { const content_start = parser.index; const styles = parser.read_until(/<\/style>/); const content_end = parser.index; @@ -30,7 +31,7 @@ export default function read_style(parser: Parser, start: number, attributes: No // tidy up AST walk(ast, { - enter: (node: Node) => { + enter: (node: any) => { // `any` because this isn't an ESTree node // replace `ref:a` nodes if (node.type === 'Selector') { for (let i = 0; i < node.children.length; i += 1) { @@ -46,6 +47,13 @@ export default function read_style(parser: Parser, start: number, attributes: No } } + if (node.type === 'Declaration' && node.value.type === 'Value' && node.value.children.length === 0) { + parser.error({ + code: `invalid-declaration`, + message: `Declaration cannot be empty` + }, node.start); + } + if (node.loc) { node.start = node.loc.start.offset; node.end = node.loc.end.offset; @@ -58,6 +66,7 @@ export default function read_style(parser: Parser, start: number, attributes: No const end = parser.index; return { + type: 'Style', start, end, attributes, @@ -65,12 +74,12 @@ export default function read_style(parser: Parser, start: number, attributes: No content: { start: content_start, end: content_end, - styles, - }, + styles + } }; } -function is_ref_selector(a: Node, b: Node) { +function is_ref_selector(a: any, b: any) { // TODO add CSS node types if (!b) return false; return ( diff --git a/src/compiler/parse/state/mustache.ts b/src/compiler/parse/state/mustache.ts index 8de35cee48..140e722b10 100644 --- a/src/compiler/parse/state/mustache.ts +++ b/src/compiler/parse/state/mustache.ts @@ -4,9 +4,9 @@ import { closing_tag_omitted } from '../utils/html'; import { whitespace } from '../../utils/patterns'; import { trim_start, trim_end } from '../../utils/trim'; import { Parser } from '../index'; -import { Node } from '../../interfaces'; +import { TemplateNode } from '../../interfaces'; -function trim_whitespace(block: Node, trim_before: boolean, trim_after: boolean) { +function trim_whitespace(block: TemplateNode, trim_before: boolean, trim_after: boolean) { if (!block.children || block.children.length === 0) return; // AwaitBlock const first_child = block.children[0]; @@ -160,57 +160,47 @@ export default function mustache(parser: Parser) { parser.stack.push(block.else); } - } else if (parser.eat(':then')) { - // TODO DRY out this and the next section - const pending_block = parser.current(); - if (pending_block.type === 'PendingBlock') { - pending_block.end = start; - parser.stack.pop(); - const await_block = parser.current(); + } else if (parser.match(':then') || parser.match(':catch')) { + const block = parser.current(); + const is_then = parser.eat(':then') || !parser.eat(':catch'); - if (!parser.eat('}')) { - parser.require_whitespace(); - await_block.value = parser.read_identifier(); - parser.allow_whitespace(); - parser.eat('}', true); + if (is_then) { + if (block.type !== 'PendingBlock') { + parser.error({ + code: `invalid-then-placement`, + message: 'Cannot have an {:then} block outside an {#await ...} block' + }); } - - const then_block: Node = { - start, - end: null, - type: 'ThenBlock', - children: [], - skip: false - }; - - await_block.then = then_block; - parser.stack.push(then_block); - } - } else if (parser.eat(':catch')) { - const then_block = parser.current(); - if (then_block.type === 'ThenBlock') { - then_block.end = start; - parser.stack.pop(); - const await_block = parser.current(); - - if (!parser.eat('}')) { - parser.require_whitespace(); - await_block.error = parser.read_identifier(); - parser.allow_whitespace(); - parser.eat('}', true); + } else { + if (block.type !== 'ThenBlock' && block.type !== 'PendingBlock') { + parser.error({ + code: `invalid-catch-placement`, + message: 'Cannot have an {:catch} block outside an {#await ...} block' + }); } + } - const catch_block: Node = { - start, - end: null, - type: 'CatchBlock', - children: [], - skip: false - }; + block.end = start; + parser.stack.pop(); + const await_block = parser.current(); - await_block.catch = catch_block; - parser.stack.push(catch_block); + if (!parser.eat('}')) { + parser.require_whitespace(); + await_block[is_then ? 'value': 'error'] = parser.read_identifier(); + parser.allow_whitespace(); + parser.eat('}', true); } + + const new_block: TemplateNode = { + start, + end: null, + type: is_then ? 'ThenBlock': 'CatchBlock', + children: [], + skip: false + }; + + await_block[is_then ? 'then' : 'catch'] = new_block; + parser.stack.push(new_block); } else if (parser.eat('#')) { // {#if foo}, {#each foo} or {#await foo} let type; @@ -232,7 +222,7 @@ export default function mustache(parser: Parser) { const expression = read_expression(parser); - const block: Node = type === 'AwaitBlock' ? + const block: TemplateNode = type === 'AwaitBlock' ? { start, end: null, diff --git a/src/compiler/parse/state/tag.ts b/src/compiler/parse/state/tag.ts index 21a7b3caea..c7e761afc2 100644 --- a/src/compiler/parse/state/tag.ts +++ b/src/compiler/parse/state/tag.ts @@ -4,7 +4,7 @@ import read_style from '../read/style'; import { decode_character_references, closing_tag_omitted } from '../utils/html'; import { is_void } from '../../utils/names'; import { Parser } from '../index'; -import { Directive, DirectiveType, Node, Text } from '../../interfaces'; +import { Directive, DirectiveType, TemplateNode, Text } from '../../interfaces'; import fuzzymatch from '../../utils/fuzzymatch'; import list from '../../utils/list'; @@ -37,10 +37,8 @@ const specials = new Map([ ], ]); -// eslint-disable-next-line no-useless-escape -const SELF = /^svelte:self(?=[\s\/>])/; -// eslint-disable-next-line no-useless-escape -const COMPONENT = /^svelte:component(?=[\s\/>])/; +const SELF = /^svelte:self(?=[\s/>])/; +const COMPONENT = /^svelte:component(?=[\s/>])/; function parent_is_head(stack) { let i = stack.length; @@ -83,7 +81,7 @@ export default function tag(parser: Parser) { parser.current().children.length ) { parser.error({ - code: `invalid-${name.slice(7)}-content`, + code: `invalid-${slug}-content`, message: `<${name}> cannot have children` }, parser.current().children[0].start); } @@ -112,7 +110,7 @@ export default function tag(parser: Parser) { : name === 'title' && parent_is_head(parser.stack) ? 'Title' : name === 'slot' && !parser.customElement ? 'Slot' : 'Element'; - const element: Node = { + const element: TemplateNode = { start, end: null, // filled in later type, @@ -406,7 +404,7 @@ function read_attribute(parser: Parser, unique_names: Set) { end: directive.end, type: 'Identifier', name: directive.name - }; + } as any; } return directive; @@ -447,7 +445,7 @@ function read_attribute_value(parser: Parser) { return value; } -function read_sequence(parser: Parser, done: () => boolean): Node[] { +function read_sequence(parser: Parser, done: () => boolean): TemplateNode[] { let current_chunk: Text = { start: parser.index, end: null, @@ -464,7 +462,7 @@ function read_sequence(parser: Parser, done: () => boolean): Node[] { } } - const chunks: Node[] = []; + const chunks: TemplateNode[] = []; while (parser.index < parser.template.length) { const index = parser.index; diff --git a/src/compiler/preprocess/index.ts b/src/compiler/preprocess/index.ts index 2faa3b97f2..4549517fbd 100644 --- a/src/compiler/preprocess/index.ts +++ b/src/compiler/preprocess/index.ts @@ -94,8 +94,12 @@ export default async function preprocess( for (const fn of script) { source = await replace_async( source, - /([^]*?)<\/script>/gi, + /|([^]*?)<\/script>/gi, async (match, attributes = '', content) => { + if (!attributes && !content) { + return match; + } + attributes = attributes || ''; const processed = await fn({ content, attributes: parse_attributes(attributes), @@ -110,8 +114,11 @@ export default async function preprocess( for (const fn of style) { source = await replace_async( source, - /([^]*?)<\/style>/gi, + /|([^]*?)<\/style>/gi, async (match, attributes = '', content) => { + if (!attributes && !content) { + return match; + } const processed: Processed = await fn({ content, attributes: parse_attributes(attributes), diff --git a/src/compiler/utils/indentation.ts b/src/compiler/utils/indentation.ts deleted file mode 100644 index 54ededc37d..0000000000 --- a/src/compiler/utils/indentation.ts +++ /dev/null @@ -1,57 +0,0 @@ -import MagicString from 'magic-string'; -import { Node } from '../interfaces'; -import { walk } from 'estree-walker'; -import repeat from './repeat'; - -export function remove_indentation(code: MagicString, node: Node) { - const indent = code.getIndentString(); - const pattern = new RegExp(`^${indent}`, 'gm'); - - const excluded = []; - - walk(node, { - enter(node) { - if (node.type === 'TemplateElement') { - excluded.push(node); - } - } - }); - - const str = code.original.slice(node.start, node.end); - - let match; - while (match = pattern.exec(str)) { - const index = node.start + match.index; - while (excluded[0] && excluded[0].end < index) excluded.shift(); - if (excluded[0] && excluded[0].start < index) continue; - - code.remove(index, index + indent.length); - } -} - -export function add_indentation(code: MagicString, node: Node, levels = 1) { - const base_indent = code.getIndentString(); - const indent = repeat(base_indent, levels); - const pattern = /\n/gm; - - const excluded = []; - - walk(node, { - enter(node) { - if (node.type === 'TemplateElement') { - excluded.push(node); - } - } - }); - - const str = code.original.slice(node.start, node.end); - - let match; - while (match = pattern.exec(str)) { - const index = node.start + match.index; - while (excluded[0] && excluded[0].end < index) excluded.shift(); - if (excluded[0] && excluded[0].start < index) continue; - - code.appendLeft(index + 1, indent); - } -} diff --git a/src/compiler/utils/names.ts b/src/compiler/utils/names.ts index 8d9150bc18..88d4d4a319 100644 --- a/src/compiler/utils/names.ts +++ b/src/compiler/utils/names.ts @@ -15,6 +15,7 @@ export const globals = new Set([ 'encodeURIComponent', 'Error', 'EvalError', + 'Event', 'history', 'Infinity', 'InternalError', @@ -23,6 +24,7 @@ export const globals = new Set([ 'isNaN', 'JSON', 'localStorage', + 'location', 'Map', 'Math', 'NaN', @@ -104,7 +106,7 @@ export function is_void(name: string) { return void_element_names.test(name) || name.toLowerCase() === '!doctype'; } -function is_valid(str: string): boolean { +export function is_valid(str: string): boolean { let i = 0; while (i < str.length) { @@ -117,16 +119,6 @@ function is_valid(str: string): boolean { return true; } -export function quote_name_if_necessary(name: string) { - if (!is_valid(name)) return `"${name}"`; - return name; -} - -export function quote_prop_if_necessary(name: string) { - if (!is_valid(name)) return `["${name}"]`; - return `.${name}`; -} - export function sanitize(name: string) { return name .replace(/[^a-zA-Z0-9_]+/g, '_') diff --git a/src/runtime/ambient.ts b/src/runtime/ambient.ts index b094056c59..09cd9b72f2 100644 --- a/src/runtime/ambient.ts +++ b/src/runtime/ambient.ts @@ -1,19 +1,3 @@ declare module '*.svelte' { - type Props = Record; - - export default class { - constructor(options: { - target: Element; - anchor?: Element; - props?: Props; - hydrate?: boolean; - intro?: boolean; - }); - - $set(props: Props): void; - $on(event: string, callback: (event: CustomEvent) => void): () => void; - $destroy(): void; - - [accessor: string]: any; - } + export { SvelteComponentDev as default } from 'svelte/internal'; } diff --git a/src/runtime/animate/index.ts b/src/runtime/animate/index.ts index d00d23c98d..087c0f7141 100644 --- a/src/runtime/animate/index.ts +++ b/src/runtime/animate/index.ts @@ -19,15 +19,17 @@ interface FlipParams { export function flip(node: Element, animation: { from: DOMRect; to: DOMRect }, params: FlipParams): AnimationConfig { const style = getComputedStyle(node); const transform = style.transform === 'none' ? '' : style.transform; + const scaleX = animation.from.width / node.clientWidth; + const scaleY = animation.from.height / node.clientHeight; - const dx = animation.from.left - animation.to.left; - const dy = animation.from.top - animation.to.top; + const dx = (animation.from.left - animation.to.left) / scaleX; + const dy = (animation.from.top - animation.to.top) / scaleY; const d = Math.sqrt(dx * dx + dy * dy); const { delay = 0, - duration = d => Math.sqrt(d) * 120, + duration = (d: number) => Math.sqrt(d) * 120, easing = cubicOut } = params; diff --git a/src/runtime/index.ts b/src/runtime/index.ts index 339cfee39f..735dd28735 100644 --- a/src/runtime/index.ts +++ b/src/runtime/index.ts @@ -9,5 +9,6 @@ export { setContext, getContext, tick, - createEventDispatcher + createEventDispatcher, + SvelteComponentDev as SvelteComponent } from 'svelte/internal'; diff --git a/src/runtime/internal/Component.ts b/src/runtime/internal/Component.ts index 74facf5b45..a9ac96db12 100644 --- a/src/runtime/internal/Component.ts +++ b/src/runtime/internal/Component.ts @@ -1,9 +1,24 @@ import { add_render_callback, flush, schedule_update, dirty_components } from './scheduler'; import { current_component, set_current_component } from './lifecycle'; -import { blank_object, is_function, run, run_all, noop } from './utils'; +import { blank_object, is_function, run, run_all, noop, has_prop } from './utils'; import { children } from './dom'; import { transition_in } from './transitions'; +interface Fragment { + key: string|null; + first: null; + /* create */ c: () => void; + /* claim */ l: (nodes: any) => void; + /* hydrate */ h: () => void; + /* mount */ m: (target: HTMLElement, anchor: any) => void; + /* update */ p: (changed: any, ctx: any) => void; + /* measure */ r: () => void; + /* fix */ f: () => void; + /* animate */ a: () => void; + /* intro */ i: (local: any) => void; + /* outro */ o: (local: any) => void; + /* destroy */ d: (detaching: 0|1) => void; +} // eslint-disable-next-line @typescript-eslint/class-name-casing interface T$$ { dirty: null; @@ -12,8 +27,8 @@ interface T$$ { update: () => void; callbacks: any; after_update: any[]; - props: any; - fragment: null|any; + props: Record; + fragment: null|false|Fragment; not_equal: any; before_update: any[]; context: Map; @@ -23,15 +38,25 @@ interface T$$ { } export function bind(component, name, callback) { - if (component.$$.props.indexOf(name) === -1) return; - component.$$.bound[name] = callback; - callback(component.$$.ctx[name]); + if (has_prop(component.$$.props, name)) { + name = component.$$.props[name] || name; + component.$$.bound[name] = callback; + callback(component.$$.ctx[name]); + } +} + +export function create_component(block) { + block && block.c(); +} + +export function claim_component(block, parent_nodes) { + block && block.l(parent_nodes); } export function mount_component(component, target, anchor) { const { fragment, on_mount, on_destroy, after_update } = component.$$; - fragment.m(target, anchor); + fragment && fragment.m(target, anchor); // onMount happens before the initial afterUpdate add_render_callback(() => { @@ -50,15 +75,16 @@ export function mount_component(component, target, anchor) { } export function destroy_component(component, detaching) { - if (component.$$.fragment) { - run_all(component.$$.on_destroy); + const $$ = component.$$; + if ($$.fragment !== null) { + run_all($$.on_destroy); - component.$$.fragment.d(detaching); + $$.fragment && $$.fragment.d(detaching); // TODO null out other refs, including component.$$ (but need to // preserve final state?) - component.$$.on_destroy = component.$$.fragment = null; - component.$$.ctx = {}; + $$.on_destroy = $$.fragment = null; + $$.ctx = {}; } } @@ -71,18 +97,18 @@ function make_dirty(component, key) { component.$$.dirty[key] = true; } -export function init(component, options, instance, create_fragment, not_equal, prop_names) { +export function init(component, options, instance, create_fragment, not_equal, props) { const parent_component = current_component; set_current_component(component); - const props = options.props || {}; + const prop_values = options.props || {}; const $$: T$$ = component.$$ = { fragment: null, ctx: null, // state - props: prop_names, + props, update: noop, not_equal, bound: blank_object(), @@ -103,27 +129,29 @@ export function init(component, options, instance, create_fragment, not_equal, p let ready = false; $$.ctx = instance - ? instance(component, props, (key, ret, value = ret) => { + ? instance(component, prop_values, (key, ret, value = ret) => { if ($$.ctx && not_equal($$.ctx[key], $$.ctx[key] = value)) { if ($$.bound[key]) $$.bound[key](value); if (ready) make_dirty(component, key); } return ret; }) - : props; + : prop_values; $$.update(); ready = true; run_all($$.before_update); - $$.fragment = create_fragment($$.ctx); + + // `false` as a special case of no DOM component + $$.fragment = create_fragment ? create_fragment($$.ctx) : false; if (options.target) { if (options.hydrate) { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - $$.fragment!.l(children(options.target)); + $$.fragment && $$.fragment!.l(children(options.target)); } else { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - $$.fragment!.c(); + $$.fragment && $$.fragment!.c(); } if (options.intro) transition_in(component.$$.fragment); @@ -135,7 +163,7 @@ export function init(component, options, instance, create_fragment, not_equal, p } export let SvelteElement; -if (typeof HTMLElement !== 'undefined') { +if (typeof HTMLElement === 'function') { SvelteElement = class extends HTMLElement { $$: T$$; constructor() { diff --git a/src/runtime/internal/await_block.ts b/src/runtime/internal/await_block.ts index 4037caa98e..6cd7ee5cb4 100644 --- a/src/runtime/internal/await_block.ts +++ b/src/runtime/internal/await_block.ts @@ -14,6 +14,8 @@ export function handle_promise(promise, info) { const child_ctx = assign(assign({}, info.ctx), info.resolved); const block = type && (info.current = type)(child_ctx); + let needs_flush = false; + if (info.block) { if (info.blocks) { info.blocks.forEach((block, i) => { @@ -33,11 +35,15 @@ export function handle_promise(promise, info) { transition_in(block, 1); block.m(info.mount(), info.anchor); - flush(); + needs_flush = true; } info.block = block; if (info.blocks) info.blocks[index] = block; + + if (needs_flush) { + flush(); + } } if (is_promise(promise)) { diff --git a/src/runtime/internal/dev.ts b/src/runtime/internal/dev.ts index 6e28d4045d..cb60131166 100644 --- a/src/runtime/internal/dev.ts +++ b/src/runtime/internal/dev.ts @@ -79,8 +79,24 @@ export function set_data_dev(text, data) { text.data = data; } + +type Props = Record; +export interface SvelteComponentDev { + $set(props?: Props): void; + $on(event: string, callback: (event: CustomEvent) => void): () => void; + $destroy(): void; + [accessor: string]: any; +} + export class SvelteComponentDev extends SvelteComponent { - constructor(options) { + constructor(options: { + target: Element; + anchor?: Element; + props?: Props; + hydrate?: boolean; + intro?: boolean; + $$inline?: boolean; + }) { if (!options || (!options.target && !options.$$inline)) { throw new Error(`'target' is a required option`); } @@ -95,3 +111,12 @@ export class SvelteComponentDev extends SvelteComponent { }; } } + +export function loop_guard(timeout) { + const start = Date.now(); + return () => { + if (Date.now() - start > timeout) { + throw new Error(`Infinite loop detected`); + } + }; +} diff --git a/src/runtime/internal/dom.ts b/src/runtime/internal/dom.ts index 58a0d0729a..e4db8c1e15 100644 --- a/src/runtime/internal/dom.ts +++ b/src/runtime/internal/dom.ts @@ -1,3 +1,5 @@ +import { has_prop } from "./utils"; + export function append(target: Node, node: Node) { target.appendChild(node); } @@ -29,7 +31,7 @@ export function object_without_properties(obj: T, exclude: const target = {} as Pick>; for (const k in obj) { if ( - Object.prototype.hasOwnProperty.call(obj, k) + has_prop(obj, k) // @ts-ignore && exclude.indexOf(k) === -1 ) { @@ -86,14 +88,18 @@ export function self(fn) { export function attr(node: Element, attribute: string, value?: string) { if (value == null) node.removeAttribute(attribute); - else node.setAttribute(attribute, value); + else if (node.getAttribute(attribute) !== value) node.setAttribute(attribute, value); } export function set_attributes(node: Element & ElementCSSInlineStyle, attributes: { [x: string]: string }) { + // @ts-ignore + const descriptors = Object.getOwnPropertyDescriptors(node.__proto__); for (const key in attributes) { - if (key === 'style') { + if (attributes[key] == null) { + node.removeAttribute(key); + } else if (key === 'style') { node.style.cssText = attributes[key]; - } else if (key in node) { + } else if (descriptors[key] && descriptors[key].set) { node[key] = attributes[key]; } else { attr(node, key, attributes[key]); diff --git a/src/runtime/internal/lifecycle.ts b/src/runtime/internal/lifecycle.ts index 5157c90fbb..5a716d3d95 100644 --- a/src/runtime/internal/lifecycle.ts +++ b/src/runtime/internal/lifecycle.ts @@ -32,9 +32,9 @@ export function onError(fn) { } export function createEventDispatcher() { - const component = current_component; + const component = get_current_component(); - return (type, detail) => { + return (type: string, detail?: any) => { const callbacks = component.$$.callbacks[type]; if (callbacks) { diff --git a/src/runtime/internal/scheduler.ts b/src/runtime/internal/scheduler.ts index 14dc9bac25..350105efad 100644 --- a/src/runtime/internal/scheduler.ts +++ b/src/runtime/internal/scheduler.ts @@ -81,11 +81,11 @@ function update($$) { function exec_update($$) { $$.update($$.dirty); - run_all($$.before_update); - $$.fragment.p($$.dirty, $$.ctx); - $$.dirty = null; + run_all($$.before_update); + $$.fragment && $$.fragment.p($$.dirty, $$.ctx); + $$.dirty = null; - $$.after_update.forEach(add_render_callback); + $$.after_update.forEach(add_render_callback); } function try_exec_update($$) { diff --git a/src/runtime/internal/ssr.ts b/src/runtime/internal/ssr.ts index 7fe07e2c7d..3957032533 100644 --- a/src/runtime/internal/ssr.ts +++ b/src/runtime/internal/ssr.ts @@ -1,26 +1,34 @@ import { set_current_component, current_component } from './lifecycle'; import { run_all, blank_object } from './utils'; +import { boolean_attributes } from '../../compiler/compile/render_ssr/handlers/shared/boolean_attributes'; export const invalid_attribute_name_character = /[\s'">/=\u{FDD0}-\u{FDEF}\u{FFFE}\u{FFFF}\u{1FFFE}\u{1FFFF}\u{2FFFE}\u{2FFFF}\u{3FFFE}\u{3FFFF}\u{4FFFE}\u{4FFFF}\u{5FFFE}\u{5FFFF}\u{6FFFE}\u{6FFFF}\u{7FFFE}\u{7FFFF}\u{8FFFE}\u{8FFFF}\u{9FFFE}\u{9FFFF}\u{AFFFE}\u{AFFFF}\u{BFFFE}\u{BFFFF}\u{CFFFE}\u{CFFFF}\u{DFFFE}\u{DFFFF}\u{EFFFE}\u{EFFFF}\u{FFFFE}\u{FFFFF}\u{10FFFE}\u{10FFFF}]/u; // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 // https://infra.spec.whatwg.org/#noncharacter -export function spread(args) { +export function spread(args, classes_to_add) { const attributes = Object.assign({}, ...args); + if (classes_to_add) { + if (attributes.class == null) { + attributes.class = classes_to_add; + } else { + attributes.class += ' ' + classes_to_add; + } + } let str = ''; Object.keys(attributes).forEach(name => { if (invalid_attribute_name_character.test(name)) return; const value = attributes[name]; - if (value === undefined) return; if (value === true) str += " " + name; - - const escaped = String(value) - .replace(/"/g, '"') - .replace(/'/g, '''); - - str += " " + name + "=" + JSON.stringify(escaped); + else if (boolean_attributes.has(name.toLowerCase())) { + if (value) str += " " + name; + } else if (value != null) { + str += " " + name + "=" + JSON.stringify(String(value) + .replace(/"/g, '"') + .replace(/'/g, ''')); + } }); return str; diff --git a/src/runtime/internal/utils.ts b/src/runtime/internal/utils.ts index d267b73cee..6816f8684a 100644 --- a/src/runtime/internal/utils.ts +++ b/src/runtime/internal/utils.ts @@ -105,3 +105,5 @@ export function set_store_value(store, ret, value = ret) { store.set(value); return ret; } + +export const has_prop = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop); \ No newline at end of file diff --git a/src/runtime/motion/spring.ts b/src/runtime/motion/spring.ts index 7742dd4106..1804ff43a5 100644 --- a/src/runtime/motion/spring.ts +++ b/src/runtime/motion/spring.ts @@ -65,7 +65,7 @@ interface Spring extends Readable{ stiffness: number; } -export function spring(value: T, opts: SpringOpts = {}): Spring { +export function spring(value?: T, opts: SpringOpts = {}): Spring { const store = writable(value); const { stiffness = 0.15, damping = 0.8, precision = 0.01 } = opts; @@ -84,12 +84,12 @@ export function spring(value: T, opts: SpringOpts = {}): Spring { target_value = new_value; const token = current_token = {}; - if (opts.hard || (spring.stiffness >= 1 && spring.damping >= 1)) { + if (value == null || opts.hard || (spring.stiffness >= 1 && spring.damping >= 1)) { cancel_task = true; // cancel any running animation last_time = now(); - last_value = value; + last_value = new_value; store.set(value = target_value); - return new Promise(f => f()); // fulfil immediately + return Promise.resolve(); } else if (opts.soft) { const rate = opts.soft === true ? .5 : +opts.soft; inv_mass_recovery_rate = 1 / (rate * 60); diff --git a/src/runtime/motion/tweened.ts b/src/runtime/motion/tweened.ts index 7159c17eb5..e33f0f79f9 100644 --- a/src/runtime/motion/tweened.ts +++ b/src/runtime/motion/tweened.ts @@ -69,13 +69,18 @@ interface Tweened extends Readable { update(updater: Updater, opts: Options): Promise; } -export function tweened(value: T, defaults: Options = {}): Tweened { +export function tweened(value?: T, defaults: Options = {}): Tweened { const store = writable(value); let task: Task; let target_value = value; function set(new_value: T, opts: Options) { + if (value == null) { + store.set(value = new_value); + return Promise.resolve(); + } + target_value = new_value; let previous_task = task; diff --git a/src/runtime/store/index.ts b/src/runtime/store/index.ts index eb2eda5779..64a63d4179 100644 --- a/src/runtime/store/index.ts +++ b/src/runtime/store/index.ts @@ -122,16 +122,30 @@ type StoresValues = T extends Readable ? U : /** * Derived value store by synchronizing one or more readable stores and * applying an aggregation function over its input values. - * @param {Stores} stores input stores - * @param {function(Stores=, function(*)=):*}fn function callback that aggregates the values - * @param {*=}initial_value when used asynchronously + * + * @param stores - input stores + * @param fn - function callback that aggregates the values */ -export function derived( +export function derived( stores: S, - fn: (values: StoresValues, set?: Subscriber) => T | Unsubscriber | void, - initial_value?: T, -): Readable { + fn: (values: StoresValues) => T +): Readable; +/** + * Derived value store by synchronizing one or more readable stores and + * applying an aggregation function over its input values. + * + * @param stores - input stores + * @param fn - function callback that aggregates the values + * @param initial_value - when used asynchronously + */ +export function derived( + stores: S, + fn: (values: StoresValues, set: (value: T) => void) => Unsubscriber | void, + initial_value?: T +): Readable; + +export function derived(stores: Stores, fn: Function, initial_value?: T): Readable { const single = !Array.isArray(stores); const stores_array: Array> = single ? [stores as Readable] @@ -141,7 +155,7 @@ export function derived( return readable(initial_value, (set) => { let inited = false; - const values: StoresValues = [] as StoresValues; + const values = []; let pending = 0; let cleanup = noop; diff --git a/src/runtime/transition/index.ts b/src/runtime/transition/index.ts index ec19ca1b68..0a20c81b1f 100644 --- a/src/runtime/transition/index.ts +++ b/src/runtime/transition/index.ts @@ -1,4 +1,4 @@ -import { cubicOut, cubicInOut } from 'svelte/easing'; +import { cubicOut, cubicInOut, linear } from 'svelte/easing'; import { assign, is_function } from 'svelte/internal'; type EasingFunction = (t: number) => number; @@ -43,17 +43,20 @@ export function blur(node: Element, { interface FadeParams { delay: number; duration: number; + easing: EasingFunction; } export function fade(node: Element, { delay = 0, - duration = 400 + duration = 400, + easing = linear }: FadeParams): TransitionConfig { const o = +getComputedStyle(node).opacity; return { delay, duration, + easing, css: t => `opacity: ${t * o}` }; } diff --git a/test/css/index.js b/test/css/index.js index be2a10bef1..dc17314597 100644 --- a/test/css/index.js +++ b/test/css/index.js @@ -1,6 +1,6 @@ import * as assert from 'assert'; import * as fs from 'fs'; -import { env, normalizeHtml, svelte } from '../helpers.js'; +import { env, svelte, setupHtmlEqual, shouldUpdateExpected } from '../helpers.js'; function try_require(file) { try { @@ -37,7 +37,11 @@ function create(code) { } describe('css', () => { - fs.readdirSync('test/css/samples').forEach(dir => { + before(() => { + setupHtmlEqual(); + }); + + fs.readdirSync(`${__dirname}/samples`).forEach(dir => { if (dir[0] === '.') return; // add .solo to a sample directory name to only run that test @@ -51,7 +55,7 @@ describe('css', () => { (solo ? it.only : skip ? it.skip : it)(dir, () => { const config = try_require(`./samples/${dir}/_config.js`) || {}; const input = fs - .readFileSync(`test/css/samples/${dir}/input.svelte`, 'utf-8') + .readFileSync(`${__dirname}/samples/${dir}/input.svelte`, 'utf-8') .replace(/\s+$/, ''); const expected_warnings = (config.warnings || []).map(normalize_warning); @@ -74,18 +78,42 @@ describe('css', () => { assert.deepEqual(dom_warnings, ssr_warnings); assert.deepEqual(dom_warnings.map(normalize_warning), expected_warnings); - fs.writeFileSync(`test/css/samples/${dir}/_actual.css`, dom.css.code); + fs.writeFileSync(`${__dirname}/samples/${dir}/_actual.css`, dom.css.code); const expected = { - html: read(`test/css/samples/${dir}/expected.html`), - css: read(`test/css/samples/${dir}/expected.css`) + html: read(`${__dirname}/samples/${dir}/expected.html`), + css: read(`${__dirname}/samples/${dir}/expected.css`) }; - assert.equal(dom.css.code.replace(/svelte(-ref)?-[a-z0-9]+/g, (m, $1) => $1 ? m : 'svelte-xyz'), expected.css); + const actual_css = dom.css.code.replace(/svelte(-ref)?-[a-z0-9]+/g, (m, $1) => $1 ? m : 'svelte-xyz'); + try { + assert.equal(actual_css, expected.css); + } catch (error) { + if (shouldUpdateExpected()) { + fs.writeFileSync(`${__dirname}/samples/${dir}/expected.css`, actual_css); + console.log(`Updated ${dir}/expected.css.`); + } else { + throw error; + } + } + + let ClientComponent; + let ServerComponent; // we do this here, rather than in the expected.html !== null // block, to verify that valid code was generated - const ClientComponent = create(dom.js.code); - const ServerComponent = create(ssr.js.code); + try { + ClientComponent = create(dom.js.code); + } catch (err) { + console.log(dom.js.code); + throw err; + } + + try { + ServerComponent = create(ssr.js.code); + } catch (err) { + console.log(dom.js.code); + throw err; + } // verify that the right elements have scoping selectors if (expected.html !== null) { @@ -98,12 +126,10 @@ describe('css', () => { new ClientComponent({ target, props: config.props }); const html = target.innerHTML; - fs.writeFileSync(`test/css/samples/${dir}/_actual.html`, html); + fs.writeFileSync(`${__dirname}/samples/${dir}/_actual.html`, html); - assert.equal( - normalizeHtml(window, html.replace(/svelte(-ref)?-[a-z0-9]+/g, (m, $1) => $1 ? m : 'svelte-xyz')), - normalizeHtml(window, expected.html) - ); + const actual_html = html.replace(/svelte(-ref)?-[a-z0-9]+/g, (m, $1) => $1 ? m : 'svelte-xyz'); + assert.htmlEqual(actual_html, expected.html); window.document.head.innerHTML = ''; // remove added styles } catch (err) { @@ -113,13 +139,8 @@ describe('css', () => { // ssr try { - assert.equal( - normalizeHtml( - window, - ServerComponent.render(config.props).html.replace(/svelte(-ref)?-[a-z0-9]+/g, (m, $1) => $1 ? m : 'svelte-xyz') - ), - normalizeHtml(window, expected.html) - ); + const actual_ssr = ServerComponent.render(config.props).html.replace(/svelte(-ref)?-[a-z0-9]+/g, (m, $1) => $1 ? m : 'svelte-xyz'); + assert.htmlEqual(actual_ssr, expected.html); } catch (err) { console.log(ssr.js.code); throw err; diff --git a/test/css/samples/omit-scoping-attribute-global-children/expected.css b/test/css/samples/omit-scoping-attribute-global-children/expected.css new file mode 100644 index 0000000000..2a7a510449 --- /dev/null +++ b/test/css/samples/omit-scoping-attribute-global-children/expected.css @@ -0,0 +1 @@ +.root.svelte-xyz p{color:red} \ No newline at end of file diff --git a/test/css/samples/omit-scoping-attribute-global-children/expected.html b/test/css/samples/omit-scoping-attribute-global-children/expected.html new file mode 100644 index 0000000000..f7ee02fd83 --- /dev/null +++ b/test/css/samples/omit-scoping-attribute-global-children/expected.html @@ -0,0 +1,4 @@ +
+
+
+
\ No newline at end of file diff --git a/test/css/samples/omit-scoping-attribute-global-children/input.svelte b/test/css/samples/omit-scoping-attribute-global-children/input.svelte new file mode 100644 index 0000000000..5e52d48738 --- /dev/null +++ b/test/css/samples/omit-scoping-attribute-global-children/input.svelte @@ -0,0 +1,16 @@ + + + + +
+
+ +
+
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/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/css/samples/weird-selectors/expected.css b/test/css/samples/weird-selectors/expected.css new file mode 100644 index 0000000000..d4ead16751 --- /dev/null +++ b/test/css/samples/weird-selectors/expected.css @@ -0,0 +1 @@ +.-foo.svelte-xyz{color:red}[title='['].svelte-xyz{color:blue} \ No newline at end of file diff --git a/test/css/samples/weird-selectors/input.svelte b/test/css/samples/weird-selectors/input.svelte new file mode 100644 index 0000000000..65db029bbd --- /dev/null +++ b/test/css/samples/weird-selectors/input.svelte @@ -0,0 +1,12 @@ +
foo
+ +
bar
+ + 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..5d2847bfab 100644 --- a/test/custom-elements/index.js +++ b/test/custom-elements/index.js @@ -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/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..ff40ac5f79 100644 --- a/test/helpers.js +++ b/test/helpers.js @@ -47,17 +47,24 @@ export function tryToReadFile(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.body.innerHTML = '
'; @@ -182,58 +189,25 @@ 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 - }) - ); - - console.log( // eslint-disable-line no-console - `\n>> ${colors.cyan().bold(file)}\n${addLineNumbers(js.code)}\n<< ${colors.cyan().bold(file)}` - ); - }); -} - -const start = /\n(\t+)/; -export function deindent(strings, ...values) { - const indentation = start.exec(strings[0])[1]; - const pattern = new RegExp(`^${indentation}`, 'gm'); - - let result = strings[0].replace(start, '').replace(pattern, ''); - - let trailingIndentation = getTrailingIndentation(result); - - for (let i = 1; i < strings.length; i += 1) { - let expression = values[i - 1]; - const string = strings[i].replace(pattern, ''); - - if (Array.isArray(expression)) { - expression = expression.length ? expression.join('\n') : null; - } + try { + const { js } = compile( + fs.readFileSync(`${cwd}/${file}`, 'utf-8'), + Object.assign(options, { + filename: file + }) + ); - if (expression || expression === '') { - const value = String(expression).replace( - /\n/g, - `\n${trailingIndentation}` + console.log( // eslint-disable-line no-console + `\n>> ${colors.cyan().bold(file)}\n${addLineNumbers(js.code)}\n<< ${colors.cyan().bold(file)}` ); - result += value + string; - } else { - let c = result.length; - while (/\s/.test(result[c - 1])) c -= 1; - result = result.slice(0, c) + string; + } catch (err) { + console.log(`failed to generate output: ${err.message}`); } - - 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 shouldUpdateExpected() { + return process.argv.includes('--update'); } export function spaces(i) { @@ -241,3 +215,25 @@ export function spaces(i) { while (i--) result += ' '; return result; } + +// fake timers +const original_set_timeout = global.setTimeout; + +export function useFakeTimers() { + const callbacks = []; + + global.setTimeout = function(fn) { + callbacks.push(fn); + }; + + return { + flush() { + callbacks.forEach(fn => fn()); + callbacks.splice(0, callbacks.length); + }, + removeFakeTimers() { + callbacks.splice(0, callbacks.length); + global.setTimeout = original_set_timeout; + } + }; +} diff --git a/test/hydration/index.js b/test/hydration/index.js index 856052d69e..a0bfd6de4b 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 || {}; @@ -75,7 +77,16 @@ 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 (config.test) { config.test(assert, target, snapshot, component, window); @@ -96,7 +107,7 @@ describe('hydration', () => { }); } - fs.readdirSync('test/hydration/samples').forEach(dir => { + fs.readdirSync(`${__dirname}/samples`).forEach(dir => { runTest(dir, null); }); }); diff --git a/test/js/index.js b/test/js/index.js index 14d73d6c65..799be215f2 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,8 +15,14 @@ describe("js", () => { throw new Error("Forgot to remove `solo: true` from test"); } + dir = path.resolve(`${__dirname}/samples`, dir); + + if (!fs.existsSync(`${dir}/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 input = fs.readFileSync(`${dir}/input.svelte`, "utf-8").replace(/\s+$/, ""); @@ -34,12 +41,32 @@ describe("js", () => { const output = `${dir}/_actual.js`; fs.writeFileSync(output, actual); - const expected = fs.readFileSync(`${dir}/expected.js`, "utf-8"); + const expectedPath = `${dir}/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..3fad4fb8cc 100644 --- a/test/js/samples/action-custom-event-handler/expected.js +++ b/test/js/samples/action-custom-event-handler/expected.js @@ -5,39 +5,32 @@ import { 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; return { c() { button = element("button"); button.textContent = "foo"; }, - m(target, anchor) { insert(target, button, anchor); - foo_action = foo.call(null, button, ctx.foo_function) || {}; + foo_action = foo.call(null, button, ctx.foo_function) || ({}); }, - p(changed, ctx) { - if (typeof foo_action.update === 'function' && changed.bar) { - foo_action.update.call(null, ctx.foo_function); - } + if (is_function(foo_action.update) && changed.bar) foo_action.update.call(null, ctx.foo_function); }, - 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); + if (foo_action && is_function(foo_action.destroy)) foo_action.destroy(); } }; } @@ -47,16 +40,15 @@ function handleFoo(bar) { } function foo(node, callback) { - // 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("bar", bar = $$props.bar); }; return { bar, foo_function }; @@ -65,7 +57,7 @@ function instance($$self, $$props, $$invalidate) { 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..78fc4855c6 100644 --- a/test/js/samples/action/expected.js +++ b/test/js/samples/action/expected.js @@ -6,12 +6,14 @@ import { element, init, insert, + is_function, noop, safe_not_equal } from "svelte/internal"; function create_fragment(ctx) { - var a, link_action; + let a; + let link_action; return { c() { @@ -19,45 +21,39 @@ function create_fragment(ctx) { a.textContent = "Test"; attr(a, "href", "#"); }, - m(target, anchor) { insert(target, a, anchor); - link_action = link.call(null, a) || {}; + 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); + if (link_action && is_function(link_action.destroy)) link_action.destroy(); } }; } 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..d34e84330f 100644 --- a/test/js/samples/bind-online/expected.js +++ b/test/js/samples/bind-online/expected.js @@ -10,8 +10,7 @@ import { } from "svelte/internal"; function create_fragment(ctx) { - var dispose; - + let dispose; add_render_callback(ctx.onlinestatuschanged); return { @@ -21,12 +20,10 @@ function create_fragment(ctx) { listen(window, "offline", ctx.onlinestatuschanged) ]; }, - m: noop, p: noop, i: noop, o: noop, - d(detaching) { run_all(dispose); } @@ -37,7 +34,7 @@ function instance($$self, $$props, $$invalidate) { let online; function onlinestatuschanged() { - online = navigator.onLine; $$invalidate('online', online); + $$invalidate("online", online = navigator.onLine); } return { online, onlinestatuschanged }; @@ -46,7 +43,7 @@ function instance($$self, $$props, $$invalidate) { 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..f7bede2b4e 100644 --- a/test/js/samples/bind-open/expected.js +++ b/test/js/samples/bind-open/expected.js @@ -11,34 +11,31 @@ 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; }, - p(changed, ctx) { - if (changed.open) details.open = ctx.open; + if (changed.open) { + details.open = ctx.open; + } }, - i: noop, o: noop, - d(detaching) { - if (detaching) { - detach(details); - } - + if (detaching) detach(details); dispose(); } }; @@ -49,11 +46,11 @@ function instance($$self, $$props, $$invalidate) { function details_toggle_handler() { open = this.open; - $$invalidate('open', open); + $$invalidate("open", open); } $$self.$set = $$props => { - if ('open' in $$props) $$invalidate('open', open = $$props.open); + if ("open" in $$props) $$invalidate("open", open = $$props.open); }; return { open, details_toggle_handler }; @@ -62,7 +59,7 @@ function instance($$self, $$props, $$invalidate) { 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..ce20bc4aa7 100644 --- a/test/js/samples/bind-width-height/expected.js +++ b/test/js/samples/bind-width-height/expected.js @@ -12,7 +12,8 @@ import { } from "svelte/internal"; function create_fragment(ctx) { - var div, div_resize_listener; + let div; + let div_resize_listener; return { c() { @@ -20,39 +21,34 @@ function create_fragment(ctx) { div.textContent = "some content"; add_render_callback(() => ctx.div_resize_handler.call(div)); }, - m(target, anchor) { insert(target, div, anchor); div_resize_listener = add_resize_listener(div, ctx.div_resize_handler.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() { w = this.offsetWidth; h = this.offsetHeight; - $$invalidate('w', w); - $$invalidate('h', h); + $$invalidate("w", w); + $$invalidate("h", 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("w", w = $$props.w); + if ("h" in $$props) $$invalidate("h", h = $$props.h); }; return { w, h, div_resize_handler }; @@ -61,7 +57,7 @@ function instance($$self, $$props, $$invalidate) { 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: 0 }); } } 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..04eff699f8 --- /dev/null +++ b/test/js/samples/bindings-readonly-order/expected.js @@ -0,0 +1,83 @@ +/* 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"); + + dispose = [ + listen(input0, "change", ctx.input0_change_handler), + listen(input1, "change", ctx.input1_change_handler) + ]; + }, + m(target, anchor) { + insert(target, input0, anchor); + insert(target, t, anchor); + insert(target, input1, anchor); + }, + 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("files", files); + } + + function input1_change_handler() { + files = this.files; + $$invalidate("files", files); + } + + $$self.$set = $$props => { + if ("files" in $$props) $$invalidate("files", 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..ee2f6d0dc9 100644 --- a/test/js/samples/capture-inject-dev-only/expected.js +++ b/test/js/samples/capture-inject-dev-only/expected.js @@ -16,7 +16,11 @@ 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() { @@ -26,34 +30,26 @@ function create_fragment(ctx) { 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); }, - p(changed, ctx) { - if (changed.foo) { - set_data(t0, ctx.foo); - } + if (changed.foo) set_data(t0, ctx.foo); - if (changed.foo && (input.value !== ctx.foo)) set_input_value(input, ctx.foo); + 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,7 +60,7 @@ function instance($$self, $$props, $$invalidate) { function input_input_handler() { foo = this.value; - $$invalidate('foo', foo); + $$invalidate("foo", foo); } return { foo, input_input_handler }; @@ -73,7 +69,7 @@ function instance($$self, $$props, $$invalidate) { 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/collapses-text-around-comments/expected.js b/test/js/samples/collapses-text-around-comments/expected.js index 09b40a1e98..5fb7aaef15 100644 --- a/test/js/samples/collapses-text-around-comments/expected.js +++ b/test/js/samples/collapses-text-around-comments/expected.js @@ -15,13 +15,14 @@ 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() { @@ -29,25 +30,17 @@ function create_fragment(ctx) { t = text(ctx.foo); 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); - } + if (changed.foo) set_data(t, ctx.foo); }, - i: noop, o: noop, - d(detaching) { - if (detaching) { - detach(p); - } + if (detaching) detach(p); } }; } @@ -56,7 +49,7 @@ 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("foo", foo = $$props.foo); }; return { foo }; @@ -66,7 +59,7 @@ 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..b89ee46764 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 ctx.Nested({ 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 }; } 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..17b42a4a43 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 ctx.Nested({ 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 }; } 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..17b42a4a43 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 ctx.Nested({ 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 }; } 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..29c585744e 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: ctx.z } }); 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); - current = true; }, - p(changed, ctx) { - var bar_changes = {}; + const bar_changes = {}; if (changed.z) bar_changes.x = ctx.z; bar.$set(bar_changes); - if (changed.z && (input.value !== ctx.z)) set_input_value(input, ctx.z); + if (changed.z && input.value !== ctx.z) { + set_input_value(input, ctx.z); + } }, - 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,12 +80,11 @@ 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("z", z); } return { z, input_input_handler }; @@ -105,7 +93,7 @@ function instance($$self, $$props, $$invalidate) { 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..16d9ea9c4c 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 ctx.Nested({ 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 }; } 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..b3eedd3d6e --- /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(ctx.$foo); + }, + m(target, anchor) { + insert(target, h1, anchor); + append(h1, t); + }, + p(changed, ctx) { + if (changed.$foo) set_data(t, ctx.$foo); + }, + 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("$foo", $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..a4d7ad5c10 --- /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("$count", $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.increment; + } +} + +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..890e28f79c --- /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(ctx.$foo); + t1 = space(); + button = element("button"); + button.textContent = "reset"; + dispose = listen(button, "click", ctx.click_handler); + }, + m(target, anchor) { + insert(target, h1, anchor); + append(h1, t0); + insert(target, t1, anchor); + insert(target, button, anchor); + }, + p(changed, ctx) { + if (changed.$foo) set_data(t0, ctx.$foo); + }, + 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("$foo", $foo = $$value)), foo); + + $$self.$$.on_destroy.push(() => $$unsubscribe_foo()); + let foo = writable(0); + $$subscribe_foo(); + const click_handler = () => $$subscribe_foo($$invalidate("foo", 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..4d3954358e 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,7 +13,7 @@ function instance($$self, $$props, $$invalidate) { } $$self.$set = $$props => { - if ('x' in $$props) $$invalidate('x', x = $$props.x); + if ("x" in $$props) $$invalidate("x", x = $$props.x); }; return { x, a, b }; @@ -38,7 +22,7 @@ function instance($$self, $$props, $$invalidate) { 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: 0, b: 0 }); } get a() { 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..674be31867 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() { @@ -22,28 +24,22 @@ function create_fragment(ctx) { attr(div0, "data-foo", "bar"); attr(div1, "data-foo", ctx.bar); }, - 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); } }, - 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,7 +48,7 @@ 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("bar", bar = $$props.bar); }; return { bar }; @@ -61,7 +57,7 @@ function instance($$self, $$props, $$invalidate) { 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..b545823c57 100644 --- a/test/js/samples/debug-empty/expected.js +++ b/test/js/samples/debug-empty/expected.js @@ -18,7 +18,11 @@ 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() { @@ -30,11 +34,9 @@ function create_fragment(ctx) { 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,39 +44,39 @@ 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); - } - + if (changed.name) set_data_dev(t1, ctx.name); 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("name", name = $$props.name); }; $$self.$capture_state = () => { @@ -82,7 +84,7 @@ function instance($$self, $$props, $$invalidate) { }; $$self.$inject_state = $$props => { - if ('name' in $$props) $$invalidate('name', name = $$props.name); + if ("name" in $$props) $$invalidate("name", name = $$props.name); }; return { name }; @@ -91,12 +93,19 @@ function instance($$self, $$props, $$invalidate) { 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)) { + const props = options.props || ({}); + + if (ctx.name === 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..448fc82176 100644 --- a/test/js/samples/debug-foo-bar-baz-things/expected.js +++ b/test/js/samples/debug-foo-bar-baz-things/expected.js @@ -26,7 +26,10 @@ function get_each_context(ctx, list, i) { // (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 = ctx.thing.name + ""; + let t0; + let t1; const block = { c: function create() { @@ -39,19 +42,16 @@ function create_each_block(ctx) { 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.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; @@ -59,23 +59,29 @@ function create_each_block(ctx) { 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 t0; + let p; + let t1; + let t2; let each_value = ctx.things; - let each_blocks = []; for (let i = 0; i < each_value.length; i += 1) { @@ -94,11 +100,9 @@ function create_fragment(ctx) { t2 = text(ctx.foo); 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,12 +113,11 @@ function create_fragment(ctx) { append_dev(p, t1); append_dev(p, t2); }, - p: function update(changed, ctx) { if (changed.things) { each_value = ctx.things; - let i; + for (i = 0; i < each_value.length; i += 1) { const child_ctx = get_each_context(ctx, each_value, i); @@ -130,43 +133,48 @@ 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 (changed.foo) set_data_dev(t2, ctx.foo); }, - 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("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); }; $$self.$capture_state = () => { @@ -174,10 +182,10 @@ function instance($$self, $$props, $$invalidate) { }; $$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("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); }; return { things, foo, bar, baz }; @@ -186,21 +194,31 @@ function instance($$self, $$props, $$invalidate) { 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: 0, bar: 0, baz: 0 }); + + 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)) { + const props = options.props || ({}); + + if (ctx.things === undefined && !("things" in props)) { console.warn(" was created without expected prop 'things'"); } - if (ctx.foo === undefined && !('foo' in props)) { + + if (ctx.foo === undefined && !("foo" in props)) { console.warn(" was created without expected prop 'foo'"); } - if (ctx.bar === undefined && !('bar' in props)) { + + if (ctx.bar === undefined && !("bar" in props)) { console.warn(" was created without expected prop 'bar'"); } - if (ctx.baz === undefined && !('baz' in props)) { + + if (ctx.baz === 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..8abfd1bae1 100644 --- a/test/js/samples/debug-foo/expected.js +++ b/test/js/samples/debug-foo/expected.js @@ -26,7 +26,10 @@ function get_each_context(ctx, list, i) { // (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 = ctx.thing.name + ""; + let t0; + let t1; const block = { c: function create() { @@ -39,19 +42,16 @@ function create_each_block(ctx) { 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(changed, ctx) { - if ((changed.things) && t0_value !== (t0_value = ctx.thing.name + "")) { - set_data_dev(t0, t0_value); - } + if (changed.things && t0_value !== (t0_value = ctx.thing.name + "")) set_data_dev(t0, t0_value); if (changed.foo) { const { foo } = ctx; @@ -59,23 +59,29 @@ function create_each_block(ctx) { 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 t0; + let p; + let t1; + let t2; let each_value = ctx.things; - let each_blocks = []; for (let i = 0; i < each_value.length; i += 1) { @@ -94,11 +100,9 @@ function create_fragment(ctx) { t2 = text(ctx.foo); 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,12 +113,11 @@ function create_fragment(ctx) { append_dev(p, t1); append_dev(p, t2); }, - p: function update(changed, ctx) { if (changed.things) { each_value = ctx.things; - let i; + for (i = 0; i < each_value.length; i += 1) { const child_ctx = get_each_context(ctx, each_value, i); @@ -130,41 +133,44 @@ 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 (changed.foo) set_data_dev(t2, ctx.foo); }, - 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("things", things = $$props.things); + if ("foo" in $$props) $$invalidate("foo", foo = $$props.foo); }; $$self.$capture_state = () => { @@ -172,8 +178,8 @@ function instance($$self, $$props, $$invalidate) { }; $$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("things", things = $$props.things); + if ("foo" in $$props) $$invalidate("foo", foo = $$props.foo); }; return { things, foo }; @@ -182,15 +188,23 @@ function instance($$self, $$props, $$invalidate) { 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: 0 }); + + 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)) { + const props = options.props || ({}); + + if (ctx.things === undefined && !("things" in props)) { console.warn(" was created without expected prop 'things'"); } - if (ctx.foo === undefined && !('foo' in props)) { + + if (ctx.foo === 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..7ab1d3348e 100644 --- a/test/js/samples/debug-hoisted/expected.js +++ b/test/js/samples/debug-hoisted/expected.js @@ -18,13 +18,10 @@ function create_fragment(ctx) { 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; @@ -32,12 +29,19 @@ function create_fragment(ctx) { 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; } @@ -51,8 +55,8 @@ function instance($$self) { }; $$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("obj", obj = $$props.obj); + if ("kobzol" in $$props) $$invalidate("kobzol", kobzol = $$props.kobzol); }; return { obj }; @@ -61,8 +65,14 @@ function instance($$self) { 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..903bdb83b6 --- /dev/null +++ b/test/js/samples/debug-no-dependencies/expected.js @@ -0,0 +1,148 @@ +/* generated by Svelte vX.Y.Z */ +import { + SvelteComponentDev, + destroy_each, + detach_dev, + dispatch_dev, + empty, + init, + insert_dev, + noop, + safe_not_equal, + space, + text +} from "svelte/internal"; + +const file = undefined; + +function get_each_context(ctx, list, i) { + const child_ctx = Object.create(ctx); + child_ctx.thing = list[i]; + child_ctx.index = i; + return child_ctx; +} + +// (4:0) {#each things as thing, index} +function create_each_block(ctx) { + let t0; + let t1_value = ctx.thing + ""; + let t1; + + const block = { + c: function create() { + { + const { index } = ctx; + 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; + 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(changed, ctx) { + if (changed.things) { + each_value = things; + 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); + } 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..54448a91b4 100644 --- a/test/js/samples/deconflict-builtins/expected.js +++ b/test/js/samples/deconflict-builtins/expected.js @@ -22,38 +22,31 @@ function get_each_context(ctx, list, i) { // (5:0) {#each createElement as node} function create_each_block(ctx) { - var span, t_value = ctx.node + "", t; + let span; + let t_value = ctx.node + ""; + 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); - } + if (changed.createElement && t_value !== (t_value = ctx.node + "")) 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_1_anchor; let each_value = ctx.createElement; - 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,12 +68,11 @@ function create_fragment(ctx) { insert(target, each_1_anchor, anchor); }, - p(changed, ctx) { if (changed.createElement) { each_value = ctx.createElement; - let i; + for (i = 0; i < each_value.length; i += 1) { const child_ctx = get_each_context(ctx, each_value, i); @@ -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,7 +105,7 @@ 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("createElement", createElement = $$props.createElement); }; return { createElement }; @@ -127,7 +114,7 @@ function instance($$self, $$props, $$invalidate) { 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..6bd0c596b9 100644 --- a/test/js/samples/deconflict-globals/expected.js +++ b/test/js/samples/deconflict-globals/expected.js @@ -1,32 +1,17 @@ /* 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("foo", foo = $$props.foo); }; return { foo }; @@ -35,7 +20,7 @@ function instance($$self, $$props, $$invalidate) { 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..5da2b4aead 100644 --- a/test/js/samples/dev-warning-missing-data-computed/expected.js +++ b/test/js/samples/dev-warning-missing-data-computed/expected.js @@ -18,7 +18,11 @@ 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, ctx.foo) + ""; + let t0; + let t1; + let t2; const block = { c: function create() { @@ -28,53 +32,48 @@ function create_fragment(ctx) { t2 = text(ctx.bar); 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); - } + 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); }, - 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("foo", foo = $$props.foo); }; $$self.$capture_state = () => { @@ -82,12 +81,14 @@ function instance($$self, $$props, $$invalidate) { }; $$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("foo", foo = $$props.foo); + if ("bar" in $$props) $$invalidate("bar", bar = $$props.bar); }; - $$self.$$.update = ($$dirty = { foo: 1 }) => { - if ($$dirty.foo) { $$invalidate('bar', bar = foo * 2); } + $$self.$$.update = (changed = { foo: 1 }) => { + if (changed.foo) { + $: $$invalidate("bar", bar = foo * 2); + } }; return { foo, bar }; @@ -96,12 +97,19 @@ function instance($$self, $$props, $$invalidate) { 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)) { + const props = options.props || ({}); + + if (ctx.foo === 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..98f638dfcf 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); }, - 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..3804cab6bb 100644 --- a/test/js/samples/each-block-array-literal/expected.js +++ b/test/js/samples/each-block-array-literal/expected.js @@ -22,38 +22,31 @@ function get_each_context(ctx, list, i) { // (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 = ctx.num + ""; + 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); - } + if ((changed.a || changed.b || changed.c || changed.d || changed.e) && t_value !== (t_value = ctx.num + "")) 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_1_anchor; let each_value = [ctx.a, ctx.b, ctx.c, ctx.d, ctx.e]; - 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,13 +68,12 @@ 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]; - 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]) { @@ -99,29 +90,28 @@ 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("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); }; return { a, b, c, d, e }; @@ -130,7 +120,7 @@ function instance($$self, $$props, $$invalidate) { 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: 0, c: 0, d: 0, e: 0 }); } } diff --git a/test/js/samples/each-block-changed-check/expected.js b/test/js/samples/each-block-changed-check/expected.js index 0601c31334..a2735ae9c4 100644 --- a/test/js/samples/each-block-changed-check/expected.js +++ b/test/js/samples/each-block-changed-check/expected.js @@ -25,7 +25,20 @@ function get_each_context(ctx, list, i) { // (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 = ctx.comment.author + ""; + let t2; + let t3; + let t4_value = ctx.elapsed(ctx.comment.time, ctx.time) + ""; + let t4; + let t5; + let t6; + let html_tag; + let raw_value = ctx.comment.html + ""; return { c() { @@ -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); - } + 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); }, - d(detaching) { - if (detaching) { - detach(div); - } + if (detaching) detach(div); } }; } function create_fragment(ctx) { - var t0, p, t1; - + let t0; + let p; + let t1; let each_value = ctx.comments; - let each_blocks = []; for (let i = 0; i < each_value.length; i += 1) { @@ -101,7 +101,6 @@ function create_fragment(ctx) { p = element("p"); t1 = text(ctx.foo); }, - m(target, anchor) { for (let i = 0; i < each_blocks.length; i += 1) { each_blocks[i].m(target, anchor); @@ -111,12 +110,11 @@ 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; - let i; + for (i = 0; i < each_value.length; i += 1) { const child_ctx = get_each_context(ctx, each_value, i); @@ -132,36 +130,33 @@ 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 (changed.foo) set_data(t1, ctx.foo); }, - 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("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); }; return { comments, elapsed, time, foo }; @@ -170,7 +165,7 @@ function instance($$self, $$props, $$invalidate) { 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: 0, time: 0, foo: 0 }); } } diff --git a/test/js/samples/each-block-keyed-animated/expected.js b/test/js/samples/each-block-keyed-animated/expected.js index 25aa1e5c5d..e3661764b1 100644 --- a/test/js/samples/each-block-keyed-animated/expected.js +++ b/test/js/samples/each-block-keyed-animated/expected.js @@ -25,57 +25,49 @@ function get_each_context(ctx, list, i) { // (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 = ctx.thing.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); - } + if (changed.things && t_value !== (t_value = ctx.thing.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_blocks = []; + let each_1_lookup = new Map(); + let each_1_anchor; let each_value = ctx.things; - const get_key = ctx => ctx.thing.id; for (let i = 0; i < each_value.length; i += 1) { @@ -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,20 @@ 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(); }, - 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,7 +127,7 @@ 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("things", things = $$props.things); }; return { things }; @@ -150,7 +136,7 @@ function instance($$self, $$props, $$invalidate) { 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..beb5a613bc 100644 --- a/test/js/samples/each-block-keyed/expected.js +++ b/test/js/samples/each-block-keyed/expected.js @@ -23,43 +23,36 @@ function get_each_context(ctx, list, i) { // (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 = ctx.thing.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); - } + if (changed.things && t_value !== (t_value = ctx.thing.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_blocks = []; + let each_1_lookup = new Map(); + let each_1_anchor; let each_value = ctx.things; - const get_key = ctx => ctx.thing.id; for (let i = 0; i < each_value.length; i += 1) { @@ -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,18 @@ 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); }, - 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,7 +96,7 @@ 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("things", things = $$props.things); }; return { things }; @@ -118,7 +105,7 @@ function instance($$self, $$props, $$invalidate) { 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..bd5a9fb7ef --- /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..515d7e36a9 --- /dev/null +++ b/test/js/samples/event-handler-dynamic/expected.js @@ -0,0 +1,108 @@ +/* generated by Svelte vX.Y.Z */ +import { + SvelteComponent, + append, + detach, + element, + init, + insert, + 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(ctx.number); + t5 = space(); + button2 = element("button"); + button2.textContent = "click"; + + dispose = [ + listen(button0, "click", ctx.updateHandler1), + listen(button1, "click", ctx.updateHandler2), + listen(button2, "click", function () { + ctx.clickHandler.apply(this, arguments); + }) + ]; + }, + 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); + }, + p(changed, new_ctx) { + ctx = new_ctx; + if (changed.number) set_data(t4, ctx.number); + }, + 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("clickHandler", clickHandler = () => $$invalidate("number", number = 1)); + } + + function updateHandler2() { + $$invalidate("clickHandler", clickHandler = () => $$invalidate("number", 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..6f04e67808 100644 --- a/test/js/samples/event-handler-no-passive/expected.js +++ b/test/js/samples/event-handler-no-passive/expected.js @@ -12,7 +12,8 @@ import { } from "svelte/internal"; function create_fragment(ctx) { - var a, dispose; + let a; + let dispose; return { c() { @@ -21,31 +22,25 @@ function create_fragment(ctx) { attr(a, "href", "https://example.com"); dispose = listen(a, "touchstart", touchstart_handler); }, - m(target, anchor) { insert(target, a, anchor); }, - 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..3f324bb76d 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,6 +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 }), @@ -36,7 +43,6 @@ function create_fragment(ctx) { listen(div, "touchstart", handleTouchstart, { passive: true }) ]; }, - m(target, anchor) { insert(target, div, anchor); append(div, button0); @@ -45,33 +51,28 @@ function create_fragment(ctx) { append(div, t3); append(div, button2); }, - 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..badae4a2c0 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 = ctx.item.divider && ctx.item.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] - } - + 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..b057041e88 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; 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(null, ctx); + 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))) { 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,7 +89,7 @@ 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("foo", foo = $$props.foo); }; return { foo }; @@ -113,7 +98,7 @@ function instance($$self, $$props, $$invalidate) { 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..fd2185b86d 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 = ctx.foo && 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) { 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,7 +67,7 @@ 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("foo", foo = $$props.foo); }; return { foo }; @@ -87,7 +76,7 @@ function instance($$self, $$props, $$invalidate) { 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..636a4f19bb 100644 --- a/test/js/samples/inline-style-optimized-multiple/expected.js +++ b/test/js/samples/inline-style-optimized-multiple/expected.js @@ -11,7 +11,7 @@ import { } from "svelte/internal"; function create_fragment(ctx) { - var div; + let div; return { c() { @@ -19,11 +19,9 @@ function create_fragment(ctx) { set_style(div, "color", ctx.color); set_style(div, "transform", "translate(" + ctx.x + "px," + ctx.y + "px)"); }, - m(target, anchor) { insert(target, div, anchor); }, - p(changed, ctx) { if (changed.color) { set_style(div, "color", ctx.color); @@ -33,25 +31,23 @@ function create_fragment(ctx) { set_style(div, "transform", "translate(" + ctx.x + "px," + ctx.y + "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("color", color = $$props.color); + if ("x" in $$props) $$invalidate("x", x = $$props.x); + if ("y" in $$props) $$invalidate("y", y = $$props.y); }; return { color, x, y }; @@ -60,7 +56,7 @@ function instance($$self, $$props, $$invalidate) { 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: 0, y: 0 }); } } diff --git a/test/js/samples/inline-style-optimized-url/expected.js b/test/js/samples/inline-style-optimized-url/expected.js index 8dfc48447d..53a9434369 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 + ")"); }, - m(target, anchor) { insert(target, div, anchor); }, - p(changed, ctx) { if (changed.data) { set_style(div, "background", "url(data:image/png;base64," + ctx.data + ")"); } }, - i: noop, o: noop, - d(detaching) { - if (detaching) { - detach(div); - } + if (detaching) detach(div); } }; } @@ -44,7 +38,7 @@ 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("data", data = $$props.data); }; return { data }; @@ -53,7 +47,7 @@ function instance($$self, $$props, $$invalidate) { 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..95079a63fe 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); }, - m(target, anchor) { insert(target, div, anchor); }, - p(changed, ctx) { if (changed.color) { set_style(div, "color", ctx.color); } }, - i: noop, o: noop, - d(detaching) { - if (detaching) { - detach(div); - } + if (detaching) detach(div); } }; } @@ -44,7 +38,7 @@ 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("color", color = $$props.color); }; return { color }; @@ -53,7 +47,7 @@ function instance($$self, $$props, $$invalidate) { 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..11eaddbdf7 100644 --- a/test/js/samples/inline-style-unoptimized/expected.js +++ b/test/js/samples/inline-style-unoptimized/expected.js @@ -12,7 +12,10 @@ 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() { @@ -20,45 +23,41 @@ function create_fragment(ctx) { t = space(); div1 = element("div"); attr(div0, "style", ctx.style); - attr(div1, "style", div1_style_value = "" + ctx.key + ": " + ctx.value); + attr(div1, "style", div1_style_value = "" + (ctx.key + ": " + ctx.value)); }, - 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); } - if ((changed.key || changed.value) && div1_style_value !== (div1_style_value = "" + ctx.key + ": " + ctx.value)) { + if ((changed.key || changed.value) && div1_style_value !== (div1_style_value = "" + (ctx.key + ": " + ctx.value))) { 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("style", style = $$props.style); + if ("key" in $$props) $$invalidate("key", key = $$props.key); + if ("value" in $$props) $$invalidate("value", value = $$props.value); }; return { style, key, value }; @@ -67,7 +66,7 @@ function instance($$self, $$props, $$invalidate) { 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: 0, value: 0 }); } } 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..a190d6cf72 100644 --- a/test/js/samples/input-files/expected.js +++ b/test/js/samples/input-files/expected.js @@ -12,7 +12,8 @@ import { } from "svelte/internal"; function create_fragment(ctx) { - var input, dispose; + let input; + let dispose; return { c() { @@ -21,20 +22,14 @@ function create_fragment(ctx) { input.multiple = true; dispose = listen(input, "change", ctx.input_change_handler); }, - m(target, anchor) { insert(target, input, anchor); }, - p: noop, i: noop, o: noop, - d(detaching) { - if (detaching) { - detach(input); - } - + if (detaching) detach(input); dispose(); } }; @@ -45,11 +40,11 @@ function instance($$self, $$props, $$invalidate) { function input_change_handler() { files = this.files; - $$invalidate('files', files); + $$invalidate("files", files); } $$self.$set = $$props => { - if ('files' in $$props) $$invalidate('files', files = $$props.files); + if ("files" in $$props) $$invalidate("files", files = $$props.files); }; return { files, input_change_handler }; @@ -58,7 +53,7 @@ function instance($$self, $$props, $$invalidate) { 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..85bc9dfcef 100644 --- a/test/js/samples/input-no-initial-value/expected.js +++ b/test/js/samples/input-no-initial-value/expected.js @@ -16,13 +16,17 @@ 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"); @@ -33,29 +37,22 @@ function create_fragment(ctx) { listen(form, "submit", ctx.handleSubmit) ]; }, - m(target, anchor) { insert(target, form, anchor); append(form, input); - set_input_value(input, ctx.test); - - append(form, t); + append(form, t0); append(form, button); }, - p(changed, ctx) { - if (changed.test && (input.value !== ctx.test)) set_input_value(input, ctx.test); + if (changed.test && input.value !== ctx.test) { + set_input_value(input, ctx.test); + } }, - i: noop, o: noop, - d(detaching) { - if (detaching) { - detach(form); - } - + if (detaching) detach(form); run_all(dispose); } }; @@ -66,12 +63,12 @@ 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("test", test); } return { test, handleSubmit, input_input_handler }; @@ -80,7 +77,7 @@ function instance($$self, $$props, $$invalidate) { 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..2ea13df038 100644 --- a/test/js/samples/input-range/expected.js +++ b/test/js/samples/input-range/expected.js @@ -15,7 +15,8 @@ import { } from "svelte/internal"; function create_fragment(ctx) { - var input, dispose; + let input; + let dispose; return { c() { @@ -27,25 +28,19 @@ function create_fragment(ctx) { listen(input, "input", ctx.input_change_input_handler) ]; }, - m(target, anchor) { insert(target, input, anchor); - set_input_value(input, ctx.value); }, - p(changed, ctx) { - if (changed.value) set_input_value(input, ctx.value); + if (changed.value) { + set_input_value(input, ctx.value); + } }, - i: noop, o: noop, - d(detaching) { - if (detaching) { - detach(input); - } - + if (detaching) detach(input); run_all(dispose); } }; @@ -56,11 +51,11 @@ function instance($$self, $$props, $$invalidate) { function input_change_input_handler() { value = to_number(this.value); - $$invalidate('value', value); + $$invalidate("value", value); } $$self.$set = $$props => { - if ('value' in $$props) $$invalidate('value', value = $$props.value); + if ("value" in $$props) $$invalidate("value", value = $$props.value); }; return { value, input_change_input_handler }; @@ -69,7 +64,7 @@ function instance($$self, $$props, $$invalidate) { 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-without-blowback-guard/expected.js b/test/js/samples/input-without-blowback-guard/expected.js index d97326fcea..eacdbece83 100644 --- a/test/js/samples/input-without-blowback-guard/expected.js +++ b/test/js/samples/input-without-blowback-guard/expected.js @@ -12,7 +12,8 @@ import { } from "svelte/internal"; function create_fragment(ctx) { - var input, dispose; + let input; + let dispose; return { c() { @@ -20,25 +21,19 @@ function create_fragment(ctx) { attr(input, "type", "checkbox"); dispose = listen(input, "change", ctx.input_change_handler); }, - m(target, anchor) { insert(target, input, anchor); - input.checked = ctx.foo; }, - p(changed, ctx) { - if (changed.foo) input.checked = ctx.foo; + if (changed.foo) { + input.checked = ctx.foo; + } }, - i: noop, o: noop, - d(detaching) { - if (detaching) { - detach(input); - } - + if (detaching) detach(input); dispose(); } }; @@ -49,11 +44,11 @@ function instance($$self, $$props, $$invalidate) { function input_change_handler() { foo = this.checked; - $$invalidate('foo', foo); + $$invalidate("foo", foo); } $$self.$set = $$props => { - if ('foo' in $$props) $$invalidate('foo', foo = $$props.foo); + if ("foo" in $$props) $$invalidate("foo", foo = $$props.foo); }; return { foo, input_change_handler }; @@ -62,7 +57,7 @@ function instance($$self, $$props, $$invalidate) { 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..4b0574b79d 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() { @@ -27,7 +32,6 @@ function create_fragment(ctx) { t3 = text(ctx.x); dispose = listen(button, "click", ctx.foo); }, - m(target, anchor) { insert(target, button, anchor); insert(target, t1, anchor); @@ -35,23 +39,15 @@ function create_fragment(ctx) { append(p, t2); append(p, t3); }, - p(changed, ctx) { - if (changed.x) { - set_data(t3, ctx.x); - } + if (changed.x) set_data(t3, ctx.x); }, - 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,7 +57,7 @@ function instance($$self, $$props, $$invalidate) { let x = 0; function foo() { - if (true) $$invalidate('x', x += 1); + if (true) $$invalidate("x", x += 1); } return { x, foo }; @@ -70,7 +66,7 @@ function instance($$self, $$props, $$invalidate) { 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-x-equals-x/expected.js b/test/js/samples/instrumentation-script-x-equals-x/expected.js index 0d7740b55d..8a3fa9366a 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 = ctx.things.length + ""; + let t3; + let dispose; return { c() { @@ -27,7 +33,6 @@ function create_fragment(ctx) { t3 = text(t3_value); dispose = listen(button, "click", ctx.foo); }, - m(target, anchor) { insert(target, button, anchor); insert(target, t1, anchor); @@ -35,23 +40,15 @@ function create_fragment(ctx) { append(p, t2); append(p, t3); }, - p(changed, ctx) { - if ((changed.things) && t3_value !== (t3_value = ctx.things.length + "")) { - set_data(t3, t3_value); - } + if (changed.things && t3_value !== (t3_value = ctx.things.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,7 +59,7 @@ function instance($$self, $$props, $$invalidate) { function foo() { things.push(1); - $$invalidate('things', things); + $$invalidate("things", things); } return { things, foo }; @@ -71,7 +68,7 @@ function instance($$self, $$props, $$invalidate) { 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..e2d8c4466f 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() { @@ -27,7 +32,6 @@ function create_fragment(ctx) { t3 = text(ctx.x); dispose = listen(button, "click", ctx.click_handler); }, - m(target, anchor) { insert(target, button, anchor); insert(target, t1, anchor); @@ -35,23 +39,15 @@ function create_fragment(ctx) { append(p, t2); append(p, t3); }, - p(changed, ctx) { - if (changed.x) { - set_data(t3, ctx.x); - } + if (changed.x) set_data(t3, ctx.x); }, - 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,7 +57,7 @@ function instance($$self, $$props, $$invalidate) { let x = 0; const click_handler = () => { - if (true) $$invalidate('x', x += 1); + if (true) $$invalidate("x", x += 1); }; return { x, click_handler }; @@ -70,7 +66,7 @@ function instance($$self, $$props, $$invalidate) { 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..eefda55f31 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 = ctx.things.length + ""; + let t3; + let dispose; return { c() { @@ -27,7 +33,6 @@ function create_fragment(ctx) { t3 = text(t3_value); dispose = listen(button, "click", ctx.click_handler); }, - m(target, anchor) { insert(target, button, anchor); insert(target, t1, anchor); @@ -35,23 +40,15 @@ function create_fragment(ctx) { append(p, t2); append(p, t3); }, - p(changed, ctx) { - if ((changed.things) && t3_value !== (t3_value = ctx.things.length + "")) { - set_data(t3, t3_value); - } + if (changed.things && t3_value !== (t3_value = ctx.things.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,7 +57,10 @@ 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("things", things); + }; return { things, click_handler }; } @@ -68,7 +68,7 @@ function instance($$self, $$props, $$invalidate) { 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..59d9a7e43b --- /dev/null +++ b/test/js/samples/loop-protect/expected.js @@ -0,0 +1,109 @@ +/* generated by Svelte vX.Y.Z */ +import { + SvelteComponentDev, + dispatch_dev, + init, + loop_guard, + noop, + safe_not_equal +} from "svelte/internal"; + +const file = undefined; + +function create_fragment(ctx) { + const block = { + c: noop, + l: function claim(nodes) { + throw new Error("options.hydrate only works if the component was compiled with the `hydratable: true` option"); + }, + m: noop, + p: noop, + i: noop, + o: noop, + d: noop + }; + + dispatch_dev("SvelteRegisterBlock", { + block, + id: create_fragment.name, + type: "component", + source: "", + ctx + }); + + return block; +} + +function instance($$self) { + const guard = loop_guard(100); + + while (true) { + foo(); + guard(); + } + + const guard_1 = loop_guard(100); + + for (; ; ) { + foo(); + guard_1(); + } + + const guard_2 = loop_guard(100); + + while (true) { + foo(); + guard_2(); + } + + const guard_4 = loop_guard(100); + + do { + foo(); + guard_4(); + } while (true); + + $$self.$capture_state = () => { + return {}; + }; + + $$self.$inject_state = $$props => { + + }; + + $: { + const guard_3 = loop_guard(100); + + while (true) { + foo(); + guard_3(); + } + } + + $: { + const guard_5 = loop_guard(100); + + do { + foo(); + guard_5(); + } while (true); + } + + return {}; +} + +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; \ No newline at end of file diff --git a/test/js/samples/loop-protect/input.svelte b/test/js/samples/loop-protect/input.svelte new file mode 100644 index 0000000000..c39ea75f72 --- /dev/null +++ b/test/js/samples/loop-protect/input.svelte @@ -0,0 +1,12 @@ + \ 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..0538f07055 100644 --- a/test/js/samples/media-bindings/expected.js +++ b/test/js/samples/media-bindings/expected.js @@ -15,24 +15,32 @@ 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); } return { c() { audio = element("audio"); - if (ctx.played === void 0 || ctx.currentTime === void 0) add_render_callback(audio_timeupdate_handler); + if (ctx.played === void 0 || ctx.currentTime === void 0 || ctx.ended === 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 (ctx.seeking === void 0) add_render_callback(() => ctx.audio_seeking_seeked_handler.call(audio)); + if (ctx.ended === void 0) add_render_callback(() => ctx.audio_ended_handler.call(audio)); dispose = [ listen(audio, "timeupdate", audio_timeupdate_handler), @@ -42,90 +50,125 @@ function create_fragment(ctx) { 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, "ratechange", ctx.audio_ratechange_handler), + listen(audio, "seeking", ctx.audio_seeking_seeked_handler), + listen(audio, "seeked", ctx.audio_seeking_seeked_handler), + listen(audio, "ended", ctx.audio_ended_handler) ]; }, - m(target, anchor) { insert(target, audio, anchor); - audio.volume = ctx.volume; + if (!isNaN(ctx.volume)) { + audio.volume = ctx.volume; + } - audio.playbackRate = ctx.playbackRate; + if (!isNaN(ctx.playbackRate)) { + audio.playbackRate = ctx.playbackRate; + } }, - 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; + 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; }, - 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_timeupdate_handler() { played = time_ranges_to_array(this.played); currentTime = this.currentTime; - $$invalidate('played', played); - $$invalidate('currentTime', currentTime); + ended = this.ended; + $$invalidate("played", played); + $$invalidate("currentTime", currentTime); + $$invalidate("ended", ended); } function audio_durationchange_handler() { duration = this.duration; - $$invalidate('duration', duration); + $$invalidate("duration", duration); } function audio_play_pause_handler() { paused = this.paused; - $$invalidate('paused', paused); + $$invalidate("paused", paused); } function audio_progress_handler() { buffered = time_ranges_to_array(this.buffered); - $$invalidate('buffered', 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("buffered", buffered); + $$invalidate("seekable", seekable); } function audio_volumechange_handler() { volume = this.volume; - $$invalidate('volume', volume); + $$invalidate("volume", volume); } function audio_ratechange_handler() { playbackRate = this.playbackRate; - $$invalidate('playbackRate', playbackRate); + $$invalidate("playbackRate", playbackRate); + } + + function audio_seeking_seeked_handler() { + seeking = this.seeking; + $$invalidate("seeking", seeking); + } + + function audio_ended_handler() { + ended = this.ended; + $$invalidate("ended", 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("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 ("seeking" in $$props) $$invalidate("seeking", seeking = $$props.seeking); + if ("ended" in $$props) $$invalidate("ended", ended = $$props.ended); }; return { @@ -137,20 +180,36 @@ function instance($$self, $$props, $$invalidate) { paused, volume, playbackRate, + seeking, + ended, 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: 0, + played: 0, + currentTime: 0, + duration: 0, + paused: 0, + volume: 0, + playbackRate: 0, + seeking: 0, + ended: 0 + }); } } 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; -