From 52f5005cfd2f6b88da79025829bab133ef87e3dc Mon Sep 17 00:00:00 2001 From: Mlocik97 Date: Tue, 19 Jul 2022 09:26:57 +0200 Subject: [PATCH 001/145] [docs] update port in "Svelte for new developers" blog. (#7697) Co-authored-by: Ben McCann <322311+benmccann@users.noreply.github.com> --- site/content/blog/2019-04-16-svelte-for-new-developers.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/content/blog/2019-04-16-svelte-for-new-developers.md b/site/content/blog/2019-04-16-svelte-for-new-developers.md index 0a01474bbd..834e042138 100644 --- a/site/content/blog/2019-04-16-svelte-for-new-developers.md +++ b/site/content/blog/2019-04-16-svelte-for-new-developers.md @@ -61,7 +61,7 @@ We're going to use the [Svelte + Vite](https://github.com/vitejs/vite/tree/main/ On the command line, navigate to where you want to create a new project, then type the following lines (you can paste the whole lot, but you'll develop better muscle memory if you get into the habit of writing each line out one at a time then running it): ```bash -npm init vite my-svelte-project -- --template svelte +npm create vite@latest my-svelte-project -- --template svelte cd my-svelte-project npm install ``` @@ -78,7 +78,7 @@ npm run dev Running the `dev` script starts a program called [Vite](https://vitejs.dev/). Vite's job is to take your application's source files, pass them to other programs (including Svelte, in our case) and convert them into the code that will actually run when you open the application in a browser. -Speaking of which, open a browser and navigate to http://localhost:3000. This is your application running on a local *web server* (hence 'localhost') on port 3000. +Speaking of which, open a browser and navigate to http://localhost:5173. This is your application running on a local *web server* (hence 'localhost') on port 5173. Try changing `src/App.svelte` and saving it. The application will update with your changes. From 91b20b9c2eedc28b3989ac5b013857c64cc22e36 Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Wed, 20 Jul 2022 00:01:08 +0800 Subject: [PATCH 002/145] [fix] error when using combinator incorrectly (#7650) * error when using combinator incorrectly * add new test case --- src/compiler/compile/compiler_errors.ts | 4 ++++ src/compiler/compile/css/Selector.ts | 12 ++++++++++++ .../css-invalid-combinator-selector-1/errors.json | 9 +++++++++ .../css-invalid-combinator-selector-1/input.svelte | 13 +++++++++++++ .../css-invalid-combinator-selector-2/errors.json | 9 +++++++++ .../css-invalid-combinator-selector-2/input.svelte | 11 +++++++++++ .../css-invalid-combinator-selector-3/errors.json | 9 +++++++++ .../css-invalid-combinator-selector-3/input.svelte | 9 +++++++++ .../css-invalid-combinator-selector-4/errors.json | 9 +++++++++ .../css-invalid-combinator-selector-4/input.svelte | 7 +++++++ 10 files changed, 92 insertions(+) create mode 100644 test/validator/samples/css-invalid-combinator-selector-1/errors.json create mode 100644 test/validator/samples/css-invalid-combinator-selector-1/input.svelte create mode 100644 test/validator/samples/css-invalid-combinator-selector-2/errors.json create mode 100644 test/validator/samples/css-invalid-combinator-selector-2/input.svelte create mode 100644 test/validator/samples/css-invalid-combinator-selector-3/errors.json create mode 100644 test/validator/samples/css-invalid-combinator-selector-3/input.svelte create mode 100644 test/validator/samples/css-invalid-combinator-selector-4/errors.json create mode 100644 test/validator/samples/css-invalid-combinator-selector-4/input.svelte diff --git a/src/compiler/compile/compiler_errors.ts b/src/compiler/compile/compiler_errors.ts index ea95c8cbec..c1a7d8bc5c 100644 --- a/src/compiler/compile/compiler_errors.ts +++ b/src/compiler/compile/compiler_errors.ts @@ -234,6 +234,10 @@ export default { code: 'css-invalid-global-selector', message: ':global(...) must contain a single selector' }, + css_invalid_selector: (selector: string) => ({ + code: 'css-invalid-selector', + message: `Invalid selector "${selector}"` + }), duplicate_animation: { code: 'duplicate-animation', message: "An element can only have one 'animate' directive" diff --git a/src/compiler/compile/css/Selector.ts b/src/compiler/compile/css/Selector.ts index b00fbc5548..d61ba1f510 100644 --- a/src/compiler/compile/css/Selector.ts +++ b/src/compiler/compile/css/Selector.ts @@ -145,6 +145,7 @@ export default class Selector { } this.validate_global_with_multiple_selectors(component); + this.validate_invalid_combinator_without_selector(component); } validate_global_with_multiple_selectors(component: Component) { @@ -163,6 +164,17 @@ export default class Selector { } } } + validate_invalid_combinator_without_selector(component: Component) { + for (let i = 0; i < this.blocks.length; i++) { + const block = this.blocks[i]; + if (block.combinator && block.selectors.length === 0) { + component.error(this.node, compiler_errors.css_invalid_selector(component.source.slice(this.node.start, this.node.end))); + } + if (!block.combinator && block.selectors.length === 0) { + component.error(this.node, compiler_errors.css_invalid_selector(component.source.slice(this.node.start, this.node.end))); + } + } + } get_amount_class_specificity_increased() { let count = 0; diff --git a/test/validator/samples/css-invalid-combinator-selector-1/errors.json b/test/validator/samples/css-invalid-combinator-selector-1/errors.json new file mode 100644 index 0000000000..b50fb678f0 --- /dev/null +++ b/test/validator/samples/css-invalid-combinator-selector-1/errors.json @@ -0,0 +1,9 @@ +[ + { + "code": "css-invalid-selector", + "message": "Invalid selector \"> span\"", + "start": { "line": 10, "column": 1, "character": 88 }, + "end": { "line": 10, "column": 7, "character": 94 }, + "pos": 88 + } +] diff --git a/test/validator/samples/css-invalid-combinator-selector-1/input.svelte b/test/validator/samples/css-invalid-combinator-selector-1/input.svelte new file mode 100644 index 0000000000..614b9d932c --- /dev/null +++ b/test/validator/samples/css-invalid-combinator-selector-1/input.svelte @@ -0,0 +1,13 @@ +

+ + diff --git a/test/validator/samples/css-invalid-combinator-selector-2/errors.json b/test/validator/samples/css-invalid-combinator-selector-2/errors.json new file mode 100644 index 0000000000..8c55da03c8 --- /dev/null +++ b/test/validator/samples/css-invalid-combinator-selector-2/errors.json @@ -0,0 +1,9 @@ +[ + { + "code": "css-invalid-selector", + "message": "Invalid selector \"+ p\"", + "start": { "line": 8, "column": 1, "character": 68 }, + "end": { "line": 8, "column": 4, "character": 71 }, + "pos": 68 + } +] diff --git a/test/validator/samples/css-invalid-combinator-selector-2/input.svelte b/test/validator/samples/css-invalid-combinator-selector-2/input.svelte new file mode 100644 index 0000000000..9cc20ce817 --- /dev/null +++ b/test/validator/samples/css-invalid-combinator-selector-2/input.svelte @@ -0,0 +1,11 @@ +

+

+ + diff --git a/test/validator/samples/css-invalid-combinator-selector-3/errors.json b/test/validator/samples/css-invalid-combinator-selector-3/errors.json new file mode 100644 index 0000000000..869cc09c95 --- /dev/null +++ b/test/validator/samples/css-invalid-combinator-selector-3/errors.json @@ -0,0 +1,9 @@ +[ + { + "code": "css-invalid-selector", + "message": "Invalid selector \"> span\"", + "start": { "line": 5, "column": 2, "character": 44 }, + "end": { "line": 5, "column": 8, "character": 50 }, + "pos": 44 + } +] diff --git a/test/validator/samples/css-invalid-combinator-selector-3/input.svelte b/test/validator/samples/css-invalid-combinator-selector-3/input.svelte new file mode 100644 index 0000000000..fdd4870921 --- /dev/null +++ b/test/validator/samples/css-invalid-combinator-selector-3/input.svelte @@ -0,0 +1,9 @@ +

+ + diff --git a/test/validator/samples/css-invalid-combinator-selector-4/errors.json b/test/validator/samples/css-invalid-combinator-selector-4/errors.json new file mode 100644 index 0000000000..239704f48e --- /dev/null +++ b/test/validator/samples/css-invalid-combinator-selector-4/errors.json @@ -0,0 +1,9 @@ +[ + { + "code": "css-invalid-selector", + "message": "Invalid selector \"p >\"", + "start": { "line": 4, "column": 1, "character": 26 }, + "end": { "line": 4, "column": 4, "character": 29 }, + "pos": 26 + } +] diff --git a/test/validator/samples/css-invalid-combinator-selector-4/input.svelte b/test/validator/samples/css-invalid-combinator-selector-4/input.svelte new file mode 100644 index 0000000000..db04318f73 --- /dev/null +++ b/test/validator/samples/css-invalid-combinator-selector-4/input.svelte @@ -0,0 +1,7 @@ +

+ + From 01ba78a6fb7d3db12c0c1bf39e2d3308972df5d3 Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Wed, 20 Jul 2022 00:02:40 +0800 Subject: [PATCH 003/145] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f85f615380..03aeeac579 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ * Add a11y warning `a11y-no-abstract-role` which checks ARIA roles must be non-abstract ARIA role ([#6241](https://github.com/sveltejs/svelte/pull/6241)) * Add a11y warning `a11y-no-interactive-element-to-noninteractive-role` which checks for noninteractive roles used on interactive elements ([#5955](https://github.com/sveltejs/svelte/pull/5955)) * Remove of empty stylesheets created from transitions ([#4801](https://github.com/sveltejs/svelte/issues/4801), [#7164](https://github.com/sveltejs/svelte/issues/7164)) +* Disallow invalid CSS selectors starting with a combinator ([#7643](https://github.com/sveltejs/svelte/issues/7643)) ## 3.49.0 From bb02a22d3e295bdd8eb8f291ab724616a106d45f Mon Sep 17 00:00:00 2001 From: Hofer Ivan Date: Mon, 25 Jul 2022 21:09:03 +0200 Subject: [PATCH 004/145] [feat] add convenience type for `ComponentEvents` (#7702) --- generate-type-definitions.js | 2 +- src/runtime/internal/dev.ts | 26 ++++++++++++++++++++++---- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/generate-type-definitions.js b/generate-type-definitions.js index 00b079eb5d..d8f6e9f826 100644 --- a/generate-type-definitions.js +++ b/generate-type-definitions.js @@ -16,7 +16,7 @@ function modify(path, modifyFn) { modify( 'types/runtime/index.d.ts', - content => content.replace('SvelteComponentTyped', 'SvelteComponentTyped, ComponentType, ComponentConstructorOptions, ComponentProps') + content => content.replace('SvelteComponentTyped', 'SvelteComponentTyped, ComponentType, ComponentConstructorOptions, ComponentProps, ComponentEvents') ); modify( 'types/compiler/index.d.ts', diff --git a/src/runtime/internal/dev.ts b/src/runtime/internal/dev.ts index 5b00e7dc5b..df40f94230 100644 --- a/src/runtime/internal/dev.ts +++ b/src/runtime/internal/dev.ts @@ -264,18 +264,18 @@ export class SvelteComponentTyped< /** * Convenience type to get the type of a Svelte component. Useful for example in combination with * dynamic components using ``. - * + * * Example: * ```html * - * + * * * * ``` @@ -292,7 +292,7 @@ export type ComponentType * import type { ComponentProps } from 'svelte'; * import Component from './Component.svelte'; - * + * * const props: ComponentProps = { foo: 'bar' }; // Errors if these aren't the correct props * * ``` @@ -301,6 +301,24 @@ export type ComponentProps = Component extend ? Props : never; +/** + * Convenience type to get the events the given component expects. Example: + * ```html + * + * + * + * ``` + */ +export type ComponentEvents = + Component extends SvelteComponentTyped ? Events : never; + export function loop_guard(timeout) { const start = Date.now(); return () => { From 5a725713f7126e300928a0850a65cf18e50384a5 Mon Sep 17 00:00:00 2001 From: Simon H <5968653+dummdidumm@users.noreply.github.com> Date: Mon, 25 Jul 2022 21:10:13 +0200 Subject: [PATCH 005/145] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 03aeeac579..c9f06c5f72 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ * Add a11y warning `a11y-no-interactive-element-to-noninteractive-role` which checks for noninteractive roles used on interactive elements ([#5955](https://github.com/sveltejs/svelte/pull/5955)) * Remove of empty stylesheets created from transitions ([#4801](https://github.com/sveltejs/svelte/issues/4801), [#7164](https://github.com/sveltejs/svelte/issues/7164)) * Disallow invalid CSS selectors starting with a combinator ([#7643](https://github.com/sveltejs/svelte/issues/7643)) +* Add `ComponentEvents` convenience type ([#7702](https://github.com/sveltejs/svelte/pull/7702)) ## 3.49.0 From 9ad416be94d0b8cf1a78f7f3714a84badbc9329f Mon Sep 17 00:00:00 2001 From: Bjorn Lu Date: Wed, 27 Jul 2022 16:56:37 +0800 Subject: [PATCH 006/145] [chore] upgrade source-map (#7729) Fixes #7728 --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 01e23422bb..dfff153e97 100644 --- a/package-lock.json +++ b/package-lock.json @@ -42,7 +42,7 @@ "periscopic": "^3.0.4", "puppeteer": "^2.0.0", "rollup": "^1.27.14", - "source-map": "^0.7.3", + "source-map": "^0.7.4", "source-map-support": "^0.5.13", "sourcemap-codec": "^1.4.8", "tiny-glob": "^0.2.6", @@ -4047,9 +4047,9 @@ } }, "node_modules/source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", "dev": true, "engines": { "node": ">= 8" @@ -7832,9 +7832,9 @@ "dev": true }, "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", "dev": true }, "source-map-support": { diff --git a/package.json b/package.json index 9bdf7b3089..4a4d5266c3 100644 --- a/package.json +++ b/package.json @@ -148,7 +148,7 @@ "periscopic": "^3.0.4", "puppeteer": "^2.0.0", "rollup": "^1.27.14", - "source-map": "^0.7.3", + "source-map": "^0.7.4", "source-map-support": "^0.5.13", "sourcemap-codec": "^1.4.8", "tiny-glob": "^0.2.6", From 5dd703fe811a94ea90080edec220d7ee9a09d219 Mon Sep 17 00:00:00 2001 From: qinmu Date: Fri, 29 Jul 2022 00:02:15 +0800 Subject: [PATCH 007/145] [fix] handle arrow function on slot inside svelte:fragment (#7667) Fixes #7485 --- .../compile/nodes/shared/Expression.ts | 2 +- .../Inner.svelte | 8 ++++++ .../Outer.svelte | 12 +++++++++ .../_config.js | 27 +++++++++++++++++++ .../main.svelte | 12 +++++++++ 5 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 test/runtime/samples/component-slot-let-inline-function/Inner.svelte create mode 100644 test/runtime/samples/component-slot-let-inline-function/Outer.svelte create mode 100644 test/runtime/samples/component-slot-let-inline-function/_config.js create mode 100644 test/runtime/samples/component-slot-let-inline-function/main.svelte diff --git a/src/compiler/compile/nodes/shared/Expression.ts b/src/compiler/compile/nodes/shared/Expression.ts index a773355e31..0603c15589 100644 --- a/src/compiler/compile/nodes/shared/Expression.ts +++ b/src/compiler/compile/nodes/shared/Expression.ts @@ -323,7 +323,7 @@ export default class Expression { const func_expression = func_declaration[0]; - if (node.type === 'InlineComponent') { + if (node.type === 'InlineComponent' || node.type === 'SlotTemplate') { // this.replace(func_expression); } else { diff --git a/test/runtime/samples/component-slot-let-inline-function/Inner.svelte b/test/runtime/samples/component-slot-let-inline-function/Inner.svelte new file mode 100644 index 0000000000..5a30e1855b --- /dev/null +++ b/test/runtime/samples/component-slot-let-inline-function/Inner.svelte @@ -0,0 +1,8 @@ + + \ No newline at end of file diff --git a/test/runtime/samples/component-slot-let-inline-function/Outer.svelte b/test/runtime/samples/component-slot-let-inline-function/Outer.svelte new file mode 100644 index 0000000000..40ed99ca63 --- /dev/null +++ b/test/runtime/samples/component-slot-let-inline-function/Outer.svelte @@ -0,0 +1,12 @@ + + + + + innerCall(a)} /> + + \ No newline at end of file diff --git a/test/runtime/samples/component-slot-let-inline-function/_config.js b/test/runtime/samples/component-slot-let-inline-function/_config.js new file mode 100644 index 0000000000..55318efaea --- /dev/null +++ b/test/runtime/samples/component-slot-let-inline-function/_config.js @@ -0,0 +1,27 @@ +let logs; +function log(value) { + logs.push(value); +} + +export default { + html: '', + props: { + a: 'a', + b: 'b', + log + }, + before_test() { + logs = []; + }, + async test({ assert, component, target, window }) { + const button = target.querySelector('button'); + await button.dispatchEvent(new window.MouseEvent('click')); + + assert.deepEqual(logs, ['a: a, b: b']); + + component.a = '1'; + component.b = '2'; + await button.dispatchEvent(new window.MouseEvent('click')); + assert.deepEqual(logs, ['a: a, b: b', 'a: 1, b: 2']); + } +}; diff --git a/test/runtime/samples/component-slot-let-inline-function/main.svelte b/test/runtime/samples/component-slot-let-inline-function/main.svelte new file mode 100644 index 0000000000..6ea417d0f2 --- /dev/null +++ b/test/runtime/samples/component-slot-let-inline-function/main.svelte @@ -0,0 +1,12 @@ + + + + + From 12cbaea9e56a6724acba9daf4d2ebf991dc7591e Mon Sep 17 00:00:00 2001 From: Simon H <5968653+dummdidumm@users.noreply.github.com> Date: Thu, 28 Jul 2022 18:03:13 +0200 Subject: [PATCH 008/145] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c9f06c5f72..43d74063e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ * Remove of empty stylesheets created from transitions ([#4801](https://github.com/sveltejs/svelte/issues/4801), [#7164](https://github.com/sveltejs/svelte/issues/7164)) * Disallow invalid CSS selectors starting with a combinator ([#7643](https://github.com/sveltejs/svelte/issues/7643)) * Add `ComponentEvents` convenience type ([#7702](https://github.com/sveltejs/svelte/pull/7702)) +* Handle arrow function on `` inside `` ([#7485](https://github.com/sveltejs/svelte/issues/7485)) ## 3.49.0 From 1198bae8351f1b9c3d9850a67617b0816f624988 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 28 Jul 2022 09:08:59 -0700 Subject: [PATCH 009/145] Bump svelte from 3.43.0 to 3.49.0 (#7689) Bumps [svelte](https://github.com/sveltejs/svelte) from 3.43.0 to 3.49.0. - [Release notes](https://github.com/sveltejs/svelte/releases) - [Changelog](https://github.com/sveltejs/svelte/blob/master/CHANGELOG.md) - [Commits](https://github.com/sveltejs/svelte/compare/v3.43.0...v3.49.0) --- updated-dependencies: - dependency-name: svelte dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index dfff153e97..0db7287a64 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4248,9 +4248,9 @@ } }, "node_modules/svelte": { - "version": "3.43.0", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.43.0.tgz", - "integrity": "sha512-T2pMPHrxXp+SM8pLLUXLQgkdo+JhTls7aqj9cD7z8wT2ccP+OrCAmtQS7h6pvMjitaZhXFNnCK582NxDpy8HSw==", + "version": "3.49.0", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.49.0.tgz", + "integrity": "sha512-+lmjic1pApJWDfPCpUUTc1m8azDqYCG1JN9YEngrx/hUyIcFJo6VZhj0A1Ai0wqoHcEIuQy+e9tk+4uDgdtsFA==", "dev": true, "peer": true, "engines": { @@ -7988,9 +7988,9 @@ "dev": true }, "svelte": { - "version": "3.43.0", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.43.0.tgz", - "integrity": "sha512-T2pMPHrxXp+SM8pLLUXLQgkdo+JhTls7aqj9cD7z8wT2ccP+OrCAmtQS7h6pvMjitaZhXFNnCK582NxDpy8HSw==", + "version": "3.49.0", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.49.0.tgz", + "integrity": "sha512-+lmjic1pApJWDfPCpUUTc1m8azDqYCG1JN9YEngrx/hUyIcFJo6VZhj0A1Ai0wqoHcEIuQy+e9tk+4uDgdtsFA==", "dev": true, "peer": true }, From 439bbf87e33e6cf22abb08689fea96fc58f9e9cb Mon Sep 17 00:00:00 2001 From: metonym Date: Mon, 1 Aug 2022 00:14:26 -0700 Subject: [PATCH 010/145] [feat] add SveltePreprocessor utility type (#7742) --- src/compiler/preprocess/types.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/compiler/preprocess/types.ts b/src/compiler/preprocess/types.ts index b1e605238d..faef6c74ed 100644 --- a/src/compiler/preprocess/types.ts +++ b/src/compiler/preprocess/types.ts @@ -40,3 +40,10 @@ export interface PreprocessorGroup { style?: Preprocessor; script?: Preprocessor; } + +export interface SveltePreprocessor< + PreprocessorType extends keyof PreprocessorGroup, + Options = any +> { + (options?: Options): Required>; +} From 7a9b8d03ee80b06b174825962c1a1cd9788635db Mon Sep 17 00:00:00 2001 From: Simon H <5968653+dummdidumm@users.noreply.github.com> Date: Mon, 1 Aug 2022 09:15:34 +0200 Subject: [PATCH 011/145] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 43d74063e4..5df9239972 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ * Remove of empty stylesheets created from transitions ([#4801](https://github.com/sveltejs/svelte/issues/4801), [#7164](https://github.com/sveltejs/svelte/issues/7164)) * Disallow invalid CSS selectors starting with a combinator ([#7643](https://github.com/sveltejs/svelte/issues/7643)) * Add `ComponentEvents` convenience type ([#7702](https://github.com/sveltejs/svelte/pull/7702)) +* Add `SveltePreprocessor` utility type ([#7742](https://github.com/sveltejs/svelte/pull/7742)) * Handle arrow function on `` inside `` ([#7485](https://github.com/sveltejs/svelte/issues/7485)) ## 3.49.0 From 474ed42b2483e24e3b9e93206994050fe71d1d97 Mon Sep 17 00:00:00 2001 From: Script Raccoon <54458975+ScriptRaccoon@users.noreply.github.com> Date: Tue, 2 Aug 2022 07:45:45 +0200 Subject: [PATCH 012/145] [fix] typo in transition docs (#7739) --- site/content/docs/02-template-syntax.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/content/docs/02-template-syntax.md b/site/content/docs/02-template-syntax.md index f2e71ecbe0..1094e25184 100644 --- a/site/content/docs/02-template-syntax.md +++ b/site/content/docs/02-template-syntax.md @@ -1006,7 +1006,7 @@ Like actions, transitions can have parameters. ```sv {#if visible}
- flies in, fades out over two seconds + fades in and out over two seconds
{/if} ``` From 8513e299ef3fb2581b21f61f7795bfd5eb582bd8 Mon Sep 17 00:00:00 2001 From: Daniel Sandoval Date: Tue, 2 Aug 2022 09:30:05 -0600 Subject: [PATCH 013/145] [docs] "What's new in Svelte" August newsletter (#7741) --- ...2-08-01-whats-new-in-svelte-august-2022.md | 119 ++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 site/content/blog/2022-08-01-whats-new-in-svelte-august-2022.md diff --git a/site/content/blog/2022-08-01-whats-new-in-svelte-august-2022.md b/site/content/blog/2022-08-01-whats-new-in-svelte-august-2022.md new file mode 100644 index 0000000000..dfea1bcdd2 --- /dev/null +++ b/site/content/blog/2022-08-01-whats-new-in-svelte-august-2022.md @@ -0,0 +1,119 @@ +--- +title: "What's new in Svelte: August 2022" +description: "Changes to SvelteKit's `load` before 1.0 plus support for Vite 3 and `vite.config.js`!" +author: Daniel Sandoval +authorURL: https://desandoval.net +--- + +There's a lot to cover this month... big changes are coming to SvelteKit's design before 1.0 can be completed. If you haven't already, check out Rich's Discussion, [Fixing `load`, and tightening up SvelteKit's design before 1.0 #5748](https://github.com/sveltejs/kit/discussions/5748). + +Also, [@dummdidumm](https://github.com/dummdidumm) (Simon H) [has joined Vercel to work on Svelte full-time](https://twitter.com/dummdidumm_/status/1549041206348222464) and [@tcc-sejohnson](https://github.com/tcc-sejohnson) has joined the group of SvelteKit maintainers! We're super excited to have additional maintainers now dedicated to working on Svelte and SvelteKit and have already been noticing their impact. July was the third largest month for SvelteKit changes since its inception! + +Now onto the rest of the updates... + +## What's new in SvelteKit +- Dynamically imported styles are now included during SSR ([#5138](https://github.com/sveltejs/kit/pull/5138)) +- Improvements to routes and prop updates to prevent unnecessary rerendering ([#5654](https://github.com/sveltejs/kit/pull/5654), [#5671](https://github.com/sveltejs/kit/pull/5671)) +- Lots of improvements to error handling ([#4665](https://github.com/sveltejs/kit/pull/4665), [#5622](https://github.com/sveltejs/kit/pull/5622), [#5619](https://github.com/sveltejs/kit/pull/5619), [#5616](https://github.com/sveltejs/kit/pull/5616)) +- Custom Vite modes are now respected in SSR builds ([#5602](https://github.com/sveltejs/kit/pull/5602)) +- Custom Vite config locations are now supported ([#5705](https://github.com/sveltejs/kit/pull/5705)) +- Private environment variables (aka "secrets") are now much more secure. Now if you accidentally import them to client-side code, you'll see an error ([#5663](https://github.com/sveltejs/kit/pull/5663), [Docs](https://kit.svelte.dev/docs/configuration#env)) +- Vercel's v3 build output API is now being used in `adapter-vercel` ([#5514](https://github.com/sveltejs/kit/pull/5514)) +- `vite-plugin-svelte` has reached 1.0 and now supports Vite 3. You'll notice new default ports for `dev` (port 5173) and `preview` (port 4173) ([#5005](https://github.com/sveltejs/kit/pull/5005), [vite-plugin-svelte CHANGELOG](https://github.com/sveltejs/vite-plugin-svelte/blob/main/packages/vite-plugin-svelte/CHANGELOG.md)) + +**Breaking changes:** +- `mode`, `prod` and `server` are no longer available in `$app/env` ([#5602](https://github.com/sveltejs/kit/pull/5602)) +- `svelte-kit` CLI commands are now run using the `vite` command and `vite.config.js` is required. This will allow first-class support with other projects in the Vite ecosystem like Vitest and Storybook ([#5332](https://github.com/sveltejs/kit/pull/5332), [Docs](https://kit.svelte.dev/docs/project-structure#project-files-vite-config-js)) +- `endpointExtensions` is now `moduleExtensions` and can be used to filter param matchers ([#5085](https://github.com/sveltejs/kit/pull/5085), [Docs](https://kit.svelte.dev/docs/configuration#moduleextensions)) +- Node 16.9 is now the minimum version for SvelteKit ([#5395](https://github.com/sveltejs/kit/pull/5395)) +- %-encoded filenames are now allowed. If you had a `%` in your route, you must now encode it with `%25` ([#5056](https://github.com/sveltejs/kit/pull/5056)) +- Endpoint method names are now uppercased to match HTTP specifications ([#5513](https://github.com/sveltejs/kit/pull/5513), [Docs](https://kit.svelte.dev/docs/routing#endpoints)) +- `writeStatic` has been removed to align with Vite's config ([#5618](https://github.com/sveltejs/kit/pull/5618)) +- `transformPage` is now `transformPageChunk` ([#5657](https://github.com/sveltejs/kit/pull/5657), [Docs](https://kit.svelte.dev/docs/hooks#handle)) +- The `prepare` script is no longer needed in `package.json` ([#5760](https://github.com/sveltejs/kit/pull/5760)) +- `adapter-node` no longer does any compression while we wait for a [bug fix in the `compression` library](https://github.com/expressjs/compression/pull/183) ([#5560](https://github.com/sveltejs/kit/pull/5506)) + +For a full list of changes, check out kit's [CHANGELOG](https://github.com/sveltejs/kit/blob/master/packages/kit/CHANGELOG.md). + + +## What's new in Svelte & Language Tools +- The `@layer` [CSS at-rule](https://developer.mozilla.org/en-US/docs/Web/CSS/@layer) is now supported in Svelte components (**3.49.0**, [PR](https://github.com/sveltejs/svelte/issues/7504)) +- The `inert` [HTML attribute](https://html.spec.whatwg.org/multipage/interaction.html#the-inert-attribute) is now supported in Svelte's language tools and plugins (**105.20.0**, [PR](https://github.com/sveltejs/language-tools/pull/1565)) +- The Svelte plugin will now use `SvelteComponentTyped` typings, if available (**105.19.0**, [PR](https://github.com/sveltejs/language-tools/pull/1548)) + + +--- + +## Community Showcase + +**Apps & Sites built with Svelte** +- [PocketBase](https://github.com/pocketbase/pocketbase) is an open source Go backend with a single file and an admin dashboard built with Svelte +- [Hondo](https://www.playhondo.com/how-to-play) is a word guessing game with multiple rounds +- [Hexapipes](https://github.com/gereleth/hexapipes) is a site for playing hexagonal pipes puzzle +- [Mail Must Move](https://www.mordon.app/) is an email made for those who want to get more done +- [Jot Down](https://github.com/brysonbw/vscode-jot-down) is a Visual Studio Code extension for quick and simple note taking +- [Kadium](https://kadium.kasper.space/) is an app for staying on top of YouTube channels' uploads +- [Samen zjin we #1metS10](https://1mets10.avrotros.nl/) is a campaign website to support S10, the dutch Eurovision finalist, by sending a drawing or a wish +- [On Writing Code](https://onwritingcode.com/) is an interactive website to learn programming design patterns +- [Svelte-In-Motion](https://github.com/novacbn/svelte-in-motion) lets you create Svelte-animated videos in your browser +- [Svelte Terminal](https://github.com/Nico-Mayer/svelte-terminal) is a terminal-like website +- [Bulletlist](https://bulletlist.com/) is a simple tool with a single purpose: making lists +- [Remind Me Again](https://github.com/probablykasper/remind-me-again) is an app for toggleable reminders on Mac, Linux and Windows +- [Heyweek](https://heyweek.com/) is a timetracking app built for freelancers craving that extra pizzazz + +**Learning Resources** + +_Starring the Svelte team_ +- [The Svelte Documentary is out!](https://www.svelteradio.com/episodes/the-svelte-documentary-is-out) on Svelte Radio +- [Beginner SvelteKit](https://vercel.com/docs/beginner-sveltekit) by Vercel +- [Challenge: Explore Svelte by Building a Bubble Popping Game](https://prismic.io/blog/try-svelte-build-game) by Brittney Postma +- [Let's write a Client-side Routing Library with Svelte](https://www.youtube.com/watch?v=3foVDSknGEY) by lihautan +- [Svelte Sirens July Talk - Testing in Svelte with Jess Sachs](https://sveltesirens.dev/event/testing-in-svelte) + +_To Watch_ +- [10 Awesome Svelte UI Component Libraries](https://www.youtube.com/watch?v=RkD88ARvucM) by LevelUpTuts +- [Learn How SvelteKit Works](https://www.youtube.com/watch?v=VizuTy3uSNE) and [SvelteKit Endpoints](https://www.youtube.com/watch?v=XnVxDLTgCgo) by Joy of Code +- [SvelteKit using TS, and Storybook setup](https://www.youtube.com/watch?v=L4F5dSu0FcQ) by Jarrod Kane +- [Building Apps with Svelte!](https://www.youtube.com/watch?v=prsXVk1fdW4) by Simon Grimm +- [SvelteKit authentication, the better way - Tutorial](https://www.youtube.com/watch?v=Y98KipzwVdM) by Pilcrow + +_To Read_ +- [Some assorted Svelte demos](https://geoffrich.net/posts/assorted-svelte-demos/) by Geoff Rich +- [Three ways to bootstrap a Svelte project](https://maier.tech/posts/three-ways-to-bootstrap-a-svelte-project) by Thilo Maier +- [Design & build an app with Svelte](https://bootcamp.uxdesign.cc/design-build-an-app-with-svelte-ecd7ed0729da) by Hugo +- [Define routes via JS in SvelteKit](https://dev.to/maxcore/define-routes-via-js-in-sveltekit-27e9) by Max Core +- [Integrating Telegram api with SvelteKit](https://dev.to/theether0/integrating-telegram-api-with-sveltekit-5gb) by Shivam Meena +- [SvelteKit SSG: how to Prerender your SvelteKit Site](https://rodneylab.com/sveltekit-ssg/) by Rodney Lab +- [ADEO Design System: Building a Web Component library with Svelte and Rollup](https://medium.com/adeo-tech/adeo-design-system-building-a-web-component-library-with-svelte-and-rollup-72d65de50163) by Mohamed Mokhtari +- [The Svelte Handbook](https://thevalleyofcode.com/svelte/) by The Valley of Code +- [Test Svelte Component Using Vitest & Playwright](https://davipon.hashnode.dev/test-svelte-component-using-vitest-playwright) by David Peng +- [Transitional Apps with Phoenix and Svelte](https://nathancahill.com/phoenix-svelte) by Nathan Cahill + +_Tech Demos_ +- [Bringing the best GraphQL experience to Svelte](https://www.the-guild.dev/blog/houdini-and-kitql) by The Guild +- [Style your Svelte website faster with Stylify CSS](https://stylifycss.com/blog/style-your-svelte-website-faster-with-stylify-css/) by Stylify +- [Revamped Auth Helpers for Supabase (with SvelteKit support)](https://supabase.com/blog/2022/07/13/supabase-auth-helpers-with-sveltekit-support) by Supabase + + +**Libraries, Tools & Components** +- [Lucia](https://github.com/pilcrowOnPaper/lucia-sveltekit) is a simple, JWT based authentication library for SvelteKit that connects your SvelteKit app with your database +- [Skeleton](https://github.com/Brain-Bones/skeleton) is a UI component library for use with Svelte + Tailwind +- [pass-composer](https://pass-composer.vercel.app/) helps you compose your postprocessing passes for threlte scenes +- [@crikey/stores-*](https://www.npmjs.com/package/@crikey/stores-base) is a collection of 8 libraries to extend Svelte stores for common use-cases +- [Svelte Chrome Storage](https://github.com/shaun-wild/svelte-chrome-storage) is a lightweight abstraction between Svelte stores and Chrome extension storage +- [Svelte Schema Form](https://github.com/restspace/svelte-schema-form) is a form generator for JSON schema +- [svelte-gesture](https://github.com/wobsoriano/svelte-gesture) is a library that lets you bind richer mouse and touch events to any component or view +- [Snap Layout](https://github.com/ThaUnknown/snap-layout) and [universal-title-bar](https://github.com/ThaUnknown/universal-title-bar) bring Windows 11 snap layout and title features to webapps and PWAs. Both can be imported as a `.svelte` module or as a web component +- [svelte-adapter-bun](https://github.com/gornostay25/svelte-adapter-bun) is an adapter for SvelteKit apps that generates a standalone Bun server +- [json2dir](https://www.npmjs.com/package/json2dir) converts JSON objects into directory trees +- [Svelte Command Palette](https://github.com/rohitpotato/svelte-command-palette) is a drop-in command palette component +- [svelte-use-drop-outside](https://github.com/untemps/svelte-use-drop-outside) is a Svelte action to drop an element outside an area +- [PowerTable](https://github.com/muonw/powertable) is a JavaScript component that turns JSON data into an interactive HTML table +- [svelte-slides](https://github.com/rajasegar/svelte-slides) is a slide show template for Svelte using Reveal.js +- [Svelte Theme Light](https://marketplace.visualstudio.com/items?itemName=webmaek.svelte-theme-light) is a Visual Studio Code theme based on the Svelte REPL + +Did we miss anything? Let us know on [Reddit](https://www.reddit.com/r/sveltejs/) or [Discord](https://discord.com/invite/yy75DKs)! + +Still looking for something to do in September? Come join us at the Svelte Summit in Stockholm! [Get your tickets now](https://www.sveltesummit.com/). + +See ya next month! From 816409a27b07090fd6796f585121112e5bd71c88 Mon Sep 17 00:00:00 2001 From: Tal500 Date: Sat, 6 Aug 2022 20:54:23 +0300 Subject: [PATCH 014/145] [fix] Use `Node.parentNode` instead `Node.parentElement` for legacy browser support (#7724) --- src/runtime/internal/dom.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/internal/dom.ts b/src/runtime/internal/dom.ts index 072506629c..8a7d3af6da 100644 --- a/src/runtime/internal/dom.ts +++ b/src/runtime/internal/dom.ts @@ -163,7 +163,7 @@ export function append_hydration(target: NodeEx, node: NodeEx) { if (is_hydrating) { init_hydrate(target); - if ((target.actual_end_child === undefined) || ((target.actual_end_child !== null) && (target.actual_end_child.parentElement !== target))) { + if ((target.actual_end_child === undefined) || ((target.actual_end_child !== null) && (target.actual_end_child.parentNode !== target))) { target.actual_end_child = target.firstChild; } From 5b29124fbdf5df179fbd1aae7013774bf447fee8 Mon Sep 17 00:00:00 2001 From: Yuichiro Yamashita Date: Sun, 7 Aug 2022 02:56:47 +0900 Subject: [PATCH 015/145] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5df9239972..72b7df838a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ * Add `ComponentEvents` convenience type ([#7702](https://github.com/sveltejs/svelte/pull/7702)) * Add `SveltePreprocessor` utility type ([#7742](https://github.com/sveltejs/svelte/pull/7742)) * Handle arrow function on `` inside `` ([#7485](https://github.com/sveltejs/svelte/issues/7485)) +* Use `Node.parentNode` instead of `Node.parentElement` for legacy browser support ([#7723](https://github.com/sveltejs/svelte/issues/7723)) ## 3.49.0 From 419641bb3eefb53b4c627005b3637882e5e5342f Mon Sep 17 00:00:00 2001 From: Niko Simonson Date: Mon, 8 Aug 2022 09:01:54 -0700 Subject: [PATCH 016/145] Recursively check label children for input control (#5323) * Recursively check label children for input control * Add another test case * Update snapshot * clean up test Co-authored-by: tanhauhau --- src/compiler/compile/nodes/Element.ts | 20 ++++++- .../input.svelte | 3 + .../warnings.json | 1 + .../input.svelte | 6 ++ .../warnings.json | 60 +++++++++---------- 5 files changed, 58 insertions(+), 32 deletions(-) create mode 100644 test/validator/samples/a11y-label-has-associated-control-2/input.svelte create mode 100644 test/validator/samples/a11y-label-has-associated-control-2/warnings.json diff --git a/src/compiler/compile/nodes/Element.ts b/src/compiler/compile/nodes/Element.ts index e351a02499..119e187954 100644 --- a/src/compiler/compile/nodes/Element.ts +++ b/src/compiler/compile/nodes/Element.ts @@ -626,8 +626,24 @@ export default class Element extends Node { } if (this.name === 'label') { - const has_input_child = this.children.some(i => (i instanceof Element && a11y_labelable.has(i.name) )); - if (!attribute_map.has('for') && !has_input_child) { + const has_input_child = (children: INode[]) => { + if (children.some(child => (child instanceof Element && (a11y_labelable.has(child.name) || child.name === 'slot')))) { + return true; + } + + for (const child of children) { + if (!('children' in child) || child.children.length === 0) { + continue; + } + if (has_input_child(child.children)) { + return true; + } + } + + return false; + }; + + if (!attribute_map.has('for') && !has_input_child(this.children)) { component.warn(this, compiler_warnings.a11y_label_has_associated_control); } } diff --git a/test/validator/samples/a11y-label-has-associated-control-2/input.svelte b/test/validator/samples/a11y-label-has-associated-control-2/input.svelte new file mode 100644 index 0000000000..de26d50782 --- /dev/null +++ b/test/validator/samples/a11y-label-has-associated-control-2/input.svelte @@ -0,0 +1,3 @@ + diff --git a/test/validator/samples/a11y-label-has-associated-control-2/warnings.json b/test/validator/samples/a11y-label-has-associated-control-2/warnings.json new file mode 100644 index 0000000000..fe51488c70 --- /dev/null +++ b/test/validator/samples/a11y-label-has-associated-control-2/warnings.json @@ -0,0 +1 @@ +[] diff --git a/test/validator/samples/a11y-label-has-associated-control/input.svelte b/test/validator/samples/a11y-label-has-associated-control/input.svelte index 43304689dc..124888c089 100644 --- a/test/validator/samples/a11y-label-has-associated-control/input.svelte +++ b/test/validator/samples/a11y-label-has-associated-control/input.svelte @@ -1,6 +1,12 @@ + + + +G diff --git a/test/validator/samples/a11y-label-has-associated-control/warnings.json b/test/validator/samples/a11y-label-has-associated-control/warnings.json index b70a1a47de..f618e16973 100644 --- a/test/validator/samples/a11y-label-has-associated-control/warnings.json +++ b/test/validator/samples/a11y-label-has-associated-control/warnings.json @@ -1,32 +1,32 @@ [ - { - "code": "a11y-label-has-associated-control", - "end": { - "character": 16, - "column": 16, - "line": 1 - }, - "message": "A11y: A form label must be associated with a control.", - "pos": 0, - "start": { - "character": 0, - "column": 0, - "line": 1 - } - }, - { - "code": "a11y-label-has-associated-control", - "end": { - "character": 149, - "column": 30, - "line": 6 - }, - "message": "A11y: A form label must be associated with a control.", - "pos": 119, - "start": { - "character": 119, - "column": 0, - "line": 6 - } - } + { + "code": "a11y-label-has-associated-control", + "end": { + "character": 82, + "column": 16, + "line": 5 + }, + "message": "A11y: A form label must be associated with a control.", + "pos": 66, + "start": { + "character": 66, + "column": 0, + "line": 5 + } + }, + { + "code": "a11y-label-has-associated-control", + "end": { + "character": 215, + "column": 30, + "line": 10 + }, + "message": "A11y: A form label must be associated with a control.", + "pos": 185, + "start": { + "character": 185, + "column": 0, + "line": 10 + } + } ] From dc83d0b30dd981581229a3bb19eaf42bee15ea39 Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Tue, 9 Aug 2022 00:03:25 +0800 Subject: [PATCH 017/145] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 72b7df838a..313e104df3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ * Add `SveltePreprocessor` utility type ([#7742](https://github.com/sveltejs/svelte/pull/7742)) * Handle arrow function on `` inside `` ([#7485](https://github.com/sveltejs/svelte/issues/7485)) * Use `Node.parentNode` instead of `Node.parentElement` for legacy browser support ([#7723](https://github.com/sveltejs/svelte/issues/7723)) +* Improve a11y `label-has-associated-control` check to recusively check for input control ([#5528](https://github.com/sveltejs/svelte/issues/5528)) ## 3.49.0 From 012d639b42f6562f1df42d5bc9f3c79dbc0fd899 Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Tue, 9 Aug 2022 00:05:51 +0800 Subject: [PATCH 018/145] Update 05-accessibility-warnings.md reorder a11y warnings --- .../content/docs/05-accessibility-warnings.md | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/site/content/docs/05-accessibility-warnings.md b/site/content/docs/05-accessibility-warnings.md index 495d0107c4..8143f43d09 100644 --- a/site/content/docs/05-accessibility-warnings.md +++ b/site/content/docs/05-accessibility-warnings.md @@ -54,17 +54,6 @@ The following elements are visually distracting: `` and ``. --- -### `role-has-required-aria-props` - -Elements with ARIA roles must have all required attributes for that role. - -```sv - - -``` - ---- - ### `a11y-hidden` Certain DOM elements are useful for screen reader navigation and should not be hidden. @@ -272,6 +261,17 @@ Avoid positive `tabindex` property values. This will move elements out of the ex --- +### `a11y-role-has-required-aria-props` + +Elements with ARIA roles must have all required attributes for that role. + +```sv + + +``` + +--- + ### `a11y-structure` Enforce that certain DOM elements have the correct structure. From 3570a5361e2f9267891fb4c4c858d2a2cf8f49c8 Mon Sep 17 00:00:00 2001 From: Yuichiro Yamashita Date: Sun, 14 Aug 2022 17:26:19 +0900 Subject: [PATCH 019/145] [fix] Apply class directive properly after half way transition (#7765) --- .../render_dom/wrappers/Element/index.ts | 5 +++- .../class-shortcut-with-transition/_config.js | 30 +++++++++++++++++++ .../main.svelte | 17 +++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 test/runtime/samples/class-shortcut-with-transition/_config.js create mode 100644 test/runtime/samples/class-shortcut-with-transition/main.svelte diff --git a/src/compiler/compile/render_dom/wrappers/Element/index.ts b/src/compiler/compile/render_dom/wrappers/Element/index.ts index eed7c6f4ee..8e8e0d6706 100644 --- a/src/compiler/compile/render_dom/wrappers/Element/index.ts +++ b/src/compiler/compile/render_dom/wrappers/Element/index.ts @@ -1052,7 +1052,10 @@ export default class ElementWrapper extends Wrapper { block.chunks.update.push(updater); } else if ((dependencies && dependencies.size > 0) || this.class_dependencies.length) { const all_dependencies = this.class_dependencies.concat(...dependencies); - const condition = block.renderer.dirty(all_dependencies); + let condition = block.renderer.dirty(all_dependencies); + if (block.has_outros) { + condition = x`!#current || ${condition}`; + } // If all of the dependencies are non-dynamic (don't get updated) then there is no reason // to add an updater for this. diff --git a/test/runtime/samples/class-shortcut-with-transition/_config.js b/test/runtime/samples/class-shortcut-with-transition/_config.js new file mode 100644 index 0000000000..80df51bd4a --- /dev/null +++ b/test/runtime/samples/class-shortcut-with-transition/_config.js @@ -0,0 +1,30 @@ +export default { + props: { + open: false, + border: true + }, + html: '

foo

', + + test({ assert, component, target, raf }) { + component.open = true; + raf.tick(100); + assert.htmlEqual( + target.innerHTML, + '

foo

bar

' + ); + + component.open = false; + raf.tick(150); + assert.htmlEqual( + target.innerHTML, + '

foo

bar

' + ); + + component.open = true; + raf.tick(250); + assert.htmlEqual( + target.innerHTML, + '

foo

bar

' + ); + } +}; diff --git a/test/runtime/samples/class-shortcut-with-transition/main.svelte b/test/runtime/samples/class-shortcut-with-transition/main.svelte new file mode 100644 index 0000000000..3291ec4a10 --- /dev/null +++ b/test/runtime/samples/class-shortcut-with-transition/main.svelte @@ -0,0 +1,17 @@ + + +

foo

+{#if open} +

bar

+{/if} + + From 040192dd59b82e9258738ebc8ac718727828c226 Mon Sep 17 00:00:00 2001 From: Yuichiro Yamashita Date: Sun, 14 Aug 2022 17:27:10 +0900 Subject: [PATCH 020/145] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 313e104df3..a1dcc005fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ * Handle arrow function on `` inside `` ([#7485](https://github.com/sveltejs/svelte/issues/7485)) * Use `Node.parentNode` instead of `Node.parentElement` for legacy browser support ([#7723](https://github.com/sveltejs/svelte/issues/7723)) * Improve a11y `label-has-associated-control` check to recusively check for input control ([#5528](https://github.com/sveltejs/svelte/issues/5528)) +* Fix class directive updates after half way transition [#7764](https://github.com/sveltejs/svelte/issues/7764) ## 3.49.0 From d5efa2e446d1f6a968ca8441936840da63a1a5d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=9F=E4=B8=96=E5=8D=9A?= <897205285@qq.com> Date: Fri, 19 Aug 2022 12:30:22 +0800 Subject: [PATCH 021/145] [docs] Typescript -> TypeScript (#7797) * [docs] fix spellings error * fix ts --- .../blog/2020-12-01-whats-new-in-svelte-december-2020.md | 2 +- .../blog/2021-02-01-whats-new-in-svelte-february-2021.md | 2 +- .../content/blog/2021-03-01-whats-new-in-svelte-march-2021.md | 4 ++-- .../blog/2021-09-01-whats-new-in-svelte-september-2021.md | 2 +- .../blog/2021-10-01-whats-new-in-svelte-october-2021.md | 4 ++-- .../blog/2021-11-01-whats-new-in-svelte-november-2021.md | 2 +- .../content/blog/2022-04-01-whats-new-in-svelte-april-2022.md | 4 ++-- .../14-composition/04-optional-slots/app-a/App.svelte | 2 +- .../14-composition/04-optional-slots/app-b/App.svelte | 2 +- 9 files changed, 12 insertions(+), 12 deletions(-) diff --git a/site/content/blog/2020-12-01-whats-new-in-svelte-december-2020.md b/site/content/blog/2020-12-01-whats-new-in-svelte-december-2020.md index b8b1a9d13a..aac2c80f64 100644 --- a/site/content/blog/2020-12-01-whats-new-in-svelte-december-2020.md +++ b/site/content/blog/2020-12-01-whats-new-in-svelte-december-2020.md @@ -53,7 +53,7 @@ For all the features and bugfixes see the CHANGELOGs for [Svelte](https://github **Components, Libraries & Tools** - [svelte-crossword](https://russellgoldenberg.github.io/svelte-crossword/) is a customizable crossword puzzle component for Svelte. -- [svelte-cloudinary](https://github.com/cupcakearmy/svelte-cloudinary) makes it easy to integrate Cloudinary with Svelte (including Typescript and SSR support) +- [svelte-cloudinary](https://github.com/cupcakearmy/svelte-cloudinary) makes it easy to integrate Cloudinary with Svelte (including TypeScript and SSR support) - [Svelte Nova](https://extensions.panic.com/extensions/sb.lao/sb.lao.svelte-nova/) extends the new Nova editor to support Svelte - [saos](https://github.com/shiryel/saos) is a small svelte component to animate your elements on scroll. - [Svelte-nStore](https://github.com/lacikawiz/svelte-nStore) is a general purpose store replacement that fulfills the Svelte store contract and adds getter and calculation features. diff --git a/site/content/blog/2021-02-01-whats-new-in-svelte-february-2021.md b/site/content/blog/2021-02-01-whats-new-in-svelte-february-2021.md index 2d09a3c439..cb7bcb425e 100644 --- a/site/content/blog/2021-02-01-whats-new-in-svelte-february-2021.md +++ b/site/content/blog/2021-02-01-whats-new-in-svelte-february-2021.md @@ -70,7 +70,7 @@ New changes to the Svelte Society website include [a new cheat sheet](https://sv - [here-maps-svelte](https://github.com/peopledrivemecrazy/here-maps-svelte) makes it easy to include HERE maps in a Svelte app - [p5-svelte](https://github.com/tonyketcham/p5-svelte) is an absolutely dead simple way of tossing the creative coding/sketching tool, p5, into a project - [svelte-windicss-preprocess](https://github.com/voorjaar/svelte-windicss-preprocess) is a Svelte preprocessor to compile tailwindcss at build time based on windicss compiler -- [MitzaCoder/svelte-boilerplate](https://github.com/MitzaCoder/svelte-boilerplate) features configurations for Typescript, TailwindCSS, IE11 compatibility (with Babel) and lazy loaded modules. +- [MitzaCoder/svelte-boilerplate](https://github.com/MitzaCoder/svelte-boilerplate) features configurations for TypeScript, TailwindCSS, IE11 compatibility (with Babel) and lazy loaded modules. **Want to share your Svelte Component with the world?** Head over to the [Components](https://sveltesociety.dev/components) page on the Svelte Society site. You can contribute by making [a PR to this file](https://github.com/svelte-society/sveltesociety.dev/blob/master/src/pages/components/components.json). diff --git a/site/content/blog/2021-03-01-whats-new-in-svelte-march-2021.md b/site/content/blog/2021-03-01-whats-new-in-svelte-march-2021.md index 45a03444c7..ad32088dd3 100644 --- a/site/content/blog/2021-03-01-whats-new-in-svelte-march-2021.md +++ b/site/content/blog/2021-03-01-whats-new-in-svelte-march-2021.md @@ -17,7 +17,7 @@ Let's dive into the news 🐬 * Destructured defaults are now allowed to refer to other variables (**3.33.0**, [example](https://svelte.dev/repl/0ee7227e1b45465b9b47d7a5ae2d1252?version=3.33.0)) * Custom elements will now call `onMount` functions when connecting and clean up when disconnecting (**3.33.0**, checkout [this PR](https://github.com/sveltejs/svelte/pull/4522) for an interesting conversation on how folks are using Svelte with Web Components) * A `cssHash` option has been added to the compiler options to control the classname used for CSS scoping (**3.34.0**, [docs](https://svelte.dev/docs#compile-time-svelte-compile)) -* Continued improvement to Typescript definitions +* Continued improvement to TypeScript definitions For a complete list of changes, including bug fixes and links to PRs, check out [the CHANGELOG](https://github.com/sveltejs/svelte/blob/master/CHANGELOG.md) @@ -96,7 +96,7 @@ Haven't tried the language-tools yet? Check out [Svelte Extension for VSCode](ht - [Using Fauna's streaming feature to build a chat with Svelte](https://dev.to/fauna/using-fauna-s-streaming-feature-to-build-a-chat-with-svelte-1gkd) demonstrates how to setup and configure Fauna to build a real-time chat interface with Svelte - [Using TakeShape with Sapper](https://www.takeshape.io/articles/using-takeshape-with-sapper/) demonstrates how to connect the TakeShape CMS with Sapper - [YastPack](https://github.com/rodabt/yastpack) is Yet Another Snowpack-Svelte-TailwindCss-Routify Template Pack -- [S2T2](https://ralphbliu.medium.com/s2t2-snowpack-svelte-tailwindcss-typescript-8928caa5af6c) is a Snowpack + Svelte + TailwindCSS + Typescript template +- [S2T2](https://ralphbliu.medium.com/s2t2-snowpack-svelte-tailwindcss-typescript-8928caa5af6c) is a Snowpack + Svelte + TailwindCSS + TypeScript template - [tonyketcham/sapper-tailwind2-template](https://github.com/tonyketcham/sapper-tailwind2-template) is a Sapper Template w/ Tailwind 2.0, TypeScript, ESLint, and Prettier ## See you next month! diff --git a/site/content/blog/2021-09-01-whats-new-in-svelte-september-2021.md b/site/content/blog/2021-09-01-whats-new-in-svelte-september-2021.md index d4794b3c5e..46c483359a 100644 --- a/site/content/blog/2021-09-01-whats-new-in-svelte-september-2021.md +++ b/site/content/blog/2021-09-01-whats-new-in-svelte-september-2021.md @@ -44,7 +44,7 @@ To see all updates to SvelteKit, check out the [SvelteKit changelog](https://git - [macos-web](https://github.com/PuruVJ/macos-web) by @puruvjdev has been rebuilt with Svelte from the ground up. Check out all the details in this [Twitter thread](https://twitter.com/puruvjdev/status/1426267327687847939) - [Brave Search](https://search.brave.com/) is using Svelte - [exatorrent](https://github.com/varbhat/exatorrent) is a self-hostable, easy-to-use, lightweight and feature-rich torrent client written in Go and Svelte -- [json2TsTypes](https://github.com/jatinhemnani01/json2TsTypes) is a simple tool which will convert your JSON to Typescript Types/Interfaces +- [json2TsTypes](https://github.com/jatinhemnani01/json2TsTypes) is a simple tool which will convert your JSON to TypeScript Types/Interfaces - [Histogram.dev](https://histogram.dev/) generates histograms for each feature in a CSV - [cybernetic.dev](https://cybernetic.dev/) is a collection of data-centric UI experiments made while learning Svelte - [LunaNotes](https://chrome.google.com/webstore/detail/lunanotes-youtube-video-n/oehoffnnkgcdacmbkhmlbjedinpampak?hl=en) is a Chrome extension to help with taking YouTube video notes diff --git a/site/content/blog/2021-10-01-whats-new-in-svelte-october-2021.md b/site/content/blog/2021-10-01-whats-new-in-svelte-october-2021.md index 4b5b65d6f0..706b4907e0 100644 --- a/site/content/blog/2021-10-01-whats-new-in-svelte-october-2021.md +++ b/site/content/blog/2021-10-01-whats-new-in-svelte-october-2021.md @@ -52,7 +52,7 @@ To see all updates to SvelteKit, check out the [SvelteKit changelog](https://git - [hirehive](https://www.hirehive.com/) is a candidate and job tracking site - [Microsocial](https://microsocial.xyz/) is an experimental Peer-to-Peer Social Platform - [Dylan Ipsum](https://www.dylanlyrics.app/) is a random text generator to replace lorem ipsum with Bob Dylan lyrics -- [Chip8 Svelte](https://github.com/mikeyhogarth/chip8-svelte) is a CHIP-8 emulator frontend, built on top of CHIP8 Typescript +- [Chip8 Svelte](https://github.com/mikeyhogarth/chip8-svelte) is a CHIP-8 emulator frontend, built on top of CHIP8 TypeScript **Looking for a Svelte project to work on? Interested in helping make Svelte's presence on the web better?** Check out [the list of open issues](https://github.com/svelte-society/sveltesociety-2021/issues) if you'd like to contribute to the Svelte Society rewrite in SvelteKit. @@ -74,7 +74,7 @@ To see all updates to SvelteKit, check out the [SvelteKit changelog](https://git **Libraries, Tools & Components** - [sveltekit-netlify-cms](https://github.com/buhrmi/sveltekit-netlify-cms) is a SvelteKit skeleton app configured for use with Netlify CMS -- [SvelteFireTS](https://github.com/jacobbowdoin/sveltefirets) is a SvelteKit + Typescript + Firebase library inspired by Fireship.io +- [SvelteFireTS](https://github.com/jacobbowdoin/sveltefirets) is a SvelteKit + TypeScript + Firebase library inspired by Fireship.io - [stores-x](https://github.com/Anyass3/stores-x) lets you use Svelte stores just like vueX - [sveltekit-snippets](https://github.com/stordahl/sveltekit-snippets) is a VSCode extension that provides snippets for common patterns in SvelteKit & Vanilla Svelte - [svelte-xactor](https://github.com/wobsoriano/svelte-xactor) is a middleware that allows you to easily convert your xactor machines into a global store that implements the store contract diff --git a/site/content/blog/2021-11-01-whats-new-in-svelte-november-2021.md b/site/content/blog/2021-11-01-whats-new-in-svelte-november-2021.md index 12a89a639c..0b2d82c199 100644 --- a/site/content/blog/2021-11-01-whats-new-in-svelte-november-2021.md +++ b/site/content/blog/2021-11-01-whats-new-in-svelte-november-2021.md @@ -72,7 +72,7 @@ To see all updates to Svelte and SvelteKit, check out the [Svelte](https://githu - [date-picker-svelte](https://github.com/probablykasper/date-picker-svelte) is a date and time picker for Svelte - [TwelveUI](https://twelveui.readme.io/reference/what-is-twelveui) is a Svelte component library with accessibility built-in - [svelte-outclick](https://github.com/babakfp/svelte-outclick/) is a Svelte component that allows you to listen for clicks outside of an element, by providing you an outclick event -- [svelte-zero-api](https://github.com/ymzuiku/svelte-zero-api) lets you use SvelteKit APIs like client functions - with support for Typescript +- [svelte-zero-api](https://github.com/ymzuiku/svelte-zero-api) lets you use SvelteKit APIs like client functions - with support for TypeScript - [svelte-recaptcha-v2](https://github.com/basaran/svelte-recaptcha-v2) is a Google reCAPTCHA v2 implementation for Svelte SPA, SSR and sveltekit static sites. - [Svelte Body](https://github.com/ghostdevv/svelte-body) lets you apply styles to the body in routes - designed to work with SvelteKit and Routify. - [svelte-debug-console](https://github.com/basaran/svelte-debug-console) is a debug.js implementation for Svelte SPA, SSR and sveltekit static sites that lets you see your debug statements in the browser. diff --git a/site/content/blog/2022-04-01-whats-new-in-svelte-april-2022.md b/site/content/blog/2022-04-01-whats-new-in-svelte-april-2022.md index 2f9db93580..3858168008 100644 --- a/site/content/blog/2022-04-01-whats-new-in-svelte-april-2022.md +++ b/site/content/blog/2022-04-01-whats-new-in-svelte-april-2022.md @@ -41,7 +41,7 @@ More on that, and what else is new in Svelte, as we dive in... **Apps & Sites built with Svelte** - [Launcher](https://launcher.team/) is an open-source app launcher powered by SvelteKit, Prisma, and Tailwind -- [Paaster](https://paaster.io/) is a secure by default end to end encrypted pastebin built with Svelte, Vite, Typescript, Python, Starlette, rclone & Docker. +- [Paaster](https://paaster.io/) is a secure by default end to end encrypted pastebin built with Svelte, Vite, TypeScript, Python, Starlette, rclone & Docker. - [Simple AF Video Converter](https://github.com/berlyozzy/Simple-AF-Video-Converter) is an Electron wrapper around ffmpeg.wasm to make converting videos between formats easier - [Streamchaser](https://github.com/streamchaser/streamchaser) seeks to simplify movie, series and documentary search through a centralized entertainment technology platform - [Svelte Color Picker](https://github.com/V-Py/svelte-material-color-picker) is a simple color picker made with Svelte @@ -89,7 +89,7 @@ _To Watch_ **Libraries, Tools & Components** - [SvelTable](https://sveltable.io/) is a feature rich, data table component built with Svelte -- [svelte-cyberComp](https://github.com/Cybersteam00/svelte-cyberComp) is a powerful, lightweight component library written in Svelte and Typescript +- [svelte-cyberComp](https://github.com/Cybersteam00/svelte-cyberComp) is a powerful, lightweight component library written in Svelte and TypeScript - [Flowbite Svelte](https://github.com/shinokada/flowbite-svelte) is an unofficial Flowbite component library for Svelte - [Svelte-Tide-Project](https://github.com/jbertovic/svelte-tide-project) is a starter template for Svelte frontend apps with Rust Tide backend server - [Fetch Inject](https://github.com/vhscom/fetch-inject#sveltekit) implements a performance optimization technique for managing asynchronous JavaScript dependencies - now with Svelte support diff --git a/site/content/tutorial/14-composition/04-optional-slots/app-a/App.svelte b/site/content/tutorial/14-composition/04-optional-slots/app-a/App.svelte index 19537cb4b3..3dd126be75 100755 --- a/site/content/tutorial/14-composition/04-optional-slots/app-a/App.svelte +++ b/site/content/tutorial/14-composition/04-optional-slots/app-a/App.svelte @@ -10,7 +10,7 @@
  • diff --git a/site/content/tutorial/14-composition/04-optional-slots/app-b/App.svelte b/site/content/tutorial/14-composition/04-optional-slots/app-b/App.svelte index 19537cb4b3..3dd126be75 100755 --- a/site/content/tutorial/14-composition/04-optional-slots/app-b/App.svelte +++ b/site/content/tutorial/14-composition/04-optional-slots/app-b/App.svelte @@ -10,7 +10,7 @@
    • From 8d26b4a19d2b92a8334eaf2e030168e4bfcdda89 Mon Sep 17 00:00:00 2001 From: Yosuke Ota Date: Tue, 23 Aug 2022 11:20:46 +0900 Subject: [PATCH 022/145] [chore] improve performance by using `trimRight()` instead of regex replace (#7706) --- src/compiler/compile/render_ssr/index.ts | 2 +- src/compiler/parse/index.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/compile/render_ssr/index.ts b/src/compiler/compile/render_ssr/index.ts index 9d2c1cc60b..e256ba78fb 100644 --- a/src/compiler/compile/render_ssr/index.ts +++ b/src/compiler/compile/render_ssr/index.ts @@ -237,7 +237,7 @@ function trim(nodes: TemplateNode[]) { const node = nodes[end - 1] as Text; if (node.type !== 'Text') break; - node.data = node.data.replace(/\s+$/, ''); + node.data = node.data.trimRight(); if (node.data) break; } diff --git a/src/compiler/parse/index.ts b/src/compiler/parse/index.ts index 836fb670cf..e5e2260bc0 100644 --- a/src/compiler/parse/index.ts +++ b/src/compiler/parse/index.ts @@ -34,7 +34,7 @@ export class Parser { throw new TypeError('Template must be a string'); } - this.template = template.replace(/\s+$/, ''); + this.template = template.trimRight(); this.filename = options.filename; this.customElement = options.customElement; From 8238ac46dc27ae15a46c2ff1cc5222298304eccc Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Mon, 22 Aug 2022 19:22:04 -0700 Subject: [PATCH 023/145] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a1dcc005fa..5fee76add2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ * Use `Node.parentNode` instead of `Node.parentElement` for legacy browser support ([#7723](https://github.com/sveltejs/svelte/issues/7723)) * Improve a11y `label-has-associated-control` check to recusively check for input control ([#5528](https://github.com/sveltejs/svelte/issues/5528)) * Fix class directive updates after half way transition [#7764](https://github.com/sveltejs/svelte/issues/7764) +* Improve parsing speed when encountering large blocks of whitespace [#7675](https://github.com/sveltejs/svelte/issues/7675) ## 3.49.0 From a8616701e7b3c4efe48d1f3cc795d47782c85335 Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Mon, 29 Aug 2022 12:47:20 -0700 Subject: [PATCH 024/145] [docs] clarify reactivity rules (#7802) --- site/content/docs/01-component-format.md | 28 ++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/site/content/docs/01-component-format.md b/site/content/docs/01-component-format.md index 1c64094002..23508b5c7b 100644 --- a/site/content/docs/01-component-format.md +++ b/site/content/docs/01-component-format.md @@ -55,9 +55,7 @@ In development mode (see the [compiler options](/docs#compile-time-svelte-compil --- -If you export a `const`, `class` or `function`, it is readonly from outside the component. Function *expressions* are valid props, however. - -Readonly props can be accessed as properties on the element, tied to the component using [`bind:this` syntax](/docs#template-syntax-component-directives-bind-this). +If you export a `const`, `class` or `function`, it is readonly from outside the component. Functions are valid prop values, however, as shown below. ```sv ``` +Readonly props can be accessed as properties on the element, tied to the component using [`bind:this` syntax](/docs#template-syntax-component-directives-bind-this). + --- You can use reserved words as prop names. @@ -125,15 +125,29 @@ Because Svelte's reactivity is based on assignments, using array methods like `. ``` +--- + +Svelte's ` +``` + #### 3. `$:` marks a statement as reactive --- -Any top-level statement (i.e. not inside a block or a function) can be made reactive by prefixing it with the `$:` [JS label syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label). Reactive statements run immediately before the component updates, whenever the values that they depend on have changed. +Any top-level statement (i.e. not inside a block or a function) can be made reactive by prefixing it with the `$:` [JS label syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label). Reactive statements run after other script code and before the component markup is rendered, whenever the values that they depend on have changed. ```sv ``` From 0ed453dc11133e5dab902f7f44c807624d6d4c1f Mon Sep 17 00:00:00 2001 From: Daniel Sandoval Date: Thu, 1 Sep 2022 16:42:09 -0600 Subject: [PATCH 025/145] [docs] "What's new in Svelte" September newsletter (#7814) --- ...2-08-01-whats-new-in-svelte-august-2022.md | 2 +- ...9-01-whats-new-in-svelte-september-2022.md | 105 ++++++++++++++++++ 2 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 site/content/blog/2022-09-01-whats-new-in-svelte-september-2022.md diff --git a/site/content/blog/2022-08-01-whats-new-in-svelte-august-2022.md b/site/content/blog/2022-08-01-whats-new-in-svelte-august-2022.md index dfea1bcdd2..7757fab9ec 100644 --- a/site/content/blog/2022-08-01-whats-new-in-svelte-august-2022.md +++ b/site/content/blog/2022-08-01-whats-new-in-svelte-august-2022.md @@ -99,7 +99,7 @@ _Tech Demos_ - [Lucia](https://github.com/pilcrowOnPaper/lucia-sveltekit) is a simple, JWT based authentication library for SvelteKit that connects your SvelteKit app with your database - [Skeleton](https://github.com/Brain-Bones/skeleton) is a UI component library for use with Svelte + Tailwind - [pass-composer](https://pass-composer.vercel.app/) helps you compose your postprocessing passes for threlte scenes -- [@crikey/stores-*](https://www.npmjs.com/package/@crikey/stores-base) is a collection of 8 libraries to extend Svelte stores for common use-cases +- [@crikey/stores-*](https://whenderson.github.io/stores-mono/) is a collection of libraries to extend Svelte stores for common use-cases - [Svelte Chrome Storage](https://github.com/shaun-wild/svelte-chrome-storage) is a lightweight abstraction between Svelte stores and Chrome extension storage - [Svelte Schema Form](https://github.com/restspace/svelte-schema-form) is a form generator for JSON schema - [svelte-gesture](https://github.com/wobsoriano/svelte-gesture) is a library that lets you bind richer mouse and touch events to any component or view diff --git a/site/content/blog/2022-09-01-whats-new-in-svelte-september-2022.md b/site/content/blog/2022-09-01-whats-new-in-svelte-september-2022.md new file mode 100644 index 0000000000..a4a8ecfd04 --- /dev/null +++ b/site/content/blog/2022-09-01-whats-new-in-svelte-september-2022.md @@ -0,0 +1,105 @@ +--- +title: "What's new in Svelte: September 2022" +description: "Migrating to SvelteKit's new filesystem-based router" +author: Daniel Sandoval +authorURL: https://desandoval.net +--- + +Still looking for something to do this month? It's your last chance to get tickets to Svelte Summit, Stockholm! [Join us on Sept 8-9th](https://www.sveltesummit.com/) 🎉 + +With the redesign of SvelteKit's filesystem-based router merging early last month, there's lots to cover this month - from the [migration script](https://github.com/sveltejs/kit/discussions/5774) to a number of new blog posts, videos and tutorials. + +But the new routing isn't the only new feature in SvelteKit... + +## What's new in SvelteKit +- `Link` is now supported as an HTTP header and works out of the box with Cloudflare's [Automatic Early Hints](https://github.com/sveltejs/kit/issues/5455) (**1.0.0-next.405**, [PR](https://github.com/sveltejs/kit/pull/5735)) +- `$env/static/*` are now virtual to prevent writing sensitive values to disk (**1.0.0-next.413**, [PR](https://github.com/sveltejs/kit/pull/5825)) +- `$app/stores` can now be used from anywhere on the browser (**1.0.0-next.428**, [PR](https://github.com/sveltejs/kit/pull/6100)) +- `config.kit.env.dir` is a new config that sets the directory to search for `.env` files (**1.0.0-next.430**, [PR](https://github.com/sveltejs/kit/pull/6175)) + +**Breaking changes:** +- The filesystem-based router and `load` API improves the way routes are managed. **Before installing version `@sveltejs/kit@1.0.0-next.406` or later, [follow this migration guide](https://github.com/sveltejs/kit/discussions/5774)** ([PR](https://github.com/sveltejs/kit/pull/5778), [Issue](https://github.com/sveltejs/kit/discussions/5748)) +- `event.session` has been removed from `load` along with the `session` store and `getSession`. Use `event.locals` instead (**1.0.0-next.415**, [PR](https://github.com/sveltejs/kit/pull/5946)) +- Named layouts have been removed in favor of `(groups)` (**1.0.0-next.432**, [Docs](https://kit.svelte.dev/docs/advanced-routing#advanced-layouts), [PR & Migration Instructions](https://github.com/sveltejs/kit/pull/6174)) +- `event.clientAddress` is now `event.getClientAddress()` (**1.0.0-next.438**, [PR](https://github.com/sveltejs/kit/pull/6237)) +- `$app/env` has been renamed to `$app/environment`, to disambiguate with `$env/...` (**1.0.0-next.445**, [PR](https://github.com/sveltejs/kit/pull/6334)) + +For a full list of changes, check out kit's [CHANGELOG](https://github.com/sveltejs/kit/blob/master/packages/kit/CHANGELOG.md). + +**Updates to language tools** +- TypeScript doesn't resolve imports to SvelteKit's $types very well, the latest version of Svelte's language tools makes it better (**105.21.0**, [#1592](https://github.com/sveltejs/language-tools/pull/1592)) + + +--- + +## Community Showcase + +**Apps & Sites built with Svelte** +- [canno](https://twitter.com/a_warnes/status/1556724034959818754?s=20&t=RyKWALPByqMT5A_PkLtUew) is a simple interactive 3d physics game with adjustable gravity, cannon power, and debug visualizer - made with threlte +- [straw.page](https://straw.page/) is an extremely simple website builder that lets you create unique websites straight from your phone +- [Patra](https://patra.webjeda.com/) lets you share short notes just with a link. No database. No storage +- [promptoMANIA](https://promptomania.com/) is an AI art community with an online prompt builder +- [Album by Mood](https://www.albumbymood.com/) lets you listen to music based on your mood +- [Daily Sumeiro](https://digivaux.com/sumeiro/daily/) is a daily game to test your math and logic skills +- [Lofi and Games](https://www.lofiandgames.com/) - play relaxing, casual games right from your browser +- [Pitch Pipe](https://github.com/joelgibson/pitch-pipe) is a digital pitch pipe with a frequency analyser and just-intonation intervals +- [classes.wtf](https://github.com/ekzhang/classes.wtf) is a custom, distributed search engine written in Go and Svelte to make searching for Harvard courses much quicker than the standard course catalog +- [Scrumpack](https://scrumpack.io/) is a set of tools to help agile/scrum teams with their ceremonies like Planning Poker and Retrospectives + +**Learning Resources** + +_Starring the Svelte team_ +- [Supper Club × Rich Harris, Author of Svelte — Syntax Podcast 499](https://syntax.fm/show/499/supper-club-rich-harris-author-of-svelte) +- [Let's talk routing with Rich Harris on Svelte Radio](https://www.svelteradio.com/episodes/lets-talk-routing-with-rich-harris) +- [2.17 - Building the Future of Svelte at Vercel with Rich Harris](https://www.youtube.com/watch?v=F1sSUDVoij4) +- [1.15 - What's Up With SvelteKit with Shawn Wang (swyx)](https://www.youtube.com/watch?v=xLhuUShkYkM) +- [Adding Notion Tailwindcss and DaisyUI to Svelte App](https://www.youtube.com/watch?v=l4sbqrY0XGk) +- [Svelte 101 Session](https://www.youtube.com/watch?v=IIeBERpyxx4) +- [Astro and Svelte](https://www.youtube.com/watch?v=iYKKg-50Gm4) +- [Storyblok in Svelte](https://www.youtube.com/watch?v=xXHFRzqUxoE) +- [Svelte London August Recording](https://www.youtube.com/watch?v=ua6gE2zPulw) + +_Learning the new SvelteKit routing_ +- [Migrating Breaking Changes in SvelteKit](https://www.netlify.com/blog/migrating-breaking-changes-in-sveltekit/) by Brittney Postma (Netlify) +- [Major Svelte Kit API Change - Fixing `load`, and tightening up SvelteKit's design before 1.0](https://www.youtube.com/watch?v=OUGn7VifUCg) - Video by LevelUpTuts +- [SvelteKit Is Never Going To Be The Same](https://www.youtube.com/watch?v=eVFcGA-15LA) - Video by Joy of Code +- [Let's learn SvelteKit by building a static Markdown blog from scratch](https://joshcollinsworth.com/blog/build-static-sveltekit-markdown-blog) by Josh Collinsworth (updated Aug 26th to keep up with the new changes) + +_To Watch_ +- [Svelte Guide For React Developers](https://www.youtube.com/watch?v=uWDBEUkTRGk) and [Svelte State Management Guide](https://www.youtube.com/watch?v=4dDjQiOVrOo) by Joy of Code +- [What Is Bookit? The Svelte Kit Storybook Killer](https://www.youtube.com/watch?v=aOBGhvggsq0) and [What Is @type{import In Svelte Kit - JSDoc Syntax](https://www.youtube.com/watch?v=y0DvJTVO65M) by LevelUpTuts +- [TWF Yet another JS Framework... or not? Svelte!](https://www.youtube.com/watch?app=desktop&v=nT8QtDBIKZA) by TWF meetup + + +_To Read_ +- [Creating a Figma Plugin with Svelte](https://www.lekoarts.de/javascript/creating-a-figma-plugin-with-svelte) by Lennart +- [Svelte Video Blog: Vlog with Mux from your own SvelteKit Site](https://plus.rodneylab.com/tutorials/svelte-video-blog) and [Svelte Shy Header: Peekaboo Sticky Header with CSS](https://rodneylab.com/svelte-shy-header/) by Rodney Lab + + +**Libraries, Tools & Components** +- [@svelte-plugins/tooltips](https://github.com/svelte-plugins/tooltips) is a simple tooltip action and component designed for Svelte +- [Lucia](https://github.com/pilcrowOnPaper/lucia-sveltekit) is a simple authentication library for SvelteKit that connects your SvelteKit app to your database +- [remix-router-svelte](https://github.com/brophdawg11/remix-routers/tree/main/packages/svelte) is a Svelte implementation of the `react-router-dom` API (driven by `@remix-run/router`) +- [MKRT](https://github.com/j4w8n/mkrt) is a CLI to help you create SvelteKit routes, fast +- [Histoire](https://histoire.dev/guide/) is a tool to generate stories applications - scenarios where you showcase components for specific use cases +- [sveltekit-flash-message](https://www.npmjs.com/package/sveltekit-flash-message) is a Sveltekit library that passes temporary data to the next request, usually from endpoints +- [svelte-particles](https://github.com/matteobruni/tsparticles#svelte) is a lightweight TypeScript library for creating particles +- [svelte-claps](https://github.com/bufgix/svelte-claps) adds clap button (like Medium) to any page for your SvelteKit apps +- [Neon Flicker](https://svelte.dev/repl/fd5e3b2be7da42fe8afddf89661af7d7?version=3.49.0) is a Svelte component to make your text flicker in a cyberpunk style +- [ComboBox](https://svelte.dev/repl/144f22d18c6943abb1fdd00f13e23fde?version=3.49.0) is a search input to help users select from a large list of items +- [@svelte-put](https://github.com/vnphanquang/svelte-put) is useful svelte stuff to put in your projects +- [vite-plugin-svelte-bridge](https://github.com/joshnuss/vite-plugin-svelte-bridge) lets you write Svelte components and use them from React & Vue + +_UI Kits and Starters_ +- [Svelte-spectre](https://github.com/basf/svelte-spectre) is a UI-kit based on spectre.css and powered by Svelte +- [Skeleton](https://skeleton.brainandbonesllc.com/) allows you to build fast and reactive web UI using the power of Svelte + Tailwind +- [iconsax-svelte](https://www.npmjs.com/package/iconsax-svelte) brings the popular icon kit to Svelte +- [laravel-vite-svelte-spa-template](https://github.com/NukeJS/laravel-vite-svelte-spa-template) is a Laravel 9, Vite, Svelte SPA, Tailwind CSS (w/ Forms Plugin & Aspect Ratio Plugin), Axios, & TypeScript starter template +- [neutralino-svelte-boilerplate-js](https://github.com/Raffaele/neutralino-svelte-boilerplate-js) is a cross platform desktop template for Neutralino and Svelte +- [figma-plugin-svelte-vite](https://github.com/candidosales/figma-plugin-svelte-vite) is a boilerplate for creating Figma plugins using Svelte, Vite and Typescript +- [Urara](https://github.com/importantimport/urara) is a sweet & powerful SvelteKit blog starter +- [SvelteKit Commerce](https://vercel.com/templates/svelte/sveltekit-commerce) is an all-in-one starter kit for high-performance e-commerce sites built with SvelteKit by Vercel + +Did we miss anything? Let us know on [Reddit](https://www.reddit.com/r/sveltejs/) or [Discord](https://discord.com/invite/yy75DKs)! + +See ya next month! From bddd795746c2cdfe04e8256d7a50f4d38ef09238 Mon Sep 17 00:00:00 2001 From: Simon H <5968653+dummdidumm@users.noreply.github.com> Date: Fri, 2 Sep 2022 13:21:28 +0200 Subject: [PATCH 026/145] [feat] enhance action typings (#7805) Allows a way to tell language tools which additional attributes and events the action brings to the HTML element Related https://github.com/sveltejs/language-tools/pull/1553 --- src/runtime/action/index.ts | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/runtime/action/index.ts b/src/runtime/action/index.ts index d7cbf04b12..388f6f040e 100644 --- a/src/runtime/action/index.ts +++ b/src/runtime/action/index.ts @@ -4,9 +4,17 @@ * immediately after Svelte has applied updates to the markup. * - destroy: Method that is called after the element is unmounted * + * Additionally, you can specify which additional attributes and events the action enables on the applied element. + * This applies to TypeScript typings only and has no effect at runtime. + * * Example usage: * ```ts - * export function myAction(node: HTMLElement, parameter: Parameter): ActionReturn { + * interface Attributes { + * newprop?: string; + * 'on:event': (e: CustomEvent) => void; + * } + * + * export function myAction(node: HTMLElement, parameter: Parameter): ActionReturn { * // ... * return { * update: (updatedParameter) => {...}, @@ -17,9 +25,15 @@ * * Docs: https://svelte.dev/docs#template-syntax-element-directives-use-action */ -export interface ActionReturn { +export interface ActionReturn = Record> { update?: (parameter: Parameter) => void; destroy?: () => void; + /** + * ### DO NOT USE THIS + * This exists solely for type-checking and has no effect at runtime. + * Set this through the `Attributes` generic instead. + */ + $$_attributes?: Attributes; } /** @@ -32,11 +46,11 @@ export interface ActionReturn { * // ... * } * ``` - * You can return an object with methods `update` and `destroy` from the function. + * You can return an object with methods `update` and `destroy` from the function and type which additional attributes and events it has. * See interface `ActionReturn` for more details. * * Docs: https://svelte.dev/docs#template-syntax-element-directives-use-action */ -export interface Action { - (node: Node, parameter?: Parameter): void | ActionReturn; +export interface Action = Record> { + (node: Node, parameter?: Parameter): void | ActionReturn; } From af64ad94836a26a3868aa7e00fba89cf42ef2eda Mon Sep 17 00:00:00 2001 From: Simon H <5968653+dummdidumm@users.noreply.github.com> Date: Fri, 2 Sep 2022 13:32:19 +0200 Subject: [PATCH 027/145] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5fee76add2..456d65b699 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ * Disallow invalid CSS selectors starting with a combinator ([#7643](https://github.com/sveltejs/svelte/issues/7643)) * Add `ComponentEvents` convenience type ([#7702](https://github.com/sveltejs/svelte/pull/7702)) * Add `SveltePreprocessor` utility type ([#7742](https://github.com/sveltejs/svelte/pull/7742)) +* Enhance action typings ([#7805](https://github.com/sveltejs/svelte/pull/7805)) * Handle arrow function on `` inside `` ([#7485](https://github.com/sveltejs/svelte/issues/7485)) * Use `Node.parentNode` instead of `Node.parentElement` for legacy browser support ([#7723](https://github.com/sveltejs/svelte/issues/7723)) * Improve a11y `label-has-associated-control` check to recusively check for input control ([#5528](https://github.com/sveltejs/svelte/issues/5528)) From efe1df0e23a650b458d0c79f9d9ac382378380a9 Mon Sep 17 00:00:00 2001 From: Simon H <5968653+dummdidumm@users.noreply.github.com> Date: Fri, 2 Sep 2022 13:48:40 +0200 Subject: [PATCH 028/145] [fix] Only show lowercase component warning for non-html/svg elements (#7826) Fixes #5712 --- CHANGELOG.md | 1 + src/compiler/compile/nodes/Element.ts | 12 +++++------- src/shared/utils/names.ts | 13 +++++++++++++ .../samples/component-name-lowercase/input.svelte | 5 ++++- .../samples/component-name-lowercase/warnings.json | 10 +++++----- 5 files changed, 28 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 456d65b699..407c868d53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ * Improve a11y `label-has-associated-control` check to recusively check for input control ([#5528](https://github.com/sveltejs/svelte/issues/5528)) * Fix class directive updates after half way transition [#7764](https://github.com/sveltejs/svelte/issues/7764) * Improve parsing speed when encountering large blocks of whitespace [#7675](https://github.com/sveltejs/svelte/issues/7675) +* Only show lowercase component warning for non-html/svg elements [#5712](https://github.com/sveltejs/svelte/issues/5712) ## 3.49.0 diff --git a/src/compiler/compile/nodes/Element.ts b/src/compiler/compile/nodes/Element.ts index 119e187954..df0e649122 100644 --- a/src/compiler/compile/nodes/Element.ts +++ b/src/compiler/compile/nodes/Element.ts @@ -1,4 +1,4 @@ -import { is_void } from '../../../shared/utils/names'; +import { is_html, is_svg, is_void } from '../../../shared/utils/names'; import Node from './shared/Node'; import Attribute from './Attribute'; import Binding from './Binding'; @@ -26,8 +26,6 @@ import compiler_errors from '../compiler_errors'; import { ARIARoleDefintionKey, roles, aria, ARIAPropertyDefinition, ARIAProperty } from 'aria-query'; import { is_interactive_element, is_non_interactive_roles, is_presentation_role } from '../utils/a11y'; -const svg = /^(?:altGlyph|altGlyphDef|altGlyphItem|animate|animateColor|animateMotion|animateTransform|circle|clipPath|color-profile|cursor|defs|desc|discard|ellipse|feBlend|feColorMatrix|feComponentTransfer|feComposite|feConvolveMatrix|feDiffuseLighting|feDisplacementMap|feDistantLight|feDropShadow|feFlood|feFuncA|feFuncB|feFuncG|feFuncR|feGaussianBlur|feImage|feMerge|feMergeNode|feMorphology|feOffset|fePointLight|feSpecularLighting|feSpotLight|feTile|feTurbulence|filter|font|font-face|font-face-format|font-face-name|font-face-src|font-face-uri|foreignObject|g|glyph|glyphRef|hatch|hatchpath|hkern|image|line|linearGradient|marker|mask|mesh|meshgradient|meshpatch|meshrow|metadata|missing-glyph|mpath|path|pattern|polygon|polyline|radialGradient|rect|set|solidcolor|stop|svg|switch|symbol|text|textPath|tref|tspan|unknown|use|view|vkern)$/; - const aria_attributes = 'activedescendant atomic autocomplete busy checked colcount colindex colspan controls current describedby description details disabled dropeffect errormessage expanded flowto grabbed haspopup hidden invalid keyshortcuts label labelledby level live modal multiline multiselectable orientation owns placeholder posinset pressed readonly relevant required roledescription rowcount rowindex rowspan selected setsize sort valuemax valuemin valuenow valuetext'.split(' '); const aria_attribute_set = new Set(aria_attributes); @@ -166,13 +164,13 @@ function get_namespace(parent: Element, element: Element, explicit_namespace: st const parent_element = parent.find_nearest(/^Element/); if (!parent_element) { - return explicit_namespace || (svg.test(element.name) + return explicit_namespace || (is_svg(element.name) ? namespaces.svg : null); } if (parent_element.namespace !== namespaces.foreign) { - if (svg.test(element.name.toLowerCase())) return namespaces.svg; + if (is_svg(element.name.toLowerCase())) return namespaces.svg; if (parent_element.name.toLowerCase() === 'foreignobject') return null; } @@ -373,7 +371,7 @@ export default class Element extends Node { } validate() { - if (this.component.var_lookup.has(this.name) && this.component.var_lookup.get(this.name).imported) { + if (this.component.var_lookup.has(this.name) && this.component.var_lookup.get(this.name).imported && !is_svg(this.name) && !is_html(this.name)) { this.component.warn(this, compiler_warnings.component_name_lowercase(this.name)); } @@ -827,7 +825,7 @@ export default class Element extends Node { } else if (dimensions.test(name)) { if (this.name === 'svg' && (name === 'offsetWidth' || name === 'offsetHeight')) { return component.error(binding, compiler_errors.invalid_binding_on(binding.name, `. Use '${name.replace('offset', 'client')}' instead`)); - } else if (svg.test(this.name)) { + } else if (is_svg(this.name)) { return component.error(binding, compiler_errors.invalid_binding_on(binding.name, 'SVG elements')); } else if (is_void(this.name)) { return component.error(binding, compiler_errors.invalid_binding_on(binding.name, `void elements like <${this.name}>. Use a wrapper element instead`)); diff --git a/src/shared/utils/names.ts b/src/shared/utils/names.ts index 5e13e6cd87..7c7cf07cff 100644 --- a/src/shared/utils/names.ts +++ b/src/shared/utils/names.ts @@ -1,5 +1,18 @@ +/** regex of all html void element names */ const void_element_names = /^(?:area|base|br|col|command|embed|hr|img|input|keygen|link|meta|param|source|track|wbr)$/; +/** regex of all html element names. svg and math are omitted because they belong to the svg elements namespace */ +const html_element_names = /^(?:a|abbr|address|area|article|aside|audio|b|base|bdi|bdo|blockquote|body|br|button|canvas|caption|cite|code|col|colgroup|data|datalist|dd|del|details|dfn|dialog|div|dl|dt|em|embed|fieldset|figcaption|figure|footer|form|h1|h2|h3|h4|h5|h6|head|header|hr|html|i|iframe|img|input|ins|kbd|label|legend|li|link|main|map|mark|meta|meter|nav|noscript|object|ol|optgroup|option|output|p|param|picture|pre|progress|q|rp|rt|ruby|s|samp|script|section|select|small|source|span|strong|style|sub|summary|sup|table|tbody|td|template|textarea|tfoot|th|thead|time|title|tr|track|u|ul|var|video|wbr)$/; +/** regex of all svg element names */ +const svg = /^(?:altGlyph|altGlyphDef|altGlyphItem|animate|animateColor|animateMotion|animateTransform|circle|clipPath|color-profile|cursor|defs|desc|discard|ellipse|feBlend|feColorMatrix|feComponentTransfer|feComposite|feConvolveMatrix|feDiffuseLighting|feDisplacementMap|feDistantLight|feDropShadow|feFlood|feFuncA|feFuncB|feFuncG|feFuncR|feGaussianBlur|feImage|feMerge|feMergeNode|feMorphology|feOffset|fePointLight|feSpecularLighting|feSpotLight|feTile|feTurbulence|filter|font|font-face|font-face-format|font-face-name|font-face-src|font-face-uri|foreignObject|g|glyph|glyphRef|hatch|hatchpath|hkern|image|line|linearGradient|marker|mask|mesh|meshgradient|meshpatch|meshrow|metadata|missing-glyph|mpath|path|pattern|polygon|polyline|radialGradient|rect|set|solidcolor|stop|svg|switch|symbol|text|textPath|tref|tspan|unknown|use|view|vkern)$/; export function is_void(name: string) { return void_element_names.test(name) || name.toLowerCase() === '!doctype'; } + +export function is_html(name: string) { + return html_element_names.test(name); +} + +export function is_svg(name: string) { + return svg.test(name); +} diff --git a/test/validator/samples/component-name-lowercase/input.svelte b/test/validator/samples/component-name-lowercase/input.svelte index ebd7cf3481..bfca8cc471 100644 --- a/test/validator/samples/component-name-lowercase/input.svelte +++ b/test/validator/samples/component-name-lowercase/input.svelte @@ -1,7 +1,10 @@ - \ No newline at end of file + +
      diff --git a/test/validator/samples/component-name-lowercase/warnings.json b/test/validator/samples/component-name-lowercase/warnings.json index 37765b423d..57aac0c2a5 100644 --- a/test/validator/samples/component-name-lowercase/warnings.json +++ b/test/validator/samples/component-name-lowercase/warnings.json @@ -2,16 +2,16 @@ { "code": "component-name-lowercase", "message": " will be treated as an HTML element unless it begins with a capital letter", - "pos": 82, + "pos": 121, "start": { - "character": 82, + "character": 121, "column": 0, - "line": 6 + "line": 8 }, "end": { - "character": 102, + "character": 141, "column": 20, - "line": 6 + "line": 8 } } ] From 46990652c00542c13044219991f9a1149a37cc52 Mon Sep 17 00:00:00 2001 From: Conduitry Date: Fri, 2 Sep 2022 08:12:22 -0400 Subject: [PATCH 029/145] -> v3.50.0 --- CHANGELOG.md | 25 +++++++++++++------------ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 407c868d53..4b150bb169 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,22 +1,23 @@ # Svelte changelog -## Unreleased +## 3.50.0 -* Add a11y warning `a11y-role-has-required-aria-props` which checks that elements with `role` attribute has all required attributes for that role. ([#5852](https://github.com/sveltejs/svelte/pull/5852)) -* Add a11y warning `aria-proptypes` which checks ARIA state and property values ([#6978](https://github.com/sveltejs/svelte/pull/6978)) -* Add a11y warning `a11y-no-abstract-role` which checks ARIA roles must be non-abstract ARIA role ([#6241](https://github.com/sveltejs/svelte/pull/6241)) -* Add a11y warning `a11y-no-interactive-element-to-noninteractive-role` which checks for noninteractive roles used on interactive elements ([#5955](https://github.com/sveltejs/svelte/pull/5955)) -* Remove of empty stylesheets created from transitions ([#4801](https://github.com/sveltejs/svelte/issues/4801), [#7164](https://github.com/sveltejs/svelte/issues/7164)) -* Disallow invalid CSS selectors starting with a combinator ([#7643](https://github.com/sveltejs/svelte/issues/7643)) +* Add a11y warnings: + * `a11y-incorrect-aria-attribute-type`: check ARIA state and property values ([#6978](https://github.com/sveltejs/svelte/pull/6978)) + * `a11y-no-abstract-role`: check that ARIA roles are non-abstract ([#6241](https://github.com/sveltejs/svelte/pull/6241)) + * `a11y-no-interactive-element-to-noninteractive-role`: check for non-interactive roles used on interactive elements ([#5955](https://github.com/sveltejs/svelte/pull/5955)) + * `a11y-role-has-required-aria-props`: check that elements with `role` attribute have all required attributes for that role ([#5852](https://github.com/sveltejs/svelte/pull/5852)) * Add `ComponentEvents` convenience type ([#7702](https://github.com/sveltejs/svelte/pull/7702)) * Add `SveltePreprocessor` utility type ([#7742](https://github.com/sveltejs/svelte/pull/7742)) * Enhance action typings ([#7805](https://github.com/sveltejs/svelte/pull/7805)) -* Handle arrow function on `` inside `` ([#7485](https://github.com/sveltejs/svelte/issues/7485)) +* Remove empty stylesheets created from transitions ([#4801](https://github.com/sveltejs/svelte/issues/4801), [#7164](https://github.com/sveltejs/svelte/issues/7164)) +* Make `a11y-label-has-associated-control` warning check all descendants for input control ([#5528](https://github.com/sveltejs/svelte/issues/5528)) +* Only show lowercase component name warnings for non-HTML/SVG elements ([#5712](https://github.com/sveltejs/svelte/issues/5712)) +* Disallow invalid CSS selectors starting with a combinator ([#7643](https://github.com/sveltejs/svelte/issues/7643)) * Use `Node.parentNode` instead of `Node.parentElement` for legacy browser support ([#7723](https://github.com/sveltejs/svelte/issues/7723)) -* Improve a11y `label-has-associated-control` check to recusively check for input control ([#5528](https://github.com/sveltejs/svelte/issues/5528)) -* Fix class directive updates after half way transition [#7764](https://github.com/sveltejs/svelte/issues/7764) -* Improve parsing speed when encountering large blocks of whitespace [#7675](https://github.com/sveltejs/svelte/issues/7675) -* Only show lowercase component warning for non-html/svg elements [#5712](https://github.com/sveltejs/svelte/issues/5712) +* Handle arrow function on `` inside `` ([#7485](https://github.com/sveltejs/svelte/issues/7485)) +* Improve parsing speed when encountering large blocks of whitespace ([#7675](https://github.com/sveltejs/svelte/issues/7675)) +* Fix `class:` directive updates in aborted/restarted transitions ([#7764](https://github.com/sveltejs/svelte/issues/7764)) ## 3.49.0 diff --git a/package-lock.json b/package-lock.json index 0db7287a64..8beef8470a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "svelte", - "version": "3.49.0", + "version": "3.50.0", "lockfileVersion": 2, "requires": true, "packages": { diff --git a/package.json b/package.json index 4a4d5266c3..3e22d8b627 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "svelte", - "version": "3.49.0", + "version": "3.50.0", "description": "Cybernetically enhanced web apps", "module": "index.mjs", "main": "index", From f3f3d074c59c79836a42f53ecd0cece3a916ef61 Mon Sep 17 00:00:00 2001 From: schelv <13403863+schelv@users.noreply.github.com> Date: Sat, 3 Sep 2022 18:06:57 +0200 Subject: [PATCH 030/145] [docs] use KeyboardEvent.code (#7809) --- .../16-special-elements/04-svelte-window/app-a/App.svelte | 8 ++++---- .../16-special-elements/04-svelte-window/app-b/App.svelte | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/site/content/tutorial/16-special-elements/04-svelte-window/app-a/App.svelte b/site/content/tutorial/16-special-elements/04-svelte-window/app-a/App.svelte index 24c9a6368a..47f3d8a87f 100644 --- a/site/content/tutorial/16-special-elements/04-svelte-window/app-a/App.svelte +++ b/site/content/tutorial/16-special-elements/04-svelte-window/app-a/App.svelte @@ -1,10 +1,10 @@ @@ -13,7 +13,7 @@
      {#if key} {key === ' ' ? 'Space' : key} -

      {keyCode}

      +

      {code}

      {:else}

      Focus this window and press any key

      {/if} @@ -39,4 +39,4 @@ border-bottom: 5px solid rgba(0, 0, 0, 0.2); color: #555; } - \ No newline at end of file + diff --git a/site/content/tutorial/16-special-elements/04-svelte-window/app-b/App.svelte b/site/content/tutorial/16-special-elements/04-svelte-window/app-b/App.svelte index 026dfa94f7..c4b5ae53b3 100644 --- a/site/content/tutorial/16-special-elements/04-svelte-window/app-b/App.svelte +++ b/site/content/tutorial/16-special-elements/04-svelte-window/app-b/App.svelte @@ -1,10 +1,10 @@ @@ -13,7 +13,7 @@
      {#if key} {key === ' ' ? 'Space' : key} -

      {keyCode}

      +

      {code}

      {:else}

      Focus this window and press any key

      {/if} From feb8dfce61212affedfede786fd571dbd55905cb Mon Sep 17 00:00:00 2001 From: Yuichiro Yamashita Date: Sun, 4 Sep 2022 13:13:55 +0900 Subject: [PATCH 031/145] [fix] add all global objects / functions (#7786) --- CHANGELOG.md | 4 + scripts/globals-extractor.mjs | 91 ++++ src/compiler/compile/Component.ts | 3 +- src/compiler/utils/globals.ts | 840 ++++++++++++++++++++++++++++++ src/compiler/utils/names.ts | 65 --- 5 files changed, 937 insertions(+), 66 deletions(-) create mode 100644 scripts/globals-extractor.mjs create mode 100644 src/compiler/utils/globals.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b150bb169..92155c0be8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Svelte changelog +## Unreleased + +* Add all global objects / functions ([#3805](https://github.com/sveltejs/svelte/issue/3805), [#7223](https://github.com/sveltejs/svelte/issue/7223), [#7240](https://github.com/sveltejs/svelte/issue/7240)) + ## 3.50.0 * Add a11y warnings: diff --git a/scripts/globals-extractor.mjs b/scripts/globals-extractor.mjs new file mode 100644 index 0000000000..1c4274a024 --- /dev/null +++ b/scripts/globals-extractor.mjs @@ -0,0 +1,91 @@ +/** ---------------------------------------------------------------------- +This script gets a list of global objects/functions of browser. +This process is simple for now, so it is handled without AST parser. +Please run `node scripts/globals-extractor.mjs` at the project root. + +see: https://github.com/microsoft/TypeScript/tree/main/lib + ---------------------------------------------------------------------- */ + +import http from 'https'; +import fs from 'fs'; + +const GLOBAL_TS_PATH = './src/compiler/utils/globals.ts'; + +// MEMO: add additional objects/functions which existed in `src/compiler/utils/names.ts` +// before this script was introduced but could not be retrieved by this process. +const SPECIALS = ['global', 'globalThis', 'InternalError', 'process', 'undefined']; + +const get_url = (name) => `https://raw.githubusercontent.com/microsoft/TypeScript/main/lib/lib.${name}.d.ts`; +const extract_name = (split) => split.match(/^[a-zA-Z0-9_$]+/)[0]; + +const extract_functions_and_references = (name, data) => { + const functions = []; + const references = []; + data.split('\n').forEach(line => { + const trimmed = line.trim(); + const split = trimmed.replace(/[\s+]/, ' ').split(' '); + if (split[0] === 'declare' && split[1] !== 'type') { + functions.push(extract_name(split[2])); + } else if (trimmed.startsWith('/// new Promise((resolve, reject) => { + http.get(url, (res) => { + let body = ''; + res.setEncoding('utf8'); + res.on('data', (chunk) => body += chunk); + res.on('end', () => resolve(body)); + }).on('error', (e) => { + console.error(e.message); + reject(e); + }); +}); + +const fetched_names = new Set(); +const get_functions = async (name) => { + const res = []; + if (fetched_names.has(name)) return res; + fetched_names.add(name); + const body = await do_get(get_url(name)); + const { functions, references } = extract_functions_and_references(name, body); + res.push(...functions); + const chile_functions = await Promise.all(references.map(get_functions)); + chile_functions.forEach(i => res.push(...i)); + return res; +}; + +const build_output = (functions) => { + const sorted = Array.from(new Set(functions.sort())); + return `\ +/** ---------------------------------------------------------------------- +This file is automatically generated by \`scripts/globals-extractor.mjs\`. +Generated At: ${new Date().toISOString()} +---------------------------------------------------------------------- */ + +export default new Set([ +${sorted.map((i) => `\t'${i}'`).join(',\n')} +]); +`; +}; + +const get_exists_globals = () => { + const regexp = /^\s*["'](.+)["'],?\s*$/; + return fs.readFileSync(GLOBAL_TS_PATH, 'utf8') + .split('\n') + .filter(line => line.match(regexp)) + .map(line => line.match(regexp)[1]); +}; + +(async () => { + const globals = get_exists_globals(); + const new_globals = await get_functions('es2021.full'); + globals.forEach((g) => new_globals.push(g)); + SPECIALS.forEach((g) => new_globals.push(g)); + fs.writeFileSync(GLOBAL_TS_PATH, build_output(new_globals)); +})(); diff --git a/src/compiler/compile/Component.ts b/src/compiler/compile/Component.ts index 63c62a256a..2f8874de7a 100644 --- a/src/compiler/compile/Component.ts +++ b/src/compiler/compile/Component.ts @@ -1,7 +1,8 @@ import { walk } from 'estree-walker'; import { getLocator } from 'locate-character'; import Stats from '../Stats'; -import { globals, reserved, is_valid } from '../utils/names'; +import { reserved, is_valid } from '../utils/names'; +import globals from '../utils/globals'; import { namespaces, valid_namespaces } from '../utils/namespaces'; import create_module from './create_module'; import { diff --git a/src/compiler/utils/globals.ts b/src/compiler/utils/globals.ts new file mode 100644 index 0000000000..ee43af3b91 --- /dev/null +++ b/src/compiler/utils/globals.ts @@ -0,0 +1,840 @@ +/** ---------------------------------------------------------------------- +This file is automatically generated by `scripts/globals-extractor.mjs`. +Generated At: 2022-09-03T15:22:37.415Z +---------------------------------------------------------------------- */ + +export default new Set([ + 'AbortController', + 'AbortSignal', + 'AbstractRange', + 'ActiveXObject', + 'AggregateError', + 'AnalyserNode', + 'Animation', + 'AnimationEffect', + 'AnimationEvent', + 'AnimationPlaybackEvent', + 'AnimationTimeline', + 'Array', + 'ArrayBuffer', + 'Atomics', + 'Attr', + 'Audio', + 'AudioBuffer', + 'AudioBufferSourceNode', + 'AudioContext', + 'AudioDestinationNode', + 'AudioListener', + 'AudioNode', + 'AudioParam', + 'AudioParamMap', + 'AudioProcessingEvent', + 'AudioScheduledSourceNode', + 'AudioWorklet', + 'AudioWorkletNode', + 'AuthenticatorAssertionResponse', + 'AuthenticatorAttestationResponse', + 'AuthenticatorResponse', + 'BarProp', + 'BaseAudioContext', + 'BeforeUnloadEvent', + 'BigInt', + 'BigInt64Array', + 'BigUint64Array', + 'BiquadFilterNode', + 'Blob', + 'BlobEvent', + 'Boolean', + 'BroadcastChannel', + 'ByteLengthQueuingStrategy', + 'CDATASection', + 'CSS', + 'CSSAnimation', + 'CSSConditionRule', + 'CSSCounterStyleRule', + 'CSSFontFaceRule', + 'CSSGroupingRule', + 'CSSImportRule', + 'CSSKeyframeRule', + 'CSSKeyframesRule', + 'CSSMediaRule', + 'CSSNamespaceRule', + 'CSSPageRule', + 'CSSRule', + 'CSSRuleList', + 'CSSStyleDeclaration', + 'CSSStyleRule', + 'CSSStyleSheet', + 'CSSSupportsRule', + 'CSSTransition', + 'Cache', + 'CacheStorage', + 'CanvasCaptureMediaStreamTrack', + 'CanvasGradient', + 'CanvasPattern', + 'CanvasRenderingContext2D', + 'ChannelMergerNode', + 'ChannelSplitterNode', + 'CharacterData', + 'ClientRect', + 'Clipboard', + 'ClipboardEvent', + 'ClipboardItem', + 'CloseEvent', + 'Comment', + 'CompositionEvent', + 'ConstantSourceNode', + 'ConvolverNode', + 'CountQueuingStrategy', + 'Credential', + 'CredentialsContainer', + 'Crypto', + 'CryptoKey', + 'CustomElementRegistry', + 'CustomEvent', + 'DOMException', + 'DOMImplementation', + 'DOMMatrix', + 'DOMMatrixReadOnly', + 'DOMParser', + 'DOMPoint', + 'DOMPointReadOnly', + 'DOMQuad', + 'DOMRect', + 'DOMRectList', + 'DOMRectReadOnly', + 'DOMStringList', + 'DOMStringMap', + 'DOMTokenList', + 'DataTransfer', + 'DataTransferItem', + 'DataTransferItemList', + 'DataView', + 'Date', + 'DelayNode', + 'DeviceMotionEvent', + 'DeviceOrientationEvent', + 'Document', + 'DocumentFragment', + 'DocumentTimeline', + 'DocumentType', + 'DragEvent', + 'DynamicsCompressorNode', + 'Element', + 'ElementInternals', + 'Enumerator', + 'Error', + 'ErrorEvent', + 'EvalError', + 'Event', + 'EventCounts', + 'EventSource', + 'EventTarget', + 'External', + 'File', + 'FileList', + 'FileReader', + 'FileSystem', + 'FileSystemDirectoryEntry', + 'FileSystemDirectoryHandle', + 'FileSystemDirectoryReader', + 'FileSystemEntry', + 'FileSystemFileEntry', + 'FileSystemFileHandle', + 'FileSystemHandle', + 'FinalizationRegistry', + 'Float32Array', + 'Float64Array', + 'FocusEvent', + 'FontFace', + 'FontFaceSet', + 'FontFaceSetLoadEvent', + 'FormData', + 'FormDataEvent', + 'Function', + 'GainNode', + 'Gamepad', + 'GamepadButton', + 'GamepadEvent', + 'GamepadHapticActuator', + 'Geolocation', + 'GeolocationCoordinates', + 'GeolocationPosition', + 'GeolocationPositionError', + 'HTMLAllCollection', + 'HTMLAnchorElement', + 'HTMLAreaElement', + 'HTMLAudioElement', + 'HTMLBRElement', + 'HTMLBaseElement', + 'HTMLBodyElement', + 'HTMLButtonElement', + 'HTMLCanvasElement', + 'HTMLCollection', + 'HTMLDListElement', + 'HTMLDataElement', + 'HTMLDataListElement', + 'HTMLDetailsElement', + 'HTMLDialogElement', + 'HTMLDirectoryElement', + 'HTMLDivElement', + 'HTMLDocument', + 'HTMLElement', + 'HTMLEmbedElement', + 'HTMLFieldSetElement', + 'HTMLFontElement', + 'HTMLFormControlsCollection', + 'HTMLFormElement', + 'HTMLFrameElement', + 'HTMLFrameSetElement', + 'HTMLHRElement', + 'HTMLHeadElement', + 'HTMLHeadingElement', + 'HTMLHtmlElement', + 'HTMLIFrameElement', + 'HTMLImageElement', + 'HTMLInputElement', + 'HTMLLIElement', + 'HTMLLabelElement', + 'HTMLLegendElement', + 'HTMLLinkElement', + 'HTMLMapElement', + 'HTMLMarqueeElement', + 'HTMLMediaElement', + 'HTMLMenuElement', + 'HTMLMetaElement', + 'HTMLMeterElement', + 'HTMLModElement', + 'HTMLOListElement', + 'HTMLObjectElement', + 'HTMLOptGroupElement', + 'HTMLOptionElement', + 'HTMLOptionsCollection', + 'HTMLOutputElement', + 'HTMLParagraphElement', + 'HTMLParamElement', + 'HTMLPictureElement', + 'HTMLPreElement', + 'HTMLProgressElement', + 'HTMLQuoteElement', + 'HTMLScriptElement', + 'HTMLSelectElement', + 'HTMLSlotElement', + 'HTMLSourceElement', + 'HTMLSpanElement', + 'HTMLStyleElement', + 'HTMLTableCaptionElement', + 'HTMLTableCellElement', + 'HTMLTableColElement', + 'HTMLTableElement', + 'HTMLTableRowElement', + 'HTMLTableSectionElement', + 'HTMLTemplateElement', + 'HTMLTextAreaElement', + 'HTMLTimeElement', + 'HTMLTitleElement', + 'HTMLTrackElement', + 'HTMLUListElement', + 'HTMLUnknownElement', + 'HTMLVideoElement', + 'HashChangeEvent', + 'Headers', + 'History', + 'IDBCursor', + 'IDBCursorWithValue', + 'IDBDatabase', + 'IDBFactory', + 'IDBIndex', + 'IDBKeyRange', + 'IDBObjectStore', + 'IDBOpenDBRequest', + 'IDBRequest', + 'IDBTransaction', + 'IDBVersionChangeEvent', + 'IIRFilterNode', + 'IdleDeadline', + 'Image', + 'ImageBitmap', + 'ImageBitmapRenderingContext', + 'ImageData', + 'Infinity', + 'InputDeviceInfo', + 'InputEvent', + 'Int16Array', + 'Int32Array', + 'Int8Array', + 'InternalError', + 'IntersectionObserver', + 'IntersectionObserverEntry', + 'Intl', + 'JSON', + 'KeyboardEvent', + 'KeyframeEffect', + 'Location', + 'Lock', + 'LockManager', + 'Map', + 'Math', + 'MathMLElement', + 'MediaCapabilities', + 'MediaDeviceInfo', + 'MediaDevices', + 'MediaElementAudioSourceNode', + 'MediaEncryptedEvent', + 'MediaError', + 'MediaKeyMessageEvent', + 'MediaKeySession', + 'MediaKeyStatusMap', + 'MediaKeySystemAccess', + 'MediaKeys', + 'MediaList', + 'MediaMetadata', + 'MediaQueryList', + 'MediaQueryListEvent', + 'MediaRecorder', + 'MediaRecorderErrorEvent', + 'MediaSession', + 'MediaSource', + 'MediaStream', + 'MediaStreamAudioDestinationNode', + 'MediaStreamAudioSourceNode', + 'MediaStreamTrack', + 'MediaStreamTrackEvent', + 'MessageChannel', + 'MessageEvent', + 'MessagePort', + 'MimeType', + 'MimeTypeArray', + 'MouseEvent', + 'MutationEvent', + 'MutationObserver', + 'MutationRecord', + 'NaN', + 'NamedNodeMap', + 'NavigationPreloadManager', + 'Navigator', + 'NetworkInformation', + 'Node', + 'NodeFilter', + 'NodeIterator', + 'NodeList', + 'Notification', + 'Number', + 'Object', + 'OfflineAudioCompletionEvent', + 'OfflineAudioContext', + 'Option', + 'OscillatorNode', + 'OverconstrainedError', + 'PageTransitionEvent', + 'PannerNode', + 'Path2D', + 'PaymentAddress', + 'PaymentMethodChangeEvent', + 'PaymentRequest', + 'PaymentRequestUpdateEvent', + 'PaymentResponse', + 'Performance', + 'PerformanceEntry', + 'PerformanceEventTiming', + 'PerformanceMark', + 'PerformanceMeasure', + 'PerformanceNavigation', + 'PerformanceNavigationTiming', + 'PerformanceObserver', + 'PerformanceObserverEntryList', + 'PerformancePaintTiming', + 'PerformanceResourceTiming', + 'PerformanceServerTiming', + 'PerformanceTiming', + 'PeriodicWave', + 'PermissionStatus', + 'Permissions', + 'PictureInPictureWindow', + 'Plugin', + 'PluginArray', + 'PointerEvent', + 'PopStateEvent', + 'ProcessingInstruction', + 'ProgressEvent', + 'Promise', + 'PromiseRejectionEvent', + 'Proxy', + 'PublicKeyCredential', + 'PushManager', + 'PushSubscription', + 'PushSubscriptionOptions', + 'RTCCertificate', + 'RTCDTMFSender', + 'RTCDTMFToneChangeEvent', + 'RTCDataChannel', + 'RTCDataChannelEvent', + 'RTCDtlsTransport', + 'RTCEncodedAudioFrame', + 'RTCEncodedVideoFrame', + 'RTCError', + 'RTCErrorEvent', + 'RTCIceCandidate', + 'RTCIceTransport', + 'RTCPeerConnection', + 'RTCPeerConnectionIceErrorEvent', + 'RTCPeerConnectionIceEvent', + 'RTCRtpReceiver', + 'RTCRtpSender', + 'RTCRtpTransceiver', + 'RTCSctpTransport', + 'RTCSessionDescription', + 'RTCStatsReport', + 'RTCTrackEvent', + 'RadioNodeList', + 'Range', + 'RangeError', + 'ReadableByteStreamController', + 'ReadableStream', + 'ReadableStreamBYOBReader', + 'ReadableStreamBYOBRequest', + 'ReadableStreamDefaultController', + 'ReadableStreamDefaultReader', + 'ReferenceError', + 'Reflect', + 'RegExp', + 'RemotePlayback', + 'Request', + 'ResizeObserver', + 'ResizeObserverEntry', + 'ResizeObserverSize', + 'Response', + 'SVGAElement', + 'SVGAngle', + 'SVGAnimateElement', + 'SVGAnimateMotionElement', + 'SVGAnimateTransformElement', + 'SVGAnimatedAngle', + 'SVGAnimatedBoolean', + 'SVGAnimatedEnumeration', + 'SVGAnimatedInteger', + 'SVGAnimatedLength', + 'SVGAnimatedLengthList', + 'SVGAnimatedNumber', + 'SVGAnimatedNumberList', + 'SVGAnimatedPreserveAspectRatio', + 'SVGAnimatedRect', + 'SVGAnimatedString', + 'SVGAnimatedTransformList', + 'SVGAnimationElement', + 'SVGCircleElement', + 'SVGClipPathElement', + 'SVGComponentTransferFunctionElement', + 'SVGCursorElement', + 'SVGDefsElement', + 'SVGDescElement', + 'SVGElement', + 'SVGEllipseElement', + 'SVGFEBlendElement', + 'SVGFEColorMatrixElement', + 'SVGFEComponentTransferElement', + 'SVGFECompositeElement', + 'SVGFEConvolveMatrixElement', + 'SVGFEDiffuseLightingElement', + 'SVGFEDisplacementMapElement', + 'SVGFEDistantLightElement', + 'SVGFEDropShadowElement', + 'SVGFEFloodElement', + 'SVGFEFuncAElement', + 'SVGFEFuncBElement', + 'SVGFEFuncGElement', + 'SVGFEFuncRElement', + 'SVGFEGaussianBlurElement', + 'SVGFEImageElement', + 'SVGFEMergeElement', + 'SVGFEMergeNodeElement', + 'SVGFEMorphologyElement', + 'SVGFEOffsetElement', + 'SVGFEPointLightElement', + 'SVGFESpecularLightingElement', + 'SVGFESpotLightElement', + 'SVGFETileElement', + 'SVGFETurbulenceElement', + 'SVGFilterElement', + 'SVGForeignObjectElement', + 'SVGGElement', + 'SVGGeometryElement', + 'SVGGradientElement', + 'SVGGraphicsElement', + 'SVGImageElement', + 'SVGLength', + 'SVGLengthList', + 'SVGLineElement', + 'SVGLinearGradientElement', + 'SVGMPathElement', + 'SVGMarkerElement', + 'SVGMaskElement', + 'SVGMatrix', + 'SVGMetadataElement', + 'SVGNumber', + 'SVGNumberList', + 'SVGPathElement', + 'SVGPatternElement', + 'SVGPoint', + 'SVGPointList', + 'SVGPolygonElement', + 'SVGPolylineElement', + 'SVGPreserveAspectRatio', + 'SVGRadialGradientElement', + 'SVGRect', + 'SVGRectElement', + 'SVGSVGElement', + 'SVGScriptElement', + 'SVGSetElement', + 'SVGStopElement', + 'SVGStringList', + 'SVGStyleElement', + 'SVGSwitchElement', + 'SVGSymbolElement', + 'SVGTSpanElement', + 'SVGTextContentElement', + 'SVGTextElement', + 'SVGTextPathElement', + 'SVGTextPositioningElement', + 'SVGTitleElement', + 'SVGTransform', + 'SVGTransformList', + 'SVGUnitTypes', + 'SVGUseElement', + 'SVGViewElement', + 'SafeArray', + 'Screen', + 'ScreenOrientation', + 'ScriptProcessorNode', + 'SecurityPolicyViolationEvent', + 'Selection', + 'ServiceWorker', + 'ServiceWorkerContainer', + 'ServiceWorkerRegistration', + 'Set', + 'ShadowRoot', + 'SharedArrayBuffer', + 'SharedWorker', + 'SourceBuffer', + 'SourceBufferList', + 'SpeechRecognitionAlternative', + 'SpeechRecognitionErrorEvent', + 'SpeechRecognitionResult', + 'SpeechRecognitionResultList', + 'SpeechSynthesis', + 'SpeechSynthesisErrorEvent', + 'SpeechSynthesisEvent', + 'SpeechSynthesisUtterance', + 'SpeechSynthesisVoice', + 'StaticRange', + 'StereoPannerNode', + 'Storage', + 'StorageEvent', + 'StorageManager', + 'String', + 'StyleMedia', + 'StyleSheet', + 'StyleSheetList', + 'SubmitEvent', + 'SubtleCrypto', + 'Symbol', + 'SyntaxError', + 'Text', + 'TextDecoder', + 'TextDecoderStream', + 'TextEncoder', + 'TextEncoderStream', + 'TextMetrics', + 'TextTrack', + 'TextTrackCue', + 'TextTrackCueList', + 'TextTrackList', + 'TimeRanges', + 'Touch', + 'TouchEvent', + 'TouchList', + 'TrackEvent', + 'TransformStream', + 'TransformStreamDefaultController', + 'TransitionEvent', + 'TreeWalker', + 'TypeError', + 'UIEvent', + 'URIError', + 'URL', + 'URLSearchParams', + 'Uint16Array', + 'Uint32Array', + 'Uint8Array', + 'Uint8ClampedArray', + 'VBArray', + 'VTTCue', + 'VTTRegion', + 'ValidityState', + 'VarDate', + 'VideoColorSpace', + 'VideoPlaybackQuality', + 'VisualViewport', + 'WSH', + 'WScript', + 'WaveShaperNode', + 'WeakMap', + 'WeakRef', + 'WeakSet', + 'WebAssembly', + 'WebGL2RenderingContext', + 'WebGLActiveInfo', + 'WebGLBuffer', + 'WebGLContextEvent', + 'WebGLFramebuffer', + 'WebGLProgram', + 'WebGLQuery', + 'WebGLRenderbuffer', + 'WebGLRenderingContext', + 'WebGLSampler', + 'WebGLShader', + 'WebGLShaderPrecisionFormat', + 'WebGLSync', + 'WebGLTexture', + 'WebGLTransformFeedback', + 'WebGLUniformLocation', + 'WebGLVertexArrayObject', + 'WebKitCSSMatrix', + 'WebSocket', + 'WheelEvent', + 'Window', + 'Worker', + 'Worklet', + 'WritableStream', + 'WritableStreamDefaultController', + 'WritableStreamDefaultWriter', + 'XMLDocument', + 'XMLHttpRequest', + 'XMLHttpRequestEventTarget', + 'XMLHttpRequestUpload', + 'XMLSerializer', + 'XPathEvaluator', + 'XPathExpression', + 'XPathResult', + 'XSLTProcessor', + 'addEventListener', + 'alert', + 'atob', + 'blur', + 'btoa', + 'caches', + 'cancelAnimationFrame', + 'cancelIdleCallback', + 'captureEvents', + 'clearInterval', + 'clearTimeout', + 'clientInformation', + 'close', + 'closed', + 'confirm', + 'console', + 'createImageBitmap', + 'crossOriginIsolated', + 'crypto', + 'customElements', + 'decodeURI', + 'decodeURIComponent', + 'devicePixelRatio', + 'dispatchEvent', + 'document', + 'encodeURI', + 'encodeURIComponent', + 'escape', + 'eval', + 'event', + 'external', + 'fetch', + 'focus', + 'frameElement', + 'frames', + 'getComputedStyle', + 'getSelection', + 'global', + 'globalThis', + 'history', + 'importScripts', + 'indexedDB', + 'innerHeight', + 'innerWidth', + 'isFinite', + 'isNaN', + 'isSecureContext', + 'length', + 'localStorage', + 'location', + 'locationbar', + 'matchMedia', + 'menubar', + 'moveBy', + 'moveTo', + 'name', + 'navigator', + 'onabort', + 'onafterprint', + 'onanimationcancel', + 'onanimationend', + 'onanimationiteration', + 'onanimationstart', + 'onauxclick', + 'onbeforeprint', + 'onbeforeunload', + 'onblur', + 'oncanplay', + 'oncanplaythrough', + 'onchange', + 'onclick', + 'onclose', + 'oncontextmenu', + 'oncuechange', + 'ondblclick', + 'ondevicemotion', + 'ondeviceorientation', + 'ondrag', + 'ondragend', + 'ondragenter', + 'ondragleave', + 'ondragover', + 'ondragstart', + 'ondrop', + 'ondurationchange', + 'onemptied', + 'onended', + 'onerror', + 'onfocus', + 'onformdata', + 'ongamepadconnected', + 'ongamepaddisconnected', + 'ongotpointercapture', + 'onhashchange', + 'oninput', + 'oninvalid', + 'onkeydown', + 'onkeypress', + 'onkeyup', + 'onlanguagechange', + 'onload', + 'onloadeddata', + 'onloadedmetadata', + 'onloadstart', + 'onlostpointercapture', + 'onmessage', + 'onmessageerror', + 'onmousedown', + 'onmouseenter', + 'onmouseleave', + 'onmousemove', + 'onmouseout', + 'onmouseover', + 'onmouseup', + 'onoffline', + 'ononline', + 'onorientationchange', + 'onpagehide', + 'onpageshow', + 'onpause', + 'onplay', + 'onplaying', + 'onpointercancel', + 'onpointerdown', + 'onpointerenter', + 'onpointerleave', + 'onpointermove', + 'onpointerout', + 'onpointerover', + 'onpointerup', + 'onpopstate', + 'onprogress', + 'onratechange', + 'onrejectionhandled', + 'onreset', + 'onresize', + 'onscroll', + 'onsecuritypolicyviolation', + 'onseeked', + 'onseeking', + 'onselect', + 'onselectionchange', + 'onselectstart', + 'onslotchange', + 'onstalled', + 'onstorage', + 'onsubmit', + 'onsuspend', + 'ontimeupdate', + 'ontoggle', + 'ontouchcancel', + 'ontouchend', + 'ontouchmove', + 'ontouchstart', + 'ontransitioncancel', + 'ontransitionend', + 'ontransitionrun', + 'ontransitionstart', + 'onunhandledrejection', + 'onunload', + 'onvolumechange', + 'onwaiting', + 'onwebkitanimationend', + 'onwebkitanimationiteration', + 'onwebkitanimationstart', + 'onwebkittransitionend', + 'onwheel', + 'open', + 'opener', + 'orientation', + 'origin', + 'outerHeight', + 'outerWidth', + 'pageXOffset', + 'pageYOffset', + 'parent', + 'parseFloat', + 'parseInt', + 'performance', + 'personalbar', + 'postMessage', + 'print', + 'process', + 'prompt', + 'queueMicrotask', + 'releaseEvents', + 'removeEventListener', + 'reportError', + 'requestAnimationFrame', + 'requestIdleCallback', + 'resizeBy', + 'resizeTo', + 'screen', + 'screenLeft', + 'screenTop', + 'screenX', + 'screenY', + 'scroll', + 'scrollBy', + 'scrollTo', + 'scrollX', + 'scrollY', + 'scrollbars', + 'self', + 'sessionStorage', + 'setInterval', + 'setTimeout', + 'speechSynthesis', + 'status', + 'statusbar', + 'stop', + 'structuredClone', + 'toString', + 'toolbar', + 'top', + 'undefined', + 'unescape', + 'visualViewport', + 'webkitURL', + 'window' +]); diff --git a/src/compiler/utils/names.ts b/src/compiler/utils/names.ts index e091edb19e..9d5b78fceb 100644 --- a/src/compiler/utils/names.ts +++ b/src/compiler/utils/names.ts @@ -1,71 +1,6 @@ import { isIdentifierStart, isIdentifierChar } from 'acorn'; import full_char_code_at from './full_char_code_at'; -export const globals = new Set([ - 'alert', - 'Array', - 'BigInt', - 'Boolean', - 'clearInterval', - 'clearTimeout', - 'confirm', - 'console', - 'Date', - 'decodeURI', - 'decodeURIComponent', - 'document', - 'Element', - 'encodeURI', - 'encodeURIComponent', - 'Error', - 'EvalError', - 'Event', - 'EventSource', - 'fetch', - 'FormData', - 'global', - 'globalThis', - 'history', - 'HTMLElement', - 'Infinity', - 'InternalError', - 'Intl', - 'isFinite', - 'isNaN', - 'JSON', - 'localStorage', - 'location', - 'Map', - 'Math', - 'NaN', - 'navigator', - 'Node', - 'Number', - 'Object', - 'parseFloat', - 'parseInt', - 'process', - 'Promise', - 'prompt', - 'RangeError', - 'ReferenceError', - 'RegExp', - 'sessionStorage', - 'Set', - 'setInterval', - 'setTimeout', - 'String', - 'SVGElement', - 'Symbol', - 'SyntaxError', - 'TypeError', - 'undefined', - 'URIError', - 'URL', - 'URLSearchParams', - 'window' -]); - export const reserved = new Set([ 'arguments', 'await', From ed078e31fe1d3594c105a17f7fb6def769b386f6 Mon Sep 17 00:00:00 2001 From: Yuichiro Yamashita Date: Sun, 4 Sep 2022 19:08:46 +0900 Subject: [PATCH 032/145] update changelog (#7835) --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 92155c0be8..18c0b63d06 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## Unreleased -* Add all global objects / functions ([#3805](https://github.com/sveltejs/svelte/issue/3805), [#7223](https://github.com/sveltejs/svelte/issue/7223), [#7240](https://github.com/sveltejs/svelte/issue/7240)) +* Add all global objects / functions ([#3805](https://github.com/sveltejs/svelte/issues/3805), [#7223](https://github.com/sveltejs/svelte/issues/7223)) ## 3.50.0 From 07d6d179abb7fb86f45cd5175820bbb1c5cbf0e9 Mon Sep 17 00:00:00 2001 From: Yuichiro Yamashita Date: Fri, 9 Sep 2022 05:49:57 +0900 Subject: [PATCH 033/145] [fix] style manager transition regression (#7831) --- src/runtime/internal/dom.ts | 8 +++++++- src/runtime/internal/style_manager.ts | 16 +++++++-------- test/runtime-puppeteer/index.ts | 17 ++++++++++++++-- .../samples/style_manager-cleanup/_config.js | 17 ++++++++++++++++ .../samples/style_manager-cleanup/main.svelte | 16 +++++++++++++++ .../samples/transition-css-out-in/_config.js | 14 +++++++++++++ .../samples/transition-css-out-in/main.svelte | 20 +++++++++++++++++++ .../samples/style_manager-cleanup/_config.js | 14 ------------- .../samples/style_manager-cleanup/main.svelte | 14 ------------- 9 files changed, 97 insertions(+), 39 deletions(-) create mode 100644 test/runtime-puppeteer/samples/style_manager-cleanup/_config.js create mode 100644 test/runtime-puppeteer/samples/style_manager-cleanup/main.svelte create mode 100644 test/runtime-puppeteer/samples/transition-css-out-in/_config.js create mode 100644 test/runtime-puppeteer/samples/transition-css-out-in/main.svelte delete mode 100644 test/runtime/samples/style_manager-cleanup/_config.js delete mode 100644 test/runtime/samples/style_manager-cleanup/main.svelte diff --git a/src/runtime/internal/dom.ts b/src/runtime/internal/dom.ts index 8a7d3af6da..e678481a5f 100644 --- a/src/runtime/internal/dom.ts +++ b/src/runtime/internal/dom.ts @@ -154,7 +154,13 @@ export function get_root_for_style(node: Node): ShadowRoot | Document { return node.ownerDocument; } -export function append_stylesheet(node: ShadowRoot | Document, style: HTMLStyleElement) { +export function append_empty_stylesheet(node: Node) { + const style_element = element('style') as HTMLStyleElement; + append_stylesheet(get_root_for_style(node), style_element); + return style_element.sheet as CSSStyleSheet; +} + +function append_stylesheet(node: ShadowRoot | Document, style: HTMLStyleElement) { append((node as Document).head || node, style); return style.sheet as CSSStyleSheet; } diff --git a/src/runtime/internal/style_manager.ts b/src/runtime/internal/style_manager.ts index 67236cabab..36dc1e6044 100644 --- a/src/runtime/internal/style_manager.ts +++ b/src/runtime/internal/style_manager.ts @@ -1,8 +1,8 @@ -import { append_stylesheet, detach, element, get_root_for_style } from './dom'; +import { append_empty_stylesheet, detach, get_root_for_style } from './dom'; import { raf } from './environment'; interface StyleInformation { - style_element: HTMLStyleElement; + stylesheet: CSSStyleSheet; rules: Record; } @@ -20,8 +20,8 @@ function hash(str: string) { return hash >>> 0; } -function create_style_information(doc: Document | ShadowRoot) { - const info = { style_element: element('style'), rules: {} }; +function create_style_information(doc: Document | ShadowRoot, node: Element & ElementCSSInlineStyle) { + const info = { stylesheet: append_empty_stylesheet(node), rules: {} }; managed_styles.set(doc, info); return info; } @@ -39,10 +39,9 @@ export function create_rule(node: Element & ElementCSSInlineStyle, a: number, b: const name = `__svelte_${hash(rule)}_${uid}`; const doc = get_root_for_style(node); - const { style_element, rules } = managed_styles.get(doc) || create_style_information(doc); + const { stylesheet, rules } = managed_styles.get(doc) || create_style_information(doc, node); if (!rules[name]) { - const stylesheet = append_stylesheet(doc, style_element); rules[name] = true; stylesheet.insertRule(`@keyframes ${name} ${rule}`, stylesheet.cssRules.length); } @@ -72,8 +71,9 @@ export function clear_rules() { raf(() => { if (active) return; managed_styles.forEach(info => { - const { style_element } = info; - detach(style_element); + const { ownerNode } = info.stylesheet; + // there is no ownerNode if it runs on jsdom. + if (ownerNode) detach(ownerNode); }); managed_styles.clear(); }); diff --git a/test/runtime-puppeteer/index.ts b/test/runtime-puppeteer/index.ts index 8e6f813de4..62952ad9f7 100644 --- a/test/runtime-puppeteer/index.ts +++ b/test/runtime-puppeteer/index.ts @@ -117,8 +117,12 @@ describe('runtime (puppeteer)', function() { load(id) { if (id === 'main') { return ` - import SvelteComponent from ${JSON.stringify(path.join(__dirname, 'samples', dir, 'main.svelte'))}; - import config from ${JSON.stringify(path.join(__dirname, 'samples', dir, '_config.js'))}; + import SvelteComponent from ${JSON.stringify( + path.join(__dirname, 'samples', dir, 'main.svelte') + )}; + import config from ${JSON.stringify( + path.join(__dirname, 'samples', dir, '_config.js') + )}; import * as assert from 'assert'; export default async function (target) { @@ -140,6 +144,14 @@ describe('runtime (puppeteer)', function() { const component = new SvelteComponent(options); + const waitUntil = async (fn, ms = 500) => { + const start = new Date().getTime(); + do { + if (fn()) return; + await new Promise(resolve => window.setTimeout(resolve, 1)); + } while (new Date().getTime() <= start + ms); + }; + if (config.html) { assert.htmlEqual(target.innerHTML, config.html); } @@ -150,6 +162,7 @@ describe('runtime (puppeteer)', function() { component, target, window, + waitUntil, }); component.$destroy(); diff --git a/test/runtime-puppeteer/samples/style_manager-cleanup/_config.js b/test/runtime-puppeteer/samples/style_manager-cleanup/_config.js new file mode 100644 index 0000000000..b3a5a97e45 --- /dev/null +++ b/test/runtime-puppeteer/samples/style_manager-cleanup/_config.js @@ -0,0 +1,17 @@ +export default { + skip_if_ssr: true, + skip_if_hydrate: true, + skip_if_hydrate_from_ssr: true, + test: async ({ component, assert, window, waitUntil }) => { + assert.htmlEqual(window.document.head.innerHTML, ''); + component.visible = true; + assert.htmlEqual(window.document.head.innerHTML, ''); + await waitUntil(() => window.document.head.innerHTML === ''); + assert.htmlEqual(window.document.head.innerHTML, ''); + + component.visible = false; + assert.htmlEqual(window.document.head.innerHTML, ''); + await waitUntil(() => window.document.head.innerHTML === ''); + assert.htmlEqual(window.document.head.innerHTML, ''); + } +}; diff --git a/test/runtime-puppeteer/samples/style_manager-cleanup/main.svelte b/test/runtime-puppeteer/samples/style_manager-cleanup/main.svelte new file mode 100644 index 0000000000..ab13073b1e --- /dev/null +++ b/test/runtime-puppeteer/samples/style_manager-cleanup/main.svelte @@ -0,0 +1,16 @@ + + +{#if visible} +
      +{/if} diff --git a/test/runtime-puppeteer/samples/transition-css-out-in/_config.js b/test/runtime-puppeteer/samples/transition-css-out-in/_config.js new file mode 100644 index 0000000000..a50d28b257 --- /dev/null +++ b/test/runtime-puppeteer/samples/transition-css-out-in/_config.js @@ -0,0 +1,14 @@ +export default { + test: async ({ assert, component, window, waitUntil }) => { + component.visible = true; + await waitUntil(() => window.document.head.querySelector('style').sheet.rules.length === 2); + assert.equal(window.document.head.querySelector('style').sheet.rules.length, 2); + await waitUntil(() => window.document.head.querySelector('style') === null); + assert.equal(window.document.head.querySelector('style'), null); + component.visible = false; + await waitUntil(() => window.document.head.querySelector('style').sheet.rules.length === 2); + assert.equal(window.document.head.querySelector('style').sheet.rules.length, 2); + await waitUntil(() => window.document.head.querySelector('style') === null); + assert.equal(window.document.head.querySelector('style'), null); + } +}; diff --git a/test/runtime-puppeteer/samples/transition-css-out-in/main.svelte b/test/runtime-puppeteer/samples/transition-css-out-in/main.svelte new file mode 100644 index 0000000000..3ee93f0b55 --- /dev/null +++ b/test/runtime-puppeteer/samples/transition-css-out-in/main.svelte @@ -0,0 +1,20 @@ + + +{#if visible} +
      +{/if} + +{#if !visible} +
      +{/if} diff --git a/test/runtime/samples/style_manager-cleanup/_config.js b/test/runtime/samples/style_manager-cleanup/_config.js deleted file mode 100644 index 7609d76cf2..0000000000 --- a/test/runtime/samples/style_manager-cleanup/_config.js +++ /dev/null @@ -1,14 +0,0 @@ -export default { - skip_if_ssr: true, - skip_if_hydrate: true, - skip_if_hydrate_from_ssr: true, - test({ raf, assert, component, window }) { - component.visible = true; - raf.tick(100); - component.visible = false; - raf.tick(200); - raf.tick(0); - - assert.htmlEqual(window.document.head.innerHTML, ''); - } -}; diff --git a/test/runtime/samples/style_manager-cleanup/main.svelte b/test/runtime/samples/style_manager-cleanup/main.svelte deleted file mode 100644 index c2ccdc7c09..0000000000 --- a/test/runtime/samples/style_manager-cleanup/main.svelte +++ /dev/null @@ -1,14 +0,0 @@ - - - {#if visible} -
      - {/if} \ No newline at end of file From 24aff3032d7af26162fb6a319b07131d21739e9c Mon Sep 17 00:00:00 2001 From: Conduitry Date: Thu, 8 Sep 2022 16:52:21 -0400 Subject: [PATCH 034/145] -> v3.50.1 --- CHANGELOG.md | 5 +++-- package-lock.json | 2 +- package.json | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 18c0b63d06..a90eb4aa3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,9 @@ # Svelte changelog -## Unreleased +## 3.50.1 -* Add all global objects / functions ([#3805](https://github.com/sveltejs/svelte/issues/3805), [#7223](https://github.com/sveltejs/svelte/issues/7223)) +* Add all global objects and functions as known globals ([#3805](https://github.com/sveltejs/svelte/issues/3805), [#7223](https://github.com/sveltejs/svelte/issues/7223)) +* Fix regression with style manager ([#7828](https://github.com/sveltejs/svelte/issues/7828)) ## 3.50.0 diff --git a/package-lock.json b/package-lock.json index 8beef8470a..23ccc6b66f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "svelte", - "version": "3.50.0", + "version": "3.50.1", "lockfileVersion": 2, "requires": true, "packages": { diff --git a/package.json b/package.json index 3e22d8b627..836fa33267 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "svelte", - "version": "3.50.0", + "version": "3.50.1", "description": "Cybernetically enhanced web apps", "module": "index.mjs", "main": "index", From 7ac3854613ebad0b30a1d1b8dc0a2a34542a8de5 Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Sat, 10 Sep 2022 14:00:50 -0700 Subject: [PATCH 035/145] [docs] remove beta label from SvelteKit mention (#7853) --- site/content/faq/900-is-there-a-router.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/content/faq/900-is-there-a-router.md b/site/content/faq/900-is-there-a-router.md index 9d50bbe490..2f11e0e626 100644 --- a/site/content/faq/900-is-there-a-router.md +++ b/site/content/faq/900-is-there-a-router.md @@ -2,7 +2,7 @@ question: Is there a router? --- -The official routing library is [SvelteKit](https://kit.svelte.dev/), which is currently in beta. SvelteKit provides a filesystem router, server-side rendering (SSR), and hot module reloading (HMR) in one easy-to-use package. It shares similarities with Next.js for React. +The official routing library is [SvelteKit](https://kit.svelte.dev/). SvelteKit provides a filesystem router, server-side rendering (SSR), and hot module reloading (HMR) in one easy-to-use package. It shares similarities with Next.js for React. However, you can use any router lib you want. A lot of people use [page.js](https://github.com/visionmedia/page.js). There's also [navaid](https://github.com/lukeed/navaid), which is very similar. And [universal-router](https://github.com/kriasoft/universal-router), which is isomorphic with child routes, but without built-in history support. From 8ffc8fd77bf667fdf41bb1f08ed4d1da6641320f Mon Sep 17 00:00:00 2001 From: Maximiliano Ruani Date: Sun, 11 Sep 2022 15:35:17 -0300 Subject: [PATCH 036/145] [fix] Fix hydration duplicate `svelte:head` tag issue with `@html` expressions and nested components (#7745) * Fix hydration duplicate `svelte:head` tag issue with `@html` and nested components #7444 #6463 * - Changed comment style to HEAD_${head_id}_START and HEAD_${head_id}_END - Improved claim logic - Changed tests accordingly --- .../compile/render_dom/wrappers/Head.ts | 2 +- .../compile/render_ssr/handlers/Element.ts | 4 ---- .../compile/render_ssr/handlers/Head.ts | 2 +- src/runtime/internal/dom.ts | 21 +++++++++++++++++++ .../head-html-and-component/HeadNested.svelte | 2 ++ .../head-html-and-component/Nested.svelte | 5 +++++ .../head-html-and-component/_after.html | 0 .../head-html-and-component/_after_head.html | 12 +++++++++++ .../head-html-and-component/_before.html | 0 .../head-html-and-component/_before_head.html | 11 ++++++++++ .../head-html-and-component/main.svelte | 12 +++++++++++ .../_after_head.html | 8 ++++--- .../_before_head.html | 8 ++++--- .../head-html-and-component/HeadNested.svelte | 2 ++ .../head-html-and-component/Nested.svelte | 5 +++++ .../_expected-head.html | 11 ++++++++++ .../head-html-and-component/_expected.html | 0 .../head-html-and-component/main.svelte | 12 +++++++++++ .../_expected-head.html | 8 ++++--- 19 files changed, 110 insertions(+), 15 deletions(-) create mode 100644 test/hydration/samples/head-html-and-component/HeadNested.svelte create mode 100644 test/hydration/samples/head-html-and-component/Nested.svelte create mode 100644 test/hydration/samples/head-html-and-component/_after.html create mode 100644 test/hydration/samples/head-html-and-component/_after_head.html create mode 100644 test/hydration/samples/head-html-and-component/_before.html create mode 100644 test/hydration/samples/head-html-and-component/_before_head.html create mode 100644 test/hydration/samples/head-html-and-component/main.svelte create mode 100644 test/server-side-rendering/samples/head-html-and-component/HeadNested.svelte create mode 100644 test/server-side-rendering/samples/head-html-and-component/Nested.svelte create mode 100644 test/server-side-rendering/samples/head-html-and-component/_expected-head.html create mode 100644 test/server-side-rendering/samples/head-html-and-component/_expected.html create mode 100644 test/server-side-rendering/samples/head-html-and-component/main.svelte diff --git a/src/compiler/compile/render_dom/wrappers/Head.ts b/src/compiler/compile/render_dom/wrappers/Head.ts index e0b723d6dd..3869994ae4 100644 --- a/src/compiler/compile/render_dom/wrappers/Head.ts +++ b/src/compiler/compile/render_dom/wrappers/Head.ts @@ -36,7 +36,7 @@ export default class HeadWrapper extends Wrapper { let nodes; if (this.renderer.options.hydratable && this.fragment.nodes.length) { nodes = block.get_unique_name('head_nodes'); - block.chunks.claim.push(b`const ${nodes} = @query_selector_all('[data-svelte="${this.node.id}"]', @_document.head);`); + block.chunks.claim.push(b`const ${nodes} = @head_selector('${this.node.id}', @_document.head);`); } this.fragment.render(block, x`@_document.head` as unknown as Identifier, nodes); diff --git a/src/compiler/compile/render_ssr/handlers/Element.ts b/src/compiler/compile/render_ssr/handlers/Element.ts index 7f7672349e..2af0343b2a 100644 --- a/src/compiler/compile/render_ssr/handlers/Element.ts +++ b/src/compiler/compile/render_ssr/handlers/Element.ts @@ -157,10 +157,6 @@ export default function (node: Element, renderer: Renderer, options: RenderOptio } }); - if (options.hydratable && options.head_id) { - renderer.add_string(` data-svelte="${options.head_id}"`); - } - renderer.add_string('>'); if (node_contents !== undefined) { diff --git a/src/compiler/compile/render_ssr/handlers/Head.ts b/src/compiler/compile/render_ssr/handlers/Head.ts index cf1e6bd555..f4bb3fa118 100644 --- a/src/compiler/compile/render_ssr/handlers/Head.ts +++ b/src/compiler/compile/render_ssr/handlers/Head.ts @@ -12,5 +12,5 @@ export default function(node: Head, renderer: Renderer, options: RenderOptions) renderer.render(node.children, head_options); const result = renderer.pop(); - renderer.add_expression(x`$$result.head += ${result}, ""`); + renderer.add_expression(x`$$result.head += '' + ${result} + '', ""`); } diff --git a/src/runtime/internal/dom.ts b/src/runtime/internal/dom.ts index e678481a5f..090b8925e1 100644 --- a/src/runtime/internal/dom.ts +++ b/src/runtime/internal/dom.ts @@ -646,6 +646,27 @@ export function query_selector_all(selector: string, parent: HTMLElement = docum return Array.from(parent.querySelectorAll(selector)) as ChildNodeArray; } +export function head_selector(nodeId: string, head: HTMLElement) { + const result = []; + let started = 0; + + for (const node of head.childNodes) { + if (node.nodeType === 8 /* comment node */) { + const comment = node.textContent.trim(); + if (comment === `HEAD_${nodeId}_END`) { + started -= 1; + result.push(node); + } else if (comment === `HEAD_${nodeId}_START`) { + started += 1; + result.push(node); + } + } else if (started > 0) { + result.push(node); + } + } + return result; +} + export class HtmlTag { private is_svg = false; // parent for creating node diff --git a/test/hydration/samples/head-html-and-component/HeadNested.svelte b/test/hydration/samples/head-html-and-component/HeadNested.svelte new file mode 100644 index 0000000000..33bbdd1fd1 --- /dev/null +++ b/test/hydration/samples/head-html-and-component/HeadNested.svelte @@ -0,0 +1,2 @@ +{@html ''} + diff --git a/test/hydration/samples/head-html-and-component/Nested.svelte b/test/hydration/samples/head-html-and-component/Nested.svelte new file mode 100644 index 0000000000..28f5371910 --- /dev/null +++ b/test/hydration/samples/head-html-and-component/Nested.svelte @@ -0,0 +1,5 @@ + + + {@html ''} + + diff --git a/test/hydration/samples/head-html-and-component/_after.html b/test/hydration/samples/head-html-and-component/_after.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/hydration/samples/head-html-and-component/_after_head.html b/test/hydration/samples/head-html-and-component/_after_head.html new file mode 100644 index 0000000000..d7f94eda1b --- /dev/null +++ b/test/hydration/samples/head-html-and-component/_after_head.html @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/test/hydration/samples/head-html-and-component/_before.html b/test/hydration/samples/head-html-and-component/_before.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/hydration/samples/head-html-and-component/_before_head.html b/test/hydration/samples/head-html-and-component/_before_head.html new file mode 100644 index 0000000000..da265f414d --- /dev/null +++ b/test/hydration/samples/head-html-and-component/_before_head.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/test/hydration/samples/head-html-and-component/main.svelte b/test/hydration/samples/head-html-and-component/main.svelte new file mode 100644 index 0000000000..188ecace6b --- /dev/null +++ b/test/hydration/samples/head-html-and-component/main.svelte @@ -0,0 +1,12 @@ + + + + {@html ''} + + + + + diff --git a/test/hydration/samples/head-meta-hydrate-duplicate/_after_head.html b/test/hydration/samples/head-meta-hydrate-duplicate/_after_head.html index be7a01ba4f..bdd08c32f5 100644 --- a/test/hydration/samples/head-meta-hydrate-duplicate/_after_head.html +++ b/test/hydration/samples/head-meta-hydrate-duplicate/_after_head.html @@ -1,4 +1,6 @@ Some Title - - - + + + + + diff --git a/test/hydration/samples/head-meta-hydrate-duplicate/_before_head.html b/test/hydration/samples/head-meta-hydrate-duplicate/_before_head.html index 107753cdd0..bdd08c32f5 100644 --- a/test/hydration/samples/head-meta-hydrate-duplicate/_before_head.html +++ b/test/hydration/samples/head-meta-hydrate-duplicate/_before_head.html @@ -1,4 +1,6 @@ Some Title - - - \ No newline at end of file + + + + + diff --git a/test/server-side-rendering/samples/head-html-and-component/HeadNested.svelte b/test/server-side-rendering/samples/head-html-and-component/HeadNested.svelte new file mode 100644 index 0000000000..33bbdd1fd1 --- /dev/null +++ b/test/server-side-rendering/samples/head-html-and-component/HeadNested.svelte @@ -0,0 +1,2 @@ +{@html ''} + diff --git a/test/server-side-rendering/samples/head-html-and-component/Nested.svelte b/test/server-side-rendering/samples/head-html-and-component/Nested.svelte new file mode 100644 index 0000000000..28f5371910 --- /dev/null +++ b/test/server-side-rendering/samples/head-html-and-component/Nested.svelte @@ -0,0 +1,5 @@ + + + {@html ''} + + diff --git a/test/server-side-rendering/samples/head-html-and-component/_expected-head.html b/test/server-side-rendering/samples/head-html-and-component/_expected-head.html new file mode 100644 index 0000000000..da265f414d --- /dev/null +++ b/test/server-side-rendering/samples/head-html-and-component/_expected-head.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/test/server-side-rendering/samples/head-html-and-component/_expected.html b/test/server-side-rendering/samples/head-html-and-component/_expected.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/server-side-rendering/samples/head-html-and-component/main.svelte b/test/server-side-rendering/samples/head-html-and-component/main.svelte new file mode 100644 index 0000000000..188ecace6b --- /dev/null +++ b/test/server-side-rendering/samples/head-html-and-component/main.svelte @@ -0,0 +1,12 @@ + + + + {@html ''} + + + + + diff --git a/test/server-side-rendering/samples/head-meta-hydrate-duplicate/_expected-head.html b/test/server-side-rendering/samples/head-meta-hydrate-duplicate/_expected-head.html index 107753cdd0..bdd08c32f5 100644 --- a/test/server-side-rendering/samples/head-meta-hydrate-duplicate/_expected-head.html +++ b/test/server-side-rendering/samples/head-meta-hydrate-duplicate/_expected-head.html @@ -1,4 +1,6 @@ Some Title - - - \ No newline at end of file + + + + + From adcaa3c0503cacd7b61129bfebba8972cc49b661 Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Mon, 12 Sep 2022 02:41:18 +0800 Subject: [PATCH 037/145] Update CHANGELOG.md --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a90eb4aa3d..9612c8c53f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Svelte changelog +## Unreleased + +* Fix hydration issue with using `{@html}` and components in `svelte:head` ([#4533](https://github.com/sveltejs/svelte/issues/4533), [#6463](https://github.com/sveltejs/svelte/issues/6463), [#7444](https://github.com/sveltejs/svelte/issues/7444)) + ## 3.50.1 * Add all global objects and functions as known globals ([#3805](https://github.com/sveltejs/svelte/issues/3805), [#7223](https://github.com/sveltejs/svelte/issues/7223)) From 1e2a55c88e753cefc6acc668c83fee6cdbc70f31 Mon Sep 17 00:00:00 2001 From: Yuichiro Yamashita Date: Mon, 12 Sep 2022 03:48:13 +0900 Subject: [PATCH 038/145] throw warning instead of error (#7834) --- src/runtime/internal/dev.ts | 4 +++- .../dynamic-element-void-with-content-1/_config.js | 2 +- .../dynamic-element-void-with-content-2/_config.js | 2 +- .../dynamic-element-void-with-content-3/_config.js | 2 +- .../dynamic-element-void-with-content-5/_config.js | 6 ++++++ .../dynamic-element-void-with-content-5/main.svelte | 10 ++++++++++ 6 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 test/runtime/samples/dynamic-element-void-with-content-5/_config.js create mode 100644 test/runtime/samples/dynamic-element-void-with-content-5/main.svelte diff --git a/src/runtime/internal/dev.ts b/src/runtime/internal/dev.ts index df40f94230..02677172fa 100644 --- a/src/runtime/internal/dev.ts +++ b/src/runtime/internal/dev.ts @@ -117,7 +117,9 @@ export function validate_dynamic_element(tag: unknown) { export function validate_void_dynamic_element(tag: undefined | string) { if (tag && is_void(tag)) { - throw new Error(` is self-closing and cannot have content.`); + console.warn( + ` is self-closing and cannot have content.` + ); } } diff --git a/test/runtime/samples/dynamic-element-void-with-content-1/_config.js b/test/runtime/samples/dynamic-element-void-with-content-1/_config.js index 4016725e21..2888a8437b 100644 --- a/test/runtime/samples/dynamic-element-void-with-content-1/_config.js +++ b/test/runtime/samples/dynamic-element-void-with-content-1/_config.js @@ -5,5 +5,5 @@ export default { props: { tag: 'br' }, - error: ' is self-closing and cannot have content.' + warnings: [' is self-closing and cannot have content.'] }; diff --git a/test/runtime/samples/dynamic-element-void-with-content-2/_config.js b/test/runtime/samples/dynamic-element-void-with-content-2/_config.js index 4016725e21..2888a8437b 100644 --- a/test/runtime/samples/dynamic-element-void-with-content-2/_config.js +++ b/test/runtime/samples/dynamic-element-void-with-content-2/_config.js @@ -5,5 +5,5 @@ export default { props: { tag: 'br' }, - error: ' is self-closing and cannot have content.' + warnings: [' is self-closing and cannot have content.'] }; diff --git a/test/runtime/samples/dynamic-element-void-with-content-3/_config.js b/test/runtime/samples/dynamic-element-void-with-content-3/_config.js index 4016725e21..2888a8437b 100644 --- a/test/runtime/samples/dynamic-element-void-with-content-3/_config.js +++ b/test/runtime/samples/dynamic-element-void-with-content-3/_config.js @@ -5,5 +5,5 @@ export default { props: { tag: 'br' }, - error: ' is self-closing and cannot have content.' + warnings: [' is self-closing and cannot have content.'] }; diff --git a/test/runtime/samples/dynamic-element-void-with-content-5/_config.js b/test/runtime/samples/dynamic-element-void-with-content-5/_config.js new file mode 100644 index 0000000000..6e56f6bdba --- /dev/null +++ b/test/runtime/samples/dynamic-element-void-with-content-5/_config.js @@ -0,0 +1,6 @@ +export default { + compileOptions: { + dev: true + }, + warnings: [' is self-closing and cannot have content.'] +}; diff --git a/test/runtime/samples/dynamic-element-void-with-content-5/main.svelte b/test/runtime/samples/dynamic-element-void-with-content-5/main.svelte new file mode 100644 index 0000000000..990772b1e6 --- /dev/null +++ b/test/runtime/samples/dynamic-element-void-with-content-5/main.svelte @@ -0,0 +1,10 @@ + + +{#each tags as tag} + {tag.t}
      + + {#if tag.t !== 'input'}{tag.content}{/if} + +{/each} From 2f6afefab053a52b8dac31aee35635df837c8f61 Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Mon, 12 Sep 2022 02:49:22 +0800 Subject: [PATCH 039/145] Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9612c8c53f..1d8ad6f630 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ ## Unreleased * Fix hydration issue with using `{@html}` and components in `svelte:head` ([#4533](https://github.com/sveltejs/svelte/issues/4533), [#6463](https://github.com/sveltejs/svelte/issues/6463), [#7444](https://github.com/sveltejs/svelte/issues/7444)) +* Warn instead of throwing error if `` is void tag ([#7566](https://github.com/sveltejs/svelte/issues/7566)) + ## 3.50.1 From a5ca0ad65be5b79c51c9653f1ec16e84fbabba24 Mon Sep 17 00:00:00 2001 From: Yuichiro Yamashita Date: Mon, 12 Sep 2022 04:03:02 +0900 Subject: [PATCH 040/145] [fix] added support for inert (remove duplicated code) (#7785) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: added support for inert * remove duplicated boolean_attributes Co-authored-by: Gautier Ben Aïm <48261497+GauBen@users.noreply.github.com> --- .../render_dom/wrappers/Element/Attribute.ts | 32 ++----------------- src/shared/boolean_attributes.ts | 2 ++ 2 files changed, 4 insertions(+), 30 deletions(-) diff --git a/src/compiler/compile/render_dom/wrappers/Element/Attribute.ts b/src/compiler/compile/render_dom/wrappers/Element/Attribute.ts index 7b6aed0d5a..21a44ab92a 100644 --- a/src/compiler/compile/render_dom/wrappers/Element/Attribute.ts +++ b/src/compiler/compile/render_dom/wrappers/Element/Attribute.ts @@ -9,6 +9,7 @@ import Text from '../../../nodes/Text'; import handle_select_value_binding from './handle_select_value_binding'; import { Identifier, Node } from 'estree'; import { namespaces } from '../../../../utils/namespaces'; +import { boolean_attributes } from '../../../../../shared/boolean_attributes'; const non_textlike_input_types = new Set([ 'button', @@ -255,7 +256,7 @@ export default class AttributeWrapper extends BaseAttributeWrapper { get_value(block) { if (this.node.is_true) { - if (this.metadata && boolean_attribute.has(this.metadata.property_name.toLowerCase())) { + if (this.metadata && boolean_attributes.has(this.metadata.property_name.toLowerCase())) { return x`true`; } return x`""`; @@ -376,35 +377,6 @@ Object.keys(attribute_lookup).forEach(name => { if (!metadata.property_name) metadata.property_name = name; }); -// source: https://html.spec.whatwg.org/multipage/indices.html -const boolean_attribute = new Set([ - 'allowfullscreen', - 'allowpaymentrequest', - 'async', - 'autofocus', - 'autoplay', - 'checked', - 'controls', - 'default', - 'defer', - 'disabled', - 'formnovalidate', - 'hidden', - 'ismap', - 'itemscope', - 'loop', - 'multiple', - 'muted', - 'nomodule', - 'novalidate', - 'open', - 'playsinline', - 'readonly', - 'required', - 'reversed', - 'selected' -]); - function should_cache(attribute: AttributeWrapper) { return attribute.is_src || attribute.node.should_cache(); } diff --git a/src/shared/boolean_attributes.ts b/src/shared/boolean_attributes.ts index 4520a2064e..e29f921e32 100644 --- a/src/shared/boolean_attributes.ts +++ b/src/shared/boolean_attributes.ts @@ -12,7 +12,9 @@ export const boolean_attributes = new Set([ 'disabled', 'formnovalidate', 'hidden', + 'inert', 'ismap', + 'itemscope', 'loop', 'multiple', 'muted', From 78a249be36b1fa75a59755452554a531d0d4194a Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Mon, 12 Sep 2022 03:04:47 +0800 Subject: [PATCH 041/145] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d8ad6f630..711e8a3d90 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * Fix hydration issue with using `{@html}` and components in `svelte:head` ([#4533](https://github.com/sveltejs/svelte/issues/4533), [#6463](https://github.com/sveltejs/svelte/issues/6463), [#7444](https://github.com/sveltejs/svelte/issues/7444)) * Warn instead of throwing error if `` is void tag ([#7566](https://github.com/sveltejs/svelte/issues/7566)) +* Treat `inert` as boolean attribute ([#7785](https://github.com/sveltejs/svelte/pull/7785)) ## 3.50.1 From e2ef2b8731a897b36d81d130c78cd4a9019aa41f Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Sun, 11 Sep 2022 21:14:47 +0200 Subject: [PATCH 042/145] apply class for dynamic elements (#7652) --- src/compiler/compile/css/Selector.ts | 2 +- .../samples/dynamic-element-tag/_config.js | 3 ++ .../samples/dynamic-element-tag/expected.css | 1 + .../samples/dynamic-element-tag/expected.html | 4 +++ .../samples/dynamic-element-tag/input.svelte | 32 +++++++++++++++++++ 5 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 test/css/samples/dynamic-element-tag/_config.js create mode 100644 test/css/samples/dynamic-element-tag/expected.css create mode 100644 test/css/samples/dynamic-element-tag/expected.html create mode 100644 test/css/samples/dynamic-element-tag/input.svelte diff --git a/src/compiler/compile/css/Selector.ts b/src/compiler/compile/css/Selector.ts index d61ba1f510..17302c4abd 100644 --- a/src/compiler/compile/css/Selector.ts +++ b/src/compiler/compile/css/Selector.ts @@ -311,7 +311,7 @@ function block_might_apply_to_node(block: Block, node: Element): BlockAppliesToN return BlockAppliesToNode.NotPossible; } } else if (selector.type === 'TypeSelector') { - if (node.name.toLowerCase() !== name.toLowerCase() && name !== '*') return BlockAppliesToNode.NotPossible; + if (node.name.toLowerCase() !== name.toLowerCase() && name !== '*' && !node.is_dynamic_element) return BlockAppliesToNode.NotPossible; } else { return BlockAppliesToNode.UnknownSelectorType; } diff --git a/test/css/samples/dynamic-element-tag/_config.js b/test/css/samples/dynamic-element-tag/_config.js new file mode 100644 index 0000000000..c81f1a9f82 --- /dev/null +++ b/test/css/samples/dynamic-element-tag/_config.js @@ -0,0 +1,3 @@ +export default { + warnings: [] +}; diff --git a/test/css/samples/dynamic-element-tag/expected.css b/test/css/samples/dynamic-element-tag/expected.css new file mode 100644 index 0000000000..6af254e948 --- /dev/null +++ b/test/css/samples/dynamic-element-tag/expected.css @@ -0,0 +1 @@ +div.svelte-xyz.svelte-xyz.svelte-xyz{color:red}h2.svelte-xyz>p.svelte-xyz.svelte-xyz{color:red}h2.svelte-xyz span.svelte-xyz.svelte-xyz{color:red}h2.svelte-xyz>span.svelte-xyz>b.svelte-xyz{color:red}h2.svelte-xyz span b.svelte-xyz.svelte-xyz{color:red}h2.svelte-xyz b.svelte-xyz.svelte-xyz{color:red} \ No newline at end of file diff --git a/test/css/samples/dynamic-element-tag/expected.html b/test/css/samples/dynamic-element-tag/expected.html new file mode 100644 index 0000000000..509ad1d839 --- /dev/null +++ b/test/css/samples/dynamic-element-tag/expected.html @@ -0,0 +1,4 @@ +
      +

      +
      text
      +

      diff --git a/test/css/samples/dynamic-element-tag/input.svelte b/test/css/samples/dynamic-element-tag/input.svelte new file mode 100644 index 0000000000..6e8851b3f9 --- /dev/null +++ b/test/css/samples/dynamic-element-tag/input.svelte @@ -0,0 +1,32 @@ + + + + +

      + + text + +

      + + From 1afcfd2b5f30216164c582d703eb29a6ad4bd831 Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Mon, 12 Sep 2022 03:15:45 +0800 Subject: [PATCH 043/145] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 711e8a3d90..25d819449d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * Fix hydration issue with using `{@html}` and components in `svelte:head` ([#4533](https://github.com/sveltejs/svelte/issues/4533), [#6463](https://github.com/sveltejs/svelte/issues/6463), [#7444](https://github.com/sveltejs/svelte/issues/7444)) * Warn instead of throwing error if `` is void tag ([#7566](https://github.com/sveltejs/svelte/issues/7566)) * Treat `inert` as boolean attribute ([#7785](https://github.com/sveltejs/svelte/pull/7785)) +* Supporting scoped style for `` ([#7443](https://github.com/sveltejs/svelte/issues/7443)) ## 3.50.1 From 6ec8ecf7999ad74ce8cf735a98adca630f9de105 Mon Sep 17 00:00:00 2001 From: Mathias Picker <48158184+MathiasWP@users.noreply.github.com> Date: Sun, 11 Sep 2022 21:22:17 +0200 Subject: [PATCH 044/145] [fix] render of svg elements when using svelte:element (#7695) * fixed render statement for svg when using svelte:element * removed unecessary stuff in test --- .../render_dom/wrappers/Element/index.ts | 4 +- .../js/samples/svelte-element-svg/expected.js | 111 ++++++++++++++++++ .../samples/svelte-element-svg/input.svelte | 3 + 3 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 test/js/samples/svelte-element-svg/expected.js create mode 100644 test/js/samples/svelte-element-svg/input.svelte diff --git a/src/compiler/compile/render_dom/wrappers/Element/index.ts b/src/compiler/compile/render_dom/wrappers/Element/index.ts index 8e8e0d6706..531208c476 100644 --- a/src/compiler/compile/render_dom/wrappers/Element/index.ts +++ b/src/compiler/compile/render_dom/wrappers/Element/index.ts @@ -504,9 +504,10 @@ export default class ElementWrapper extends Wrapper { get_render_statement(block: Block) { const { name, namespace, tag_expr } = this.node; + const reference = tag_expr.manipulate(block); if (namespace === namespaces.svg) { - return x`@svg_element("${name}")`; + return x`@svg_element(${reference})`; } if (namespace) { @@ -518,7 +519,6 @@ export default class ElementWrapper extends Wrapper { return x`@element_is("${name}", ${is.render_chunks(block).reduce((lhs, rhs) => x`${lhs} + ${rhs}`)})`; } - const reference = tag_expr.manipulate(block); return x`@element(${reference})`; } diff --git a/test/js/samples/svelte-element-svg/expected.js b/test/js/samples/svelte-element-svg/expected.js new file mode 100644 index 0000000000..f9ca24ff30 --- /dev/null +++ b/test/js/samples/svelte-element-svg/expected.js @@ -0,0 +1,111 @@ +/* generated by Svelte vX.Y.Z */ +import { + SvelteComponent, + append, + assign, + detach, + empty, + get_spread_update, + init, + insert, + noop, + safe_not_equal, + set_svg_attributes, + svg_element +} from "svelte/internal"; + +function create_dynamic_element_1(ctx) { + return { c: noop, m: noop, p: noop, d: noop }; +} + +// (1:0) +function create_dynamic_element(ctx) { + let svelte_element1; + let svelte_element0; + let svelte_element0_levels = [{ xmlns: "http://www.w3.org/2000/svg" }]; + let svelte_element0_data = {}; + + for (let i = 0; i < svelte_element0_levels.length; i += 1) { + svelte_element0_data = assign(svelte_element0_data, svelte_element0_levels[i]); + } + + let svelte_element1_levels = [{ xmlns: "http://www.w3.org/2000/svg" }]; + let svelte_element1_data = {}; + + for (let i = 0; i < svelte_element1_levels.length; i += 1) { + svelte_element1_data = assign(svelte_element1_data, svelte_element1_levels[i]); + } + + return { + c() { + svelte_element1 = svg_element("svg"); + svelte_element0 = svg_element("path"); + set_svg_attributes(svelte_element0, svelte_element0_data); + set_svg_attributes(svelte_element1, svelte_element1_data); + }, + m(target, anchor) { + insert(target, svelte_element1, anchor); + append(svelte_element1, svelte_element0); + }, + p(ctx, dirty) { + set_svg_attributes(svelte_element0, svelte_element0_data = get_spread_update(svelte_element0_levels, [{ xmlns: "http://www.w3.org/2000/svg" }])); + set_svg_attributes(svelte_element1, svelte_element1_data = get_spread_update(svelte_element1_levels, [{ xmlns: "http://www.w3.org/2000/svg" }])); + }, + d(detaching) { + if (detaching) detach(svelte_element1); + } + }; +} + +function create_fragment(ctx) { + let previous_tag = "svg"; + let svelte_element1_anchor; + let svelte_element1 = "svg" && create_dynamic_element(ctx); + + return { + c() { + if (svelte_element1) svelte_element1.c(); + svelte_element1_anchor = empty(); + }, + m(target, anchor) { + if (svelte_element1) svelte_element1.m(target, anchor); + insert(target, svelte_element1_anchor, anchor); + }, + p(ctx, [dirty]) { + if ("svg") { + if (!previous_tag) { + svelte_element1 = create_dynamic_element(ctx); + svelte_element1.c(); + svelte_element1.m(svelte_element1_anchor.parentNode, svelte_element1_anchor); + } else if (safe_not_equal(previous_tag, "svg")) { + svelte_element1.d(1); + svelte_element1 = create_dynamic_element(ctx); + svelte_element1.c(); + svelte_element1.m(svelte_element1_anchor.parentNode, svelte_element1_anchor); + } else { + svelte_element1.p(ctx, dirty); + } + } else if (previous_tag) { + svelte_element1.d(1); + svelte_element1 = null; + } + + previous_tag = "svg"; + }, + i: noop, + o: noop, + d(detaching) { + if (detaching) detach(svelte_element1_anchor); + if (svelte_element1) svelte_element1.d(detaching); + } + }; +} + +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/svelte-element-svg/input.svelte b/test/js/samples/svelte-element-svg/input.svelte new file mode 100644 index 0000000000..2dc4d54814 --- /dev/null +++ b/test/js/samples/svelte-element-svg/input.svelte @@ -0,0 +1,3 @@ + + + \ No newline at end of file From 87f0c461a84ae64ccd2d246e775b6deefc4150b9 Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Mon, 12 Sep 2022 03:23:12 +0800 Subject: [PATCH 045/145] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25d819449d..066df51b00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * Warn instead of throwing error if `` is void tag ([#7566](https://github.com/sveltejs/svelte/issues/7566)) * Treat `inert` as boolean attribute ([#7785](https://github.com/sveltejs/svelte/pull/7785)) * Supporting scoped style for `` ([#7443](https://github.com/sveltejs/svelte/issues/7443)) +* Supports SVG elements with ``([#7613](https://github.com/sveltejs/svelte/issues/7613)) ## 3.50.1 From 78b81277e7bbce3bad5f287312d22ce5dc339d2e Mon Sep 17 00:00:00 2001 From: Vaibhav Rai Date: Mon, 12 Sep 2022 00:58:30 +0530 Subject: [PATCH 046/145] [fix]: Warn user when binding rest operator (#7526) * Fix 6860: Warn user when binding rest operator * move the binding validation to Binding node * update test Co-authored-by: vaibhav rai * add more test case, supporting deep destructuring and array destructuring Co-authored-by: vaibhav rai Co-authored-by: tanhauhau --- src/compiler/compile/compiler_warnings.ts | 6 ++++- src/compiler/compile/nodes/AwaitBlock.ts | 6 +++-- src/compiler/compile/nodes/Binding.ts | 14 +++++++++++ src/compiler/compile/nodes/ConstTag.ts | 5 +++- src/compiler/compile/nodes/EachBlock.ts | 6 ++--- src/compiler/compile/nodes/shared/Context.ts | 25 +++++++++++++------ .../rest-eachblock-binding-2/input.svelte | 11 ++++++++ .../rest-eachblock-binding-2/warnings.json | 9 +++++++ .../rest-eachblock-binding-3/input.svelte | 8 ++++++ .../rest-eachblock-binding-3/warnings.json | 9 +++++++ .../rest-eachblock-binding/input.svelte | 8 ++++++ .../rest-eachblock-binding/warnings.json | 9 +++++++ 12 files changed, 102 insertions(+), 14 deletions(-) create mode 100644 test/validator/samples/rest-eachblock-binding-2/input.svelte create mode 100644 test/validator/samples/rest-eachblock-binding-2/warnings.json create mode 100644 test/validator/samples/rest-eachblock-binding-3/input.svelte create mode 100644 test/validator/samples/rest-eachblock-binding-3/warnings.json create mode 100644 test/validator/samples/rest-eachblock-binding/input.svelte create mode 100644 test/validator/samples/rest-eachblock-binding/warnings.json diff --git a/src/compiler/compile/compiler_warnings.ts b/src/compiler/compile/compiler_warnings.ts index 5fc5faa8f1..b3e2e36797 100644 --- a/src/compiler/compile/compiler_warnings.ts +++ b/src/compiler/compile/compiler_warnings.ts @@ -186,5 +186,9 @@ export default { redundant_event_modifier_passive: { code: 'redundant-event-modifier', message: 'The passive modifier only works with wheel and touch events' - } + }, + invalid_rest_eachblock_binding: (rest_element_name: string) => ({ + code: 'invalid-rest-eachblock-binding', + message: `...${rest_element_name} operator will create a new object and binding propogation with original object will not work` + }) }; diff --git a/src/compiler/compile/nodes/AwaitBlock.ts b/src/compiler/compile/nodes/AwaitBlock.ts index 735fdbfff3..4a669b6365 100644 --- a/src/compiler/compile/nodes/AwaitBlock.ts +++ b/src/compiler/compile/nodes/AwaitBlock.ts @@ -23,6 +23,8 @@ export default class AwaitBlock extends Node { then: ThenBlock; catch: CatchBlock; + context_rest_properties: Map = new Map(); + constructor(component: Component, parent: Node, scope: TemplateScope, info: TemplateNode) { super(component, parent, scope, info); @@ -33,12 +35,12 @@ export default class AwaitBlock extends Node { if (this.then_node) { this.then_contexts = []; - unpack_destructuring({ contexts: this.then_contexts, node: info.value, scope, component }); + unpack_destructuring({ contexts: this.then_contexts, node: info.value, scope, component, context_rest_properties: this.context_rest_properties }); } if (this.catch_node) { this.catch_contexts = []; - unpack_destructuring({ contexts: this.catch_contexts, node: info.error, scope, component }); + unpack_destructuring({ contexts: this.catch_contexts, node: info.error, scope, component, context_rest_properties: this.context_rest_properties }); } this.pending = new PendingBlock(component, this, scope, info.pending); diff --git a/src/compiler/compile/nodes/Binding.ts b/src/compiler/compile/nodes/Binding.ts index 39f6fa374e..594490a5fb 100644 --- a/src/compiler/compile/nodes/Binding.ts +++ b/src/compiler/compile/nodes/Binding.ts @@ -11,6 +11,7 @@ import InlineComponent from './InlineComponent'; import Window from './Window'; import { clone } from '../../utils/clone'; import compiler_errors from '../compiler_errors'; +import compiler_warnings from '../compiler_warnings'; // TODO this should live in a specific binding const read_only_media_attributes = new Set([ @@ -47,6 +48,7 @@ export default class Binding extends Node { const { name } = get_object(this.expression.node); this.is_contextual = Array.from(this.expression.references).some(name => scope.names.has(name)); + if (this.is_contextual) this.validate_binding_rest_properties(scope); // make sure we track this as a mutable ref if (scope.is_let(name)) { @@ -95,6 +97,18 @@ export default class Binding extends Node { is_readonly_media_attribute() { return read_only_media_attributes.has(this.name); } + + validate_binding_rest_properties(scope: TemplateScope) { + this.expression.references.forEach(name => { + const each_block = scope.get_owner(name); + if (each_block && each_block.type === 'EachBlock') { + const rest_node = each_block.context_rest_properties.get(name); + if (rest_node) { + this.component.warn(rest_node as any, compiler_warnings.invalid_rest_eachblock_binding(name)); + } + } + }); + } } function isElement(node: Node): node is Element { diff --git a/src/compiler/compile/nodes/ConstTag.ts b/src/compiler/compile/nodes/ConstTag.ts index 87a9039008..44a50aa005 100644 --- a/src/compiler/compile/nodes/ConstTag.ts +++ b/src/compiler/compile/nodes/ConstTag.ts @@ -10,6 +10,7 @@ import { extract_identifiers } from 'periscopic'; import is_reference, { NodeWithPropertyDefinition } from 'is-reference'; import get_object from '../utils/get_object'; import compiler_errors from '../compiler_errors'; +import { Node as ESTreeNode } from 'estree'; const allowed_parents = new Set(['EachBlock', 'CatchBlock', 'ThenBlock', 'InlineComponent', 'SlotTemplate', 'IfBlock', 'ElseBlock']); @@ -19,6 +20,7 @@ export default class ConstTag extends Node { contexts: Context[] = []; node: ConstTagType; scope: TemplateScope; + context_rest_properties: Map = new Map(); assignees: Set = new Set(); dependencies: Set = new Set(); @@ -58,7 +60,8 @@ export default class ConstTag extends Node { contexts: this.contexts, node: this.node.expression.left, scope: this.scope, - component: this.component + component: this.component, + context_rest_properties: this.context_rest_properties }); this.expression = new Expression(this.component, this, this.scope, this.node.expression.right); this.contexts.forEach(context => { diff --git a/src/compiler/compile/nodes/EachBlock.ts b/src/compiler/compile/nodes/EachBlock.ts index bea6fb7910..4a5ea19e37 100644 --- a/src/compiler/compile/nodes/EachBlock.ts +++ b/src/compiler/compile/nodes/EachBlock.ts @@ -28,7 +28,7 @@ export default class EachBlock extends AbstractBlock { has_animation: boolean; has_binding = false; has_index_binding = false; - + context_rest_properties: Map; else?: ElseBlock; constructor(component: Component, parent: Node, scope: TemplateScope, info: TemplateNode) { @@ -40,9 +40,9 @@ export default class EachBlock extends AbstractBlock { this.index = info.index; this.scope = scope.child(); - + this.context_rest_properties = new Map(); this.contexts = []; - unpack_destructuring({ contexts: this.contexts, node: info.context, scope, component }); + unpack_destructuring({ contexts: this.contexts, node: info.context, scope, component, context_rest_properties: this.context_rest_properties }); this.contexts.forEach(context => { this.scope.add(context.key.name, this.expression.dependencies, this); diff --git a/src/compiler/compile/nodes/shared/Context.ts b/src/compiler/compile/nodes/shared/Context.ts index 670f0531e6..47180d24cd 100644 --- a/src/compiler/compile/nodes/shared/Context.ts +++ b/src/compiler/compile/nodes/shared/Context.ts @@ -20,7 +20,8 @@ export function unpack_destructuring({ modifier = (node) => node, default_modifier = (node) => node, scope, - component + component, + context_rest_properties }: { contexts: Context[]; node: Node; @@ -28,6 +29,7 @@ export function unpack_destructuring({ default_modifier?: Context['default_modifier']; scope: TemplateScope; component: Component; + context_rest_properties: Map; }) { if (!node) return; @@ -43,6 +45,7 @@ export function unpack_destructuring({ modifier, default_modifier }); + context_rest_properties.set((node.argument as Identifier).name, node); } else if (node.type === 'ArrayPattern') { node.elements.forEach((element, i) => { if (element && element.type === 'RestElement') { @@ -52,8 +55,10 @@ export function unpack_destructuring({ modifier: (node) => x`${modifier(node)}.slice(${i})` as Node, default_modifier, scope, - component + component, + context_rest_properties }); + context_rest_properties.set((element.argument as Identifier).name, element); } else if (element && element.type === 'AssignmentPattern') { const n = contexts.length; mark_referenced(element.right, scope, component); @@ -70,7 +75,8 @@ export function unpack_destructuring({ to_ctx )}` as Node, scope, - component + component, + context_rest_properties }); } else { unpack_destructuring({ @@ -79,7 +85,8 @@ export function unpack_destructuring({ modifier: (node) => x`${modifier(node)}[${i}]` as Node, default_modifier, scope, - component + component, + context_rest_properties }); } }); @@ -97,8 +104,10 @@ export function unpack_destructuring({ )}, [${used_properties}])` as Node, default_modifier, scope, - component + component, + context_rest_properties }); + context_rest_properties.set((property.argument as Identifier).name, property); } else { const key = property.key as Identifier; const value = property.value; @@ -121,7 +130,8 @@ export function unpack_destructuring({ to_ctx )}` as Node, scope, - component + component, + context_rest_properties }); } else { unpack_destructuring({ @@ -130,7 +140,8 @@ export function unpack_destructuring({ modifier: (node) => x`${modifier(node)}.${key.name}` as Node, default_modifier, scope, - component + component, + context_rest_properties }); } } diff --git a/test/validator/samples/rest-eachblock-binding-2/input.svelte b/test/validator/samples/rest-eachblock-binding-2/input.svelte new file mode 100644 index 0000000000..d92557673b --- /dev/null +++ b/test/validator/samples/rest-eachblock-binding-2/input.svelte @@ -0,0 +1,11 @@ + + +{#each objArray as [id, ...rest] (id)} + +
      +{/each} diff --git a/test/validator/samples/rest-eachblock-binding-2/warnings.json b/test/validator/samples/rest-eachblock-binding-2/warnings.json new file mode 100644 index 0000000000..a55e08ac05 --- /dev/null +++ b/test/validator/samples/rest-eachblock-binding-2/warnings.json @@ -0,0 +1,9 @@ +[ + { + "code": "invalid-rest-eachblock-binding", + "message": "...rest operator will create a new object and binding propogation with original object will not work", + "pos": 102, + "start": { "line": 8, "column": 24, "character": 102 }, + "end": { "line": 8, "column": 31, "character": 109 } + } +] diff --git a/test/validator/samples/rest-eachblock-binding-3/input.svelte b/test/validator/samples/rest-eachblock-binding-3/input.svelte new file mode 100644 index 0000000000..b8bae0cd7f --- /dev/null +++ b/test/validator/samples/rest-eachblock-binding-3/input.svelte @@ -0,0 +1,8 @@ + + +{#each objArray as { bar: { id, ...rest } } (id)} + +
      +{/each} diff --git a/test/validator/samples/rest-eachblock-binding-3/warnings.json b/test/validator/samples/rest-eachblock-binding-3/warnings.json new file mode 100644 index 0000000000..c3410b3888 --- /dev/null +++ b/test/validator/samples/rest-eachblock-binding-3/warnings.json @@ -0,0 +1,9 @@ +[ + { + "code": "invalid-rest-eachblock-binding", + "message": "...rest operator will create a new object and binding propogation with original object will not work", + "pos": 168, + "start": { "line": 5, "column": 32, "character": 168 }, + "end": { "line": 5, "column": 39, "character": 175 } + } +] diff --git a/test/validator/samples/rest-eachblock-binding/input.svelte b/test/validator/samples/rest-eachblock-binding/input.svelte new file mode 100644 index 0000000000..7b96705448 --- /dev/null +++ b/test/validator/samples/rest-eachblock-binding/input.svelte @@ -0,0 +1,8 @@ + + +{#each objArray as { id, ...rest } (id)} + +
      +{/each} diff --git a/test/validator/samples/rest-eachblock-binding/warnings.json b/test/validator/samples/rest-eachblock-binding/warnings.json new file mode 100644 index 0000000000..d5d34f31d1 --- /dev/null +++ b/test/validator/samples/rest-eachblock-binding/warnings.json @@ -0,0 +1,9 @@ +[ + { + "code": "invalid-rest-eachblock-binding", + "message": "...rest operator will create a new object and binding propogation with original object will not work", + "pos": 143, + "start": { "line": 5, "column": 25, "character": 143 }, + "end": { "line": 5, "column": 32, "character": 150 } + } +] From 7331c06a74622a4635968a0c8d87b91fda4a1110 Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Mon, 12 Sep 2022 03:30:02 +0800 Subject: [PATCH 047/145] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 066df51b00..442c941571 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ * Treat `inert` as boolean attribute ([#7785](https://github.com/sveltejs/svelte/pull/7785)) * Supporting scoped style for `` ([#7443](https://github.com/sveltejs/svelte/issues/7443)) * Supports SVG elements with ``([#7613](https://github.com/sveltejs/svelte/issues/7613)) +* Warn user when binding on a `{...rest}` object in `{#each}` block ([#6860](https://github.com/sveltejs/svelte/issues/6860)) ## 3.50.1 From 2cd661156e3646b5b8c9e93f06e240f3613737e8 Mon Sep 17 00:00:00 2001 From: Shinobu Hayashi Date: Tue, 13 Sep 2022 20:10:45 +0900 Subject: [PATCH 048/145] [feat] Add a11y rule to check no tabindex in nointeractive element (#6693) * [feature] add util module to check element is interactive element * [feature] add util module to check role is interactive role * [feature] add a11y checker for no-nointeractive-tabindex * [chore] add test for no-nointeractive-tabindex * [chore] fix tabindex-no-positive test div -> button * [refactor] bundle up two filter into one * Refactor: export a11y-no-nointeractive-tabindex warning from compiler_warning * slight refactor to use existing utils Co-authored-by: tanhauhau --- src/compiler/compile/compiler_warnings.ts | 4 ++ src/compiler/compile/nodes/Element.ts | 11 +++- src/compiler/compile/utils/a11y.ts | 4 ++ .../input.svelte | 14 +++++ .../warnings.json | 62 +++++++++++++++++++ .../a11y-tabindex-no-positive/input.svelte | 8 +-- .../a11y-tabindex-no-positive/warnings.json | 10 +-- 7 files changed, 102 insertions(+), 11 deletions(-) create mode 100644 test/validator/samples/a11y-no-nointeractive-tabindex/input.svelte create mode 100644 test/validator/samples/a11y-no-nointeractive-tabindex/warnings.json diff --git a/src/compiler/compile/compiler_warnings.ts b/src/compiler/compile/compiler_warnings.ts index b3e2e36797..7b1a3b3d29 100644 --- a/src/compiler/compile/compiler_warnings.ts +++ b/src/compiler/compile/compiler_warnings.ts @@ -179,6 +179,10 @@ export default { code: 'a11y-missing-content', message: `A11y: <${name}> element should have child content` }), + a11y_no_nointeractive_tabindex: { + code: 'a11y-no-nointeractive-tabindex', + message: 'A11y: not interactive element cannot have positive tabIndex value' + }, redundant_event_modifier_for_touch: { code: 'redundant-event-modifier', message: 'Touch event handlers that don\'t use the \'event\' object are passive by default' diff --git a/src/compiler/compile/nodes/Element.ts b/src/compiler/compile/nodes/Element.ts index df0e649122..b5f9caa6b8 100644 --- a/src/compiler/compile/nodes/Element.ts +++ b/src/compiler/compile/nodes/Element.ts @@ -24,7 +24,7 @@ import { Literal } from 'estree'; import compiler_warnings from '../compiler_warnings'; import compiler_errors from '../compiler_errors'; import { ARIARoleDefintionKey, roles, aria, ARIAPropertyDefinition, ARIAProperty } from 'aria-query'; -import { is_interactive_element, is_non_interactive_roles, is_presentation_role } from '../utils/a11y'; +import { is_interactive_element, is_non_interactive_roles, is_presentation_role, is_interactive_roles } from '../utils/a11y'; const aria_attributes = 'activedescendant atomic autocomplete busy checked colcount colindex colspan controls current describedby description details disabled dropeffect errormessage expanded flowto grabbed haspopup hidden invalid keyshortcuts label labelledby level live modal multiline multiselectable orientation owns placeholder posinset pressed readonly relevant required roledescription rowcount rowindex rowspan selected setsize sort valuemax valuemin valuenow valuetext'.split(' '); const aria_attribute_set = new Set(aria_attributes); @@ -549,8 +549,15 @@ export default class Element extends Node { } } }); - } + // no-nointeractive-tabindex + if (!is_interactive_element(this.name, attribute_map) && !is_interactive_roles(attribute_map.get('role')?.get_static_value() as ARIARoleDefintionKey)) { + const tab_index = attribute_map.get('tabindex'); + if (tab_index && (!tab_index.is_static || Number(tab_index.get_static_value()) >= 0)) { + component.warn(this, compiler_warnings.a11y_no_nointeractive_tabindex); + } + } + } validate_special_cases() { const { component, attributes, handlers } = this; diff --git a/src/compiler/compile/utils/a11y.ts b/src/compiler/compile/utils/a11y.ts index 1e06608b54..5b300eac13 100644 --- a/src/compiler/compile/utils/a11y.ts +++ b/src/compiler/compile/utils/a11y.ts @@ -51,6 +51,10 @@ export function is_non_interactive_roles(role: ARIARoleDefintionKey) { return non_interactive_roles.has(role); } +export function is_interactive_roles(role: ARIARoleDefintionKey) { + return interactive_roles.has(role); +} + const presentation_roles = new Set(['presentation', 'none']); export function is_presentation_role(role: ARIARoleDefintionKey) { diff --git a/test/validator/samples/a11y-no-nointeractive-tabindex/input.svelte b/test/validator/samples/a11y-no-nointeractive-tabindex/input.svelte new file mode 100644 index 0000000000..e9ac0d3c9f --- /dev/null +++ b/test/validator/samples/a11y-no-nointeractive-tabindex/input.svelte @@ -0,0 +1,14 @@ + +
      '); + } } } diff --git a/src/compiler/utils/namespaces.ts b/src/compiler/utils/namespaces.ts index 7da64afc8c..d51b303fe1 100644 --- a/src/compiler/utils/namespaces.ts +++ b/src/compiler/utils/namespaces.ts @@ -25,4 +25,4 @@ export const valid_namespaces = [ xmlns ]; -export const namespaces: Record = { foreign, html, mathml, svg, xlink, xml, xmlns }; +export const namespaces = { foreign, html, mathml, svg, xlink, xml, xmlns } as const; diff --git a/test/runtime-puppeteer/samples/component-css-custom-properties-dynamic-svg/Svg.svelte b/test/runtime-puppeteer/samples/component-css-custom-properties-dynamic-svg/Svg.svelte new file mode 100644 index 0000000000..26e93bff29 --- /dev/null +++ b/test/runtime-puppeteer/samples/component-css-custom-properties-dynamic-svg/Svg.svelte @@ -0,0 +1,17 @@ + + + + + + + + \ No newline at end of file diff --git a/test/runtime-puppeteer/samples/component-css-custom-properties-dynamic-svg/_config.js b/test/runtime-puppeteer/samples/component-css-custom-properties-dynamic-svg/_config.js new file mode 100644 index 0000000000..ea8b5584db --- /dev/null +++ b/test/runtime-puppeteer/samples/component-css-custom-properties-dynamic-svg/_config.js @@ -0,0 +1,55 @@ +export default { + props: { + rectColor1: 'green', + circleColor1: 'red', + rectColor2: 'black', + circleColor2: 'blue' + }, + html: ` + + + + + + + + + + + + + + + `, + test({ component, assert, target }) { + component.rectColor1 = 'yellow'; + component.circleColor2 = 'cyan'; + + assert.htmlEqual(target.innerHTML, ` + + + + + + + + + + + + + + + `); + + const circleColor1 = target.querySelector('#svg-1 circle'); + const rectColor1 = target.querySelector('#svg-1 rect'); + const circleColor2 = target.querySelector('#svg-2 circle'); + const rectColor2 = target.querySelector('#svg-2 rect'); + + assert.htmlEqual(window.getComputedStyle(circleColor1).fill, 'rgb(255, 0, 0)'); + assert.htmlEqual(window.getComputedStyle(rectColor1).fill, 'rgb(255, 255, 0)'); + assert.htmlEqual(window.getComputedStyle(circleColor2).fill, 'rgb(0, 255, 255)'); + assert.htmlEqual(window.getComputedStyle(rectColor2).fill, 'rgb(0, 0, 0)'); + } +}; diff --git a/test/runtime-puppeteer/samples/component-css-custom-properties-dynamic-svg/main.svelte b/test/runtime-puppeteer/samples/component-css-custom-properties-dynamic-svg/main.svelte new file mode 100644 index 0000000000..b30be2dbac --- /dev/null +++ b/test/runtime-puppeteer/samples/component-css-custom-properties-dynamic-svg/main.svelte @@ -0,0 +1,25 @@ + + + + + + + \ No newline at end of file From 57541e6abc3837c07019a468d32ef74552bf2677 Mon Sep 17 00:00:00 2001 From: Yuichiro Yamashita Date: Thu, 6 Oct 2022 01:21:31 +0900 Subject: [PATCH 072/145] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index afa432f613..e26890d97b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ * Supports SVG elements with ``([#7613](https://github.com/sveltejs/svelte/issues/7613)) * Warn user when binding on a `{...rest}` object in `{#each}` block ([#6860](https://github.com/sveltejs/svelte/issues/6860)) * Supports `--style-props` for `` ([#7461](https://github.com/sveltejs/svelte/issues/7461)) +* Supports `--style-props` for SVG components ([#7808](https://github.com/sveltejs/svelte/issues/7808)) * Add a11y warnings: * `a11y-no-noninteractive-tabindex`: check for tabindex on non-interactive elements ([#6693](https://github.com/sveltejs/svelte/pull/6693)) * `a11y-click-events-have-key-events`: check if click event is accompanied by key events ([#5073](https://github.com/sveltejs/svelte/pull/5073)) From 81d4dbad99f2c349ced55c65f7ac2db704a771f6 Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Thu, 6 Oct 2022 09:21:36 +0800 Subject: [PATCH 073/145] [fix] call `on_destroy` if unmounted called immediately before `on_mount` (#7860) * call on_destroy if unmounted called immediately before on_mount * feat: review changes --- src/runtime/internal/Component.ts | 49 +++---------------- src/runtime/internal/await_block.ts | 29 ++++++++++- src/runtime/internal/transitions.ts | 2 +- src/runtime/internal/types.ts | 39 +++++++++++++++ .../Component.svelte | 13 +++++ .../_config.js | 9 ++++ .../main.svelte | 36 ++++++++++++++ 7 files changed, 133 insertions(+), 44 deletions(-) create mode 100644 src/runtime/internal/types.ts create mode 100644 test/runtime/samples/await-mount-and-unmount-immediately/Component.svelte create mode 100644 test/runtime/samples/await-mount-and-unmount-immediately/_config.js create mode 100644 test/runtime/samples/await-mount-and-unmount-immediately/main.svelte diff --git a/src/runtime/internal/Component.ts b/src/runtime/internal/Component.ts index 624339e7fa..5aec24c651 100644 --- a/src/runtime/internal/Component.ts +++ b/src/runtime/internal/Component.ts @@ -3,43 +3,7 @@ import { current_component, set_current_component } from './lifecycle'; import { blank_object, is_empty, is_function, run, run_all, noop } from './utils'; import { children, detach, start_hydrating, end_hydrating } from './dom'; import { transition_in } from './transitions'; - -/** - * INTERNAL, DO NOT USE. Code may change at any time. - */ -export 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: (ctx: T$$['ctx'], dirty: T$$['dirty']) => 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; -} -interface T$$ { - dirty: number[]; - ctx: any[]; - bound: any; - update: () => void; - callbacks: any; - after_update: any[]; - props: Record; - fragment: null | false | Fragment; - not_equal: any; - before_update: any[]; - context: Map; - on_mount: any[]; - on_destroy: any[]; - skip_bound: boolean; - on_disconnect: any[]; - root:Element | ShadowRoot -} +import { T$$ } from './types'; export function bind(component, name, callback) { const index = component.$$.props[name]; @@ -58,7 +22,7 @@ export function claim_component(block, parent_nodes) { } export function mount_component(component, target, anchor, customElement) { - const { fragment, on_mount, on_destroy, after_update } = component.$$; + const { fragment, after_update } = component.$$; fragment && fragment.m(target, anchor); @@ -66,9 +30,12 @@ export function mount_component(component, target, anchor, customElement) { // onMount happens before the initial afterUpdate add_render_callback(() => { - const new_on_destroy = on_mount.map(run).filter(is_function); - if (on_destroy) { - on_destroy.push(...new_on_destroy); + const new_on_destroy = component.$$.on_mount.map(run).filter(is_function); + // if the component was destroyed immediately + // it will update the `$$.on_destroy` reference to `null`. + // the destructured on_destroy may still reference to the old array + if (component.$$.on_destroy) { + component.$$.on_destroy.push(...new_on_destroy); } else { // Edge case - component was destroyed immediately, // most likely as a result of a binding initialising diff --git a/src/runtime/internal/await_block.ts b/src/runtime/internal/await_block.ts index ea6e8a187f..1e09ada6cf 100644 --- a/src/runtime/internal/await_block.ts +++ b/src/runtime/internal/await_block.ts @@ -2,11 +2,36 @@ import { is_promise } from './utils'; import { check_outros, group_outros, transition_in, transition_out } from './transitions'; import { flush } from './scheduler'; import { get_current_component, set_current_component } from './lifecycle'; +import { Fragment, FragmentFactory } from './types'; + +interface PromiseInfo { + ctx: null | any; + // unique object instance as a key to compare different promises + token: {}, + hasCatch: boolean, + pending: FragmentFactory, + then: FragmentFactory, + catch: FragmentFactory, + // ctx index for resolved value and rejected error + value: number, + error: number, + // resolved value or rejected error + resolved?: T, + // the current factory function for creating the fragment + current: FragmentFactory | null, + // the current fragment + block: Fragment | null, + // tuple of the pending, then, catch fragment + blocks: [null | Fragment, null | Fragment, null | Fragment]; + // DOM elements to mount and anchor on for the {#await} block + mount: () => HTMLElement; + anchor: HTMLElement; +} -export function handle_promise(promise, info) { +export function handle_promise(promise: Promise, info: PromiseInfo) { const token = info.token = {}; - function update(type, index, key?, value?) { + function update(type: FragmentFactory, index: 0 | 1 | 2, key?: number, value?) { if (info.token !== token) return; info.resolved = value; diff --git a/src/runtime/internal/transitions.ts b/src/runtime/internal/transitions.ts index 306a5e3793..9aa45dc4f1 100644 --- a/src/runtime/internal/transitions.ts +++ b/src/runtime/internal/transitions.ts @@ -5,7 +5,7 @@ import { create_rule, delete_rule } from './style_manager'; import { custom_event } from './dom'; import { add_render_callback } from './scheduler'; import { TransitionConfig } from '../transition'; -import { Fragment } from './Component'; +import { Fragment } from './types'; let promise: Promise | null; type INTRO = 1; diff --git a/src/runtime/internal/types.ts b/src/runtime/internal/types.ts new file mode 100644 index 0000000000..41f8f1ca43 --- /dev/null +++ b/src/runtime/internal/types.ts @@ -0,0 +1,39 @@ +/** + * INTERNAL, DO NOT USE. Code may change at any time. + */ +export 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: (ctx: T$$['ctx'], dirty: T$$['dirty']) => 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; +} + +export type FragmentFactory = (ctx: any) => Fragment; + +export interface T$$ { + dirty: number[]; + ctx: any[]; + bound: any; + update: () => void; + callbacks: any; + after_update: any[]; + props: Record; + fragment: null | false | Fragment; + not_equal: any; + before_update: any[]; + context: Map; + on_mount: any[]; + on_destroy: any[]; + skip_bound: boolean; + on_disconnect: any[]; + root:Element | ShadowRoot +} diff --git a/test/runtime/samples/await-mount-and-unmount-immediately/Component.svelte b/test/runtime/samples/await-mount-and-unmount-immediately/Component.svelte new file mode 100644 index 0000000000..be0c7e36b0 --- /dev/null +++ b/test/runtime/samples/await-mount-and-unmount-immediately/Component.svelte @@ -0,0 +1,13 @@ + + +{state} diff --git a/test/runtime/samples/await-mount-and-unmount-immediately/_config.js b/test/runtime/samples/await-mount-and-unmount-immediately/_config.js new file mode 100644 index 0000000000..b944091319 --- /dev/null +++ b/test/runtime/samples/await-mount-and-unmount-immediately/_config.js @@ -0,0 +1,9 @@ +export default { + html: 'Loading...', + async test({ assert, component, target }) { + await component.test(); + + assert.htmlEqual(target.innerHTML, '1'); + assert.deepEqual(component.logs, ['mount 0', 'unmount 0', 'mount 1']); + } +}; diff --git a/test/runtime/samples/await-mount-and-unmount-immediately/main.svelte b/test/runtime/samples/await-mount-and-unmount-immediately/main.svelte new file mode 100644 index 0000000000..245304be83 --- /dev/null +++ b/test/runtime/samples/await-mount-and-unmount-immediately/main.svelte @@ -0,0 +1,36 @@ + + +{#await promise} + Loading... +{:then state} + +{/await} \ No newline at end of file From bfb7536c1a6718babc21c869070ff94de484c946 Mon Sep 17 00:00:00 2001 From: Yuichiro Yamashita Date: Thu, 6 Oct 2022 10:28:41 +0900 Subject: [PATCH 074/145] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e26890d97b..b5ba64d0bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ * Improve performance of custom element data setting in `` ([#7869](https://github.com/sveltejs/svelte/pull/7869)) * Supports nullish values for component event handlers ([#7568](https://github.com/sveltejs/svelte/issues/7568)) * Better error message when specifying an invalid value for `` ([#7550](https://github.com/sveltejs/svelte/issues/7550)) +* Fix to call component unmount if a component is mounted and then immediately unmounted ([#7817](https://github.com/sveltejs/svelte/issues/7817)) ## 3.50.1 From ce569f97ebd633d44c747cef8039725325c7d753 Mon Sep 17 00:00:00 2001 From: Marcos Mercuri Date: Thu, 6 Oct 2022 11:23:29 +0200 Subject: [PATCH 075/145] [docs] Add clarification on how reactivity works (#7819) * Add clarification on how reactivity works Based on the fact that there are multiple issues were opened related to a perceived bug on the reactive variables, I thought it would be good to add a clarification on the docs. Part of the text is taken from [this comment](https://github.com/sveltejs/svelte/issues/7818#issuecomment-1230374639) that I found super useful. * Reword based on PR comments --- site/content/docs/02-component-format.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/site/content/docs/02-component-format.md b/site/content/docs/02-component-format.md index 23508b5c7b..5212b001ac 100644 --- a/site/content/docs/02-component-format.md +++ b/site/content/docs/02-component-format.md @@ -192,6 +192,25 @@ Total: {total} ``` +--- +It is important to note that the reactive blocks are ordered via simple static analysis at compile time, and all the compiler looks at are the variables that are assigned to and used within the block itself, not in any functions called by them. This means that `yDependent` will not be updated when `x` is updated in the following example: + +```sv + +``` + +Moving the line `$: yDependent = y` bellow `$: setY(x)` will cause `yDependent` to be updated when `x` is updated. + --- If a statement consists entirely of an assignment to an undeclared variable, Svelte will inject a `let` declaration on your behalf. From 158ec43d99376ccb70c374e306552151b1dbf63b Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Thu, 6 Oct 2022 22:29:48 +0800 Subject: [PATCH 076/145] [fix] do not warn about missing props for bindings (#6583) --- src/compiler/compile/render_dom/index.ts | 21 +++++----- .../samples/capture-inject-state/expected.js | 22 +++++------ test/js/samples/debug-empty/expected.js | 14 +++---- .../debug-foo-bar-baz-things/expected.js | 38 +++++++++---------- test/js/samples/debug-foo/expected.js | 22 +++++------ .../expected.js | 14 +++---- .../Foo.svelte | 8 ++++ .../_config.js | 9 +++++ .../main.svelte | 8 ++++ 9 files changed, 89 insertions(+), 67 deletions(-) create mode 100644 test/runtime/samples/dev-warning-missing-data-component-bind/Foo.svelte create mode 100644 test/runtime/samples/dev-warning-missing-data-component-bind/_config.js create mode 100644 test/runtime/samples/dev-warning-missing-data-component-bind/main.svelte diff --git a/src/compiler/compile/render_dom/index.ts b/src/compiler/compile/render_dom/index.ts index 5fdac9bce4..173d93d5dd 100644 --- a/src/compiler/compile/render_dom/index.ts +++ b/src/compiler/compile/render_dom/index.ts @@ -121,7 +121,7 @@ export default function dom( const accessors = []; const not_equal = component.component_options.immutable ? x`@not_equal` : x`@safe_not_equal`; - let dev_props_check: Node[] | Node; + let missing_props_check: Node[] | Node; let inject_state: Expression; let capture_state: Expression; let props_inject: Node[] | Node; @@ -227,13 +227,13 @@ export default function dom( const expected = props.filter(prop => prop.writable && !prop.initialised); if (expected.length) { - dev_props_check = b` - const { ctx: #ctx } = this.$$; - const props = ${options.customElement ? x`this.attributes` : x`options.props || {}`}; - ${expected.map(prop => b` - if (${renderer.reference(prop.name)} === undefined && !('${prop.export_name}' in props)) { - @_console.warn("<${component.tag}> was created without expected prop '${prop.export_name}'"); - }`)} + missing_props_check = b` + $$self.$$.on_mount.push(function () { + ${expected.map(prop => b` + if (${prop.name} === undefined && !(('${prop.export_name}' in $$props) || $$self.$$.bound[$$self.$$.props['${prop.export_name}']])) { + @_console.warn("<${component.tag}> was created without expected prop '${prop.export_name}'"); + }`)} + }); `; } @@ -476,6 +476,7 @@ export default function dom( ${instance_javascript} + ${missing_props_check} ${unknown_props_check} ${renderer.binding_groups.size > 0 && b`const $$binding_groups = [${[...renderer.binding_groups.keys()].map(_ => x`[]`)}];`} @@ -533,8 +534,6 @@ export default function dom( @init(this, { target: this.shadowRoot, props: ${init_props}, customElement: true }, ${definition}, ${has_create_fragment ? 'create_fragment' : 'null'}, ${not_equal}, ${prop_indexes}, null, ${dirty}); - ${dev_props_check} - if (options) { if (options.target) { @insert(options.target, this, options.anchor); @@ -594,8 +593,6 @@ export default function dom( super(${options.dev && 'options'}); @init(this, options, ${definition}, ${has_create_fragment ? 'create_fragment' : 'null'}, ${not_equal}, ${prop_indexes}, ${optional_parameters}); ${options.dev && b`@dispatch_dev("SvelteRegisterComponent", { component: this, tagName: "${name.name}", options, id: create_fragment.name });`} - - ${dev_props_check} } } `[0] as ClassDeclaration; diff --git a/test/js/samples/capture-inject-state/expected.js b/test/js/samples/capture-inject-state/expected.js index 58e1879553..882b3e9cf6 100644 --- a/test/js/samples/capture-inject-state/expected.js +++ b/test/js/samples/capture-inject-state/expected.js @@ -113,6 +113,17 @@ function instance($$self, $$props, $$invalidate) { let { alias: realName } = $$props; let local; let shadowedByModule; + + $$self.$$.on_mount.push(function () { + if (prop === undefined && !('prop' in $$props || $$self.$$.bound[$$self.$$.props['prop']])) { + console.warn(" was created without expected prop 'prop'"); + } + + if (realName === undefined && !('alias' in $$props || $$self.$$.bound[$$self.$$.props['alias']])) { + console.warn(" was created without expected prop 'alias'"); + } + }); + const writable_props = ['prop', 'alias']; Object.keys($$props).forEach(key => { @@ -166,17 +177,6 @@ class Component extends SvelteComponentDev { options, id: create_fragment.name }); - - const { ctx } = this.$$; - const props = options.props || {}; - - if (/*prop*/ ctx[0] === undefined && !('prop' in props)) { - console.warn(" was created without expected prop 'prop'"); - } - - if (/*realName*/ ctx[1] === undefined && !('alias' in props)) { - console.warn(" was created without expected prop 'alias'"); - } } get prop() { diff --git a/test/js/samples/debug-empty/expected.js b/test/js/samples/debug-empty/expected.js index 55303b41b7..ee304591cb 100644 --- a/test/js/samples/debug-empty/expected.js +++ b/test/js/samples/debug-empty/expected.js @@ -72,6 +72,13 @@ function instance($$self, $$props, $$invalidate) { let { $$slots: slots = {}, $$scope } = $$props; validate_slots('Component', slots, []); let { name } = $$props; + + $$self.$$.on_mount.push(function () { + if (name === undefined && !('name' in $$props || $$self.$$.bound[$$self.$$.props['name']])) { + console.warn(" was created without expected prop 'name'"); + } + }); + const writable_props = ['name']; Object.keys($$props).forEach(key => { @@ -106,13 +113,6 @@ class Component extends SvelteComponentDev { options, id: create_fragment.name }); - - const { ctx } = this.$$; - const props = options.props || {}; - - if (/*name*/ ctx[0] === undefined && !('name' in props)) { - console.warn(" was created without expected prop 'name'"); - } } get 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 3377d35018..02be04c26e 100644 --- a/test/js/samples/debug-foo-bar-baz-things/expected.js +++ b/test/js/samples/debug-foo-bar-baz-things/expected.js @@ -176,6 +176,25 @@ function instance($$self, $$props, $$invalidate) { let { foo } = $$props; let { bar } = $$props; let { baz } = $$props; + + $$self.$$.on_mount.push(function () { + if (things === undefined && !('things' in $$props || $$self.$$.bound[$$self.$$.props['things']])) { + console.warn(" was created without expected prop 'things'"); + } + + if (foo === undefined && !('foo' in $$props || $$self.$$.bound[$$self.$$.props['foo']])) { + console.warn(" was created without expected prop 'foo'"); + } + + if (bar === undefined && !('bar' in $$props || $$self.$$.bound[$$self.$$.props['bar']])) { + console.warn(" was created without expected prop 'bar'"); + } + + if (baz === undefined && !('baz' in $$props || $$self.$$.bound[$$self.$$.props['baz']])) { + console.warn(" was created without expected prop 'baz'"); + } + }); + const writable_props = ['things', 'foo', 'bar', 'baz']; Object.keys($$props).forEach(key => { @@ -216,25 +235,6 @@ class Component extends SvelteComponentDev { options, id: create_fragment.name }); - - const { ctx } = this.$$; - const props = options.props || {}; - - if (/*things*/ ctx[0] === undefined && !('things' in props)) { - console.warn(" was created without expected prop 'things'"); - } - - if (/*foo*/ ctx[1] === undefined && !('foo' in props)) { - console.warn(" was created without expected prop 'foo'"); - } - - if (/*bar*/ ctx[2] === undefined && !('bar' in props)) { - console.warn(" was created without expected prop 'bar'"); - } - - if (/*baz*/ ctx[3] === undefined && !('baz' in props)) { - console.warn(" was created without expected prop 'baz'"); - } } get things() { diff --git a/test/js/samples/debug-foo/expected.js b/test/js/samples/debug-foo/expected.js index 518897c237..84dedb0a91 100644 --- a/test/js/samples/debug-foo/expected.js +++ b/test/js/samples/debug-foo/expected.js @@ -168,6 +168,17 @@ function instance($$self, $$props, $$invalidate) { validate_slots('Component', slots, []); let { things } = $$props; let { foo } = $$props; + + $$self.$$.on_mount.push(function () { + if (things === undefined && !('things' in $$props || $$self.$$.bound[$$self.$$.props['things']])) { + console.warn(" was created without expected prop 'things'"); + } + + if (foo === undefined && !('foo' in $$props || $$self.$$.bound[$$self.$$.props['foo']])) { + console.warn(" was created without expected prop 'foo'"); + } + }); + const writable_props = ['things', 'foo']; Object.keys($$props).forEach(key => { @@ -204,17 +215,6 @@ class Component extends SvelteComponentDev { options, id: create_fragment.name }); - - const { ctx } = this.$$; - const props = options.props || {}; - - if (/*things*/ ctx[0] === undefined && !('things' in props)) { - console.warn(" was created without expected prop 'things'"); - } - - if (/*foo*/ ctx[1] === undefined && !('foo' in props)) { - console.warn(" was created without expected prop 'foo'"); - } } get things() { 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 5e10ec55f8..a94cf7b5f2 100644 --- a/test/js/samples/dev-warning-missing-data-computed/expected.js +++ b/test/js/samples/dev-warning-missing-data-computed/expected.js @@ -69,6 +69,13 @@ function instance($$self, $$props, $$invalidate) { validate_slots('Component', slots, []); let { foo } = $$props; let bar; + + $$self.$$.on_mount.push(function () { + if (foo === undefined && !('foo' in $$props || $$self.$$.bound[$$self.$$.props['foo']])) { + console.warn(" was created without expected prop 'foo'"); + } + }); + const writable_props = ['foo']; Object.keys($$props).forEach(key => { @@ -110,13 +117,6 @@ class Component extends SvelteComponentDev { options, id: create_fragment.name }); - - const { ctx } = this.$$; - const props = options.props || {}; - - if (/*foo*/ ctx[0] === undefined && !('foo' in props)) { - console.warn(" was created without expected prop 'foo'"); - } } get foo() { diff --git a/test/runtime/samples/dev-warning-missing-data-component-bind/Foo.svelte b/test/runtime/samples/dev-warning-missing-data-component-bind/Foo.svelte new file mode 100644 index 0000000000..60278c4845 --- /dev/null +++ b/test/runtime/samples/dev-warning-missing-data-component-bind/Foo.svelte @@ -0,0 +1,8 @@ + + +
      {w} {x} {y}
      \ No newline at end of file diff --git a/test/runtime/samples/dev-warning-missing-data-component-bind/_config.js b/test/runtime/samples/dev-warning-missing-data-component-bind/_config.js new file mode 100644 index 0000000000..ececa00a8c --- /dev/null +++ b/test/runtime/samples/dev-warning-missing-data-component-bind/_config.js @@ -0,0 +1,9 @@ +export default { + compileOptions: { + dev: true + }, + + warnings: [ + " was created without expected prop 'y'" + ] +}; diff --git a/test/runtime/samples/dev-warning-missing-data-component-bind/main.svelte b/test/runtime/samples/dev-warning-missing-data-component-bind/main.svelte new file mode 100644 index 0000000000..eab3c8336f --- /dev/null +++ b/test/runtime/samples/dev-warning-missing-data-component-bind/main.svelte @@ -0,0 +1,8 @@ + + + \ No newline at end of file From d04b1cca24fdfb9f170d0a5f747d94eabe7ee22b Mon Sep 17 00:00:00 2001 From: Yuichiro Yamashita Date: Thu, 6 Oct 2022 23:30:42 +0900 Subject: [PATCH 077/145] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b5ba64d0bb..d12212be87 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ * Supports nullish values for component event handlers ([#7568](https://github.com/sveltejs/svelte/issues/7568)) * Better error message when specifying an invalid value for `` ([#7550](https://github.com/sveltejs/svelte/issues/7550)) * Fix to call component unmount if a component is mounted and then immediately unmounted ([#7817](https://github.com/sveltejs/svelte/issues/7817)) +* Fix false positive warnings about props binding in dev mode ([#4457](https://github.com/sveltejs/svelte/issues/4457)) ## 3.50.1 From 8de7931c64b46d22fc303adce14eb3f680c8ca66 Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Fri, 7 Oct 2022 08:23:12 +0800 Subject: [PATCH 078/145] [feat] better error message for invalid logic block placement (#7862) * better error message for invalid logic block placement * include checking for {@html} tags in invalid location --- src/compiler/parse/errors.ts | 8 ++++++++ src/compiler/parse/state/tag.ts | 19 ++++++++++++++++--- .../html-block-in-attribute/errors.json | 9 +++++++++ .../html-block-in-attribute/input.svelte | 1 + .../html-block-in-textarea/errors.json | 9 +++++++++ .../html-block-in-textarea/input.svelte | 3 +++ .../logic-block-in-attribute/errors.json | 9 +++++++++ .../logic-block-in-attribute/input.svelte | 1 + .../logic-block-in-textarea/errors.json | 9 +++++++++ .../logic-block-in-textarea/input.svelte | 5 +++++ 10 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 test/validator/samples/html-block-in-attribute/errors.json create mode 100644 test/validator/samples/html-block-in-attribute/input.svelte create mode 100644 test/validator/samples/html-block-in-textarea/errors.json create mode 100644 test/validator/samples/html-block-in-textarea/input.svelte create mode 100644 test/validator/samples/logic-block-in-attribute/errors.json create mode 100644 test/validator/samples/logic-block-in-attribute/input.svelte create mode 100644 test/validator/samples/logic-block-in-textarea/errors.json create mode 100644 test/validator/samples/logic-block-in-textarea/input.svelte diff --git a/src/compiler/parse/errors.ts b/src/compiler/parse/errors.ts index 63bd5b0919..26f03c0cb1 100644 --- a/src/compiler/parse/errors.ts +++ b/src/compiler/parse/errors.ts @@ -107,6 +107,14 @@ export default { code: `invalid-${slug}-placement`, message: `<${name}> tags cannot be inside elements or blocks` }), + invalid_logic_block_placement: (location: string, name: string) => ({ + code: 'invalid-logic-block-placement', + message: `{#${name}} logic block cannot be ${location}` + }), + invalid_tag_placement: (location: string, name: string) => ({ + code: 'invalid-tag-placement', + message: `{@${name}} tag cannot be ${location}` + }), invalid_ref_directive: (name: string) => ({ code: 'invalid-ref-directive', message: `The ref directive is no longer supported — use \`bind:this={${name}}\` instead` diff --git a/src/compiler/parse/state/tag.ts b/src/compiler/parse/state/tag.ts index efce375b7e..4be47f25b0 100644 --- a/src/compiler/parse/state/tag.ts +++ b/src/compiler/parse/state/tag.ts @@ -219,7 +219,8 @@ export default function tag(parser: Parser) { element.children = read_sequence( parser, () => - /^<\/textarea(\s[^>]*)?>/i.test(parser.template.slice(parser.index)) + /^<\/textarea(\s[^>]*)?>/i.test(parser.template.slice(parser.index)), + 'inside \ No newline at end of file diff --git a/test/validator/samples/logic-block-in-attribute/errors.json b/test/validator/samples/logic-block-in-attribute/errors.json new file mode 100644 index 0000000000..ebf68938e7 --- /dev/null +++ b/test/validator/samples/logic-block-in-attribute/errors.json @@ -0,0 +1,9 @@ +[ + { + "code": "invalid-logic-block-placement", + "message": "{#if} logic block cannot be in attribute value", + "start": { "line": 1, "column": 12, "character": 12 }, + "end": { "line": 1, "column": 12, "character": 12 }, + "pos": 12 + } +] diff --git a/test/validator/samples/logic-block-in-attribute/input.svelte b/test/validator/samples/logic-block-in-attribute/input.svelte new file mode 100644 index 0000000000..241529527c --- /dev/null +++ b/test/validator/samples/logic-block-in-attribute/input.svelte @@ -0,0 +1 @@ +
      \ No newline at end of file diff --git a/test/validator/samples/logic-block-in-textarea/errors.json b/test/validator/samples/logic-block-in-textarea/errors.json new file mode 100644 index 0000000000..b1d73d4903 --- /dev/null +++ b/test/validator/samples/logic-block-in-textarea/errors.json @@ -0,0 +1,9 @@ +[ + { + "code": "invalid-logic-block-placement", + "message": "{#each} logic block cannot be inside \ No newline at end of file From 2b7393885724ed158dd3ce1b9e53b9737a5f3c3e Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Fri, 7 Oct 2022 08:25:04 +0800 Subject: [PATCH 079/145] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d12212be87..6ca984af7d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ * Better error message when specifying an invalid value for `` ([#7550](https://github.com/sveltejs/svelte/issues/7550)) * Fix to call component unmount if a component is mounted and then immediately unmounted ([#7817](https://github.com/sveltejs/svelte/issues/7817)) * Fix false positive warnings about props binding in dev mode ([#4457](https://github.com/sveltejs/svelte/issues/4457)) +* Better error message when using logic blocks or tags in invalid place ([#7552](https://github.com/sveltejs/svelte/issues/7552)) ## 3.50.1 From 220325cd9feea12f9a9bc5eb8df5120f856b1bc9 Mon Sep 17 00:00:00 2001 From: Samuel Stroschein <35429197+samuelstroschein@users.noreply.github.com> Date: Fri, 7 Oct 2022 11:11:46 +0200 Subject: [PATCH 080/145] [docs] add inline documentation to svelte runtime functions (#7846) * add documentation * add links do docs --- src/runtime/internal/lifecycle.ts | 69 +++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/src/runtime/internal/lifecycle.ts b/src/runtime/internal/lifecycle.ts index fbbeca9a67..e75bbdc501 100644 --- a/src/runtime/internal/lifecycle.ts +++ b/src/runtime/internal/lifecycle.ts @@ -11,18 +11,47 @@ export function get_current_component() { return current_component; } +/** + * Schedules a callback to run immediately before the component is updated after any state change. + * + * The first time the callback runs will be before the initial `onMount` + * + * https://svelte.dev/docs#run-time-svelte-beforeupdate + */ export function beforeUpdate(fn: () => any) { get_current_component().$$.before_update.push(fn); } +/** + * The `onMount` function schedules a callback to run as soon as the component has been mounted to the DOM. + * It must be called during the component's initialisation (but doesn't need to live *inside* the component; + * it can be called from an external module). + * + * `onMount` does not run inside a [server-side component](/docs#run-time-server-side-component-api). + * + * https://svelte.dev/docs#run-time-svelte-onmount + */ export function onMount(fn: () => any) { get_current_component().$$.on_mount.push(fn); } +/** + * Schedules a callback to run immediately after the component has been updated. + * + * The first time the callback runs will be after the initial `onMount` + */ export function afterUpdate(fn: () => any) { get_current_component().$$.after_update.push(fn); } +/** + * Schedules a callback to run immediately before the component is unmounted. + * + * Out of `onMount`, `beforeUpdate`, `afterUpdate` and `onDestroy`, this is the + * only one that runs inside a server-side component. + * + * https://svelte.dev/docs#run-time-svelte-ondestroy + */ export function onDestroy(fn: () => any) { get_current_component().$$.on_destroy.push(fn); } @@ -31,6 +60,18 @@ export interface DispatchOptions { cancelable?: boolean; } +/** + * Creates an event dispatcher that can be used to dispatch [component events](/docs#template-syntax-component-directives-on-eventname). + * Event dispatchers are functions that can take two arguments: `name` and `detail`. + * + * Component events created with `createEventDispatcher` create a + * [CustomEvent](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent). + * These events do not [bubble](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#Event_bubbling_and_capture). + * The `detail` argument corresponds to the [CustomEvent.detail](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/detail) + * property and can contain any type of data. + * + * https://svelte.dev/docs#run-time-svelte-createeventdispatcher + */ export function createEventDispatcher(): < EventKey extends Extract >( @@ -57,19 +98,47 @@ export function createEventDispatcher(): < }; } +/** + * Associates an arbitrary `context` object with the current component and the specified `key` + * and returns that object. The context is then available to children of the component + * (including slotted content) with `getContext`. + * + * Like lifecycle functions, this must be called during component initialisation. + * + * https://svelte.dev/docs#run-time-svelte-setcontext + */ export function setContext(key, context: T): T { get_current_component().$$.context.set(key, context); return context; } +/** + * Retrieves the context that belongs to the closest parent component with the specified `key`. + * Must be called during component initialisation. + * + * https://svelte.dev/docs#run-time-svelte-getcontext + */ export function getContext(key): T { return get_current_component().$$.context.get(key); } +/** + * Retrieves the whole context map that belongs to the closest parent component. + * Must be called during component initialisation. Useful, for example, if you + * programmatically create a component and want to pass the existing context to it. + * + * https://svelte.dev/docs#run-time-svelte-getallcontexts + */ export function getAllContexts = Map>(): T { return get_current_component().$$.context; } +/** + * Checks whether a given `key` has been set in the context of a parent component. + * Must be called during component initialisation. + * + * https://svelte.dev/docs#run-time-svelte-hascontext + */ export function hasContext(key): boolean { return get_current_component().$$.context.has(key); } From ff2759e1437559669bd032abaff6920c2fc46570 Mon Sep 17 00:00:00 2001 From: Geoff Rich <4992896+geoffrich@users.noreply.github.com> Date: Fri, 7 Oct 2022 16:25:19 -0700 Subject: [PATCH 081/145] [docs] fix typo in getting started (#7918) --- site/content/docs/01-getting-started.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/site/content/docs/01-getting-started.md b/site/content/docs/01-getting-started.md index 8ae5b1fb9c..e8aae80f23 100644 --- a/site/content/docs/01-getting-started.md +++ b/site/content/docs/01-getting-started.md @@ -7,6 +7,7 @@ title: Getting started To try Svelte in an interactive online environment you can try [the REPL](https://svelte.dev/repl) or [StackBlitz](https://node.new/svelte). To create a project locally, run: + ``` npm create vite@latest myapp -- --template svelte cd myapp @@ -16,6 +17,6 @@ npm run dev Or use [SvelteKit](https://kit.svelte.dev/), the official application framework from the Svelte team (currently in beta). -See the SvelteSociety website run by the Svelte community for a list of integrations with various [tooling and editots](https://sveltesociety.dev/tools). +The Svelte team maintains a [VS Code extension](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode) and the Svelte community has created a list of integrations with various other [tooling and editors](https://sveltesociety.dev/tools). If you're having trouble, get help on [Discord](https://svelte.dev/chat) or [StackOverflow](https://stackoverflow.com/questions/tagged/svelte). From 1c659193a0b1fdf6e472be182fb600a430784d20 Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Fri, 7 Oct 2022 16:34:31 -0700 Subject: [PATCH 082/145] [docs] update SvelteKit status (#7919) --- site/content/docs/01-getting-started.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/content/docs/01-getting-started.md b/site/content/docs/01-getting-started.md index e8aae80f23..48cdbcc231 100644 --- a/site/content/docs/01-getting-started.md +++ b/site/content/docs/01-getting-started.md @@ -15,7 +15,7 @@ npm install npm run dev ``` -Or use [SvelteKit](https://kit.svelte.dev/), the official application framework from the Svelte team (currently in beta). +Or use [SvelteKit](https://kit.svelte.dev/), the official application framework from the Svelte team (currently in release candidate status). The Svelte team maintains a [VS Code extension](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode) and the Svelte community has created a list of integrations with various other [tooling and editors](https://sveltesociety.dev/tools). From 6ac7038e47c38221f16f0f73af93c9024ff2a18c Mon Sep 17 00:00:00 2001 From: Conduitry Date: Mon, 10 Oct 2022 13:15:45 -0400 Subject: [PATCH 083/145] -> v3.51.0 --- CHANGELOG.md | 34 +++++++++++++++++----------------- package-lock.json | 2 +- package.json | 2 +- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ca984af7d..cbf22201f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,26 +1,26 @@ # Svelte changelog -## Unreleased +## 3.51.0 -* Fix hydration issue with using `{@html}` and components in `svelte:head` ([#4533](https://github.com/sveltejs/svelte/issues/4533), [#6463](https://github.com/sveltejs/svelte/issues/6463), [#7444](https://github.com/sveltejs/svelte/issues/7444)) -* Warn instead of throwing error if `` is void tag ([#7566](https://github.com/sveltejs/svelte/issues/7566)) -* Treat `inert` as boolean attribute ([#7785](https://github.com/sveltejs/svelte/pull/7785)) -* Supporting scoped style for `` ([#7443](https://github.com/sveltejs/svelte/issues/7443)) -* Supports SVG elements with ``([#7613](https://github.com/sveltejs/svelte/issues/7613)) -* Warn user when binding on a `{...rest}` object in `{#each}` block ([#6860](https://github.com/sveltejs/svelte/issues/6860)) -* Supports `--style-props` for `` ([#7461](https://github.com/sveltejs/svelte/issues/7461)) -* Supports `--style-props` for SVG components ([#7808](https://github.com/sveltejs/svelte/issues/7808)) * Add a11y warnings: - * `a11y-no-noninteractive-tabindex`: check for tabindex on non-interactive elements ([#6693](https://github.com/sveltejs/svelte/pull/6693)) * `a11y-click-events-have-key-events`: check if click event is accompanied by key events ([#5073](https://github.com/sveltejs/svelte/pull/5073)) -* `a11y-role-has-required-aria-props` do not warn when elements matched their semantic role ([#7838](https://github.com/sveltejs/svelte/pull/7838)) -* Supports custom element in `` ([#7766](https://github.com/sveltejs/svelte/pull/7766)) -* Improve performance of custom element data setting in `` ([#7869](https://github.com/sveltejs/svelte/pull/7869)) + * `a11y-no-noninteractive-tabindex`: check for tabindex on non-interactive elements ([#6693](https://github.com/sveltejs/svelte/pull/6693)) +* Warn when two-way binding to `{...rest}` object in `{#each}` block ([#6860](https://github.com/sveltejs/svelte/issues/6860)) +* Support `--style-props` on `` ([#7461](https://github.com/sveltejs/svelte/issues/7461)) * Supports nullish values for component event handlers ([#7568](https://github.com/sveltejs/svelte/issues/7568)) -* Better error message when specifying an invalid value for `` ([#7550](https://github.com/sveltejs/svelte/issues/7550)) -* Fix to call component unmount if a component is mounted and then immediately unmounted ([#7817](https://github.com/sveltejs/svelte/issues/7817)) -* Fix false positive warnings about props binding in dev mode ([#4457](https://github.com/sveltejs/svelte/issues/4457)) -* Better error message when using logic blocks or tags in invalid place ([#7552](https://github.com/sveltejs/svelte/issues/7552)) +* Supports SVG elements with ``([#7613](https://github.com/sveltejs/svelte/issues/7613)) +* Treat `inert` as boolean attribute ([#7785](https://github.com/sveltejs/svelte/pull/7785)) +* Support `--style-props` for SVG components ([#7808](https://github.com/sveltejs/svelte/issues/7808)) +* Fix false positive dev warnings about unset props when they are bound ([#4457](https://github.com/sveltejs/svelte/issues/4457)) +* Fix hydration with `{@html}` and components in `` ([#4533](https://github.com/sveltejs/svelte/issues/4533), [#6463](https://github.com/sveltejs/svelte/issues/6463), [#7444](https://github.com/sveltejs/svelte/issues/7444)) +* Support scoped style for `` ([#7443](https://github.com/sveltejs/svelte/issues/7443)) +* Improve error message for invalid value for `` ([#7550](https://github.com/sveltejs/svelte/issues/7550)) +* Improve error message when using logic blocks or tags at invalid location ([#7552](https://github.com/sveltejs/svelte/issues/7552)) +* Warn instead of throwing error if `` is a void tag ([#7566](https://github.com/sveltejs/svelte/issues/7566)) +* Supports custom elements in `` ([#7733](https://github.com/sveltejs/svelte/issues/7733)) +* Fix calling component unmount if a component is mounted and then immediately unmounted ([#7817](https://github.com/sveltejs/svelte/issues/7817)) +* Do not generate `a11y-role-has-required-aria-props` warning when elements match their semantic role ([#7837](https://github.com/sveltejs/svelte/issues/7837)) +* Improve performance of custom element data setting in `` ([#7869](https://github.com/sveltejs/svelte/pull/7869)) ## 3.50.1 diff --git a/package-lock.json b/package-lock.json index 23ccc6b66f..dec2c8ef0e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "svelte", - "version": "3.50.1", + "version": "3.51.0", "lockfileVersion": 2, "requires": true, "packages": { diff --git a/package.json b/package.json index 836fa33267..bf6b9e7754 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "svelte", - "version": "3.50.1", + "version": "3.51.0", "description": "Cybernetically enhanced web apps", "module": "index.mjs", "main": "index", From 26a428972b7865d3871e05368df5e7b47bbf7e5b Mon Sep 17 00:00:00 2001 From: metonym Date: Thu, 13 Oct 2022 05:49:00 -0700 Subject: [PATCH 084/145] [fix] "not interactive" -> "noninteractive" (#7930) --- site/content/docs/06-accessibility-warnings.md | 2 +- src/compiler/compile/compiler_warnings.ts | 2 +- .../samples/a11y-no-nointeractive-tabindex/warnings.json | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/site/content/docs/06-accessibility-warnings.md b/site/content/docs/06-accessibility-warnings.md index c82ef21fcb..8be8eb888c 100644 --- a/site/content/docs/06-accessibility-warnings.md +++ b/site/content/docs/06-accessibility-warnings.md @@ -268,7 +268,7 @@ Some HTML elements have default ARIA roles. Giving these elements an ARIA role t Tab key navigation should be limited to elements on the page that can be interacted with. ```sv - +
      ``` diff --git a/src/compiler/compile/compiler_warnings.ts b/src/compiler/compile/compiler_warnings.ts index f194090870..3a11e04bd1 100644 --- a/src/compiler/compile/compiler_warnings.ts +++ b/src/compiler/compile/compiler_warnings.ts @@ -185,7 +185,7 @@ export default { }), a11y_no_noninteractive_tabindex: { code: 'a11y-no-noninteractive-tabindex', - message: 'A11y: not interactive element cannot have positive tabIndex value' + message: 'A11y: noninteractive element cannot have positive tabIndex value' }, redundant_event_modifier_for_touch: { code: 'redundant-event-modifier', diff --git a/test/validator/samples/a11y-no-nointeractive-tabindex/warnings.json b/test/validator/samples/a11y-no-nointeractive-tabindex/warnings.json index 97b8ccd9b3..740d9b346c 100644 --- a/test/validator/samples/a11y-no-nointeractive-tabindex/warnings.json +++ b/test/validator/samples/a11y-no-nointeractive-tabindex/warnings.json @@ -6,7 +6,7 @@ "column": 20, "line": 11 }, - "message": "A11y: not interactive element cannot have positive tabIndex value", + "message": "A11y: noninteractive element cannot have positive tabIndex value", "pos": 221, "start": { "character": 221, @@ -21,7 +21,7 @@ "column": 35, "line": 12 }, - "message": "A11y: not interactive element cannot have positive tabIndex value", + "message": "A11y: noninteractive element cannot have positive tabIndex value", "pos": 242, "start": { "character": 242, @@ -36,7 +36,7 @@ "column": 24, "line": 13 }, - "message": "A11y: not interactive element cannot have positive tabIndex value", + "message": "A11y: noninteractive element cannot have positive tabIndex value", "pos": 278, "start": { "character": 278, @@ -51,7 +51,7 @@ "column": 26, "line": 14 }, - "message": "A11y: not interactive element cannot have positive tabIndex value", + "message": "A11y: noninteractive element cannot have positive tabIndex value", "pos": 303, "start": { "character": 303, From 0eba57113be4185836a76ba894cbc29f366da252 Mon Sep 17 00:00:00 2001 From: Hofer Ivan Date: Thu, 13 Oct 2022 14:54:30 +0200 Subject: [PATCH 085/145] [chore]: store regexp as variable instead of defining it inline (#7716) * store regexp as variable instead of defining it inline * fix naming of `regex_quoted_value` * some more variables * optimize `.replace() calls * restore formatting changes * optimize `parser.*` calls * small refactor * optimize `.test() calls * rename some variables * fix tests * rename pattern variables * extract common regexes into `patters.ts` * rename variables to use snake_case * fix trim --- src/compiler/compile/Component.ts | 22 +++++++----- src/compiler/compile/css/Selector.ts | 15 +++++--- src/compiler/compile/css/Stylesheet.ts | 9 +++-- src/compiler/compile/index.ts | 7 ++-- src/compiler/compile/nodes/Binding.ts | 4 +-- src/compiler/compile/nodes/Element.ts | 26 +++++++++----- src/compiler/compile/nodes/EventHandler.ts | 6 ++-- src/compiler/compile/nodes/Head.ts | 3 +- src/compiler/compile/nodes/InlineComponent.ts | 7 ++-- src/compiler/compile/nodes/Text.ts | 7 ++-- .../compile/nodes/shared/AbstractBlock.ts | 4 ++- .../compile/nodes/shared/Expression.ts | 4 ++- src/compiler/compile/render_dom/Block.ts | 3 +- src/compiler/compile/render_dom/index.ts | 3 +- .../render_dom/wrappers/Element/Attribute.ts | 17 +++++---- .../wrappers/Element/StyleAttribute.ts | 13 ++++--- .../render_dom/wrappers/Element/index.ts | 36 ++++++++++++------- .../compile/render_dom/wrappers/Fragment.ts | 3 +- .../wrappers/InlineComponent/index.ts | 4 ++- .../compile/render_dom/wrappers/Text.ts | 4 ++- .../render_dom/wrappers/shared/add_actions.ts | 4 ++- .../shared/create_debugging_comment.ts | 4 ++- .../compile/render_ssr/handlers/Element.ts | 6 ++-- .../handlers/shared/get_attribute_value.ts | 3 +- .../utils/remove_whitespace_children.ts | 3 +- .../compile/utils/get_name_from_filename.ts | 19 ++++++---- src/compiler/compile/utils/hash.ts | 5 ++- src/compiler/compile/utils/stringify.ts | 8 +++-- src/compiler/parse/index.ts | 14 ++++---- src/compiler/parse/read/context.ts | 3 +- src/compiler/parse/read/expression.ts | 4 +-- src/compiler/parse/read/script.ts | 9 +++-- src/compiler/parse/read/style.ts | 6 ++-- src/compiler/parse/state/mustache.ts | 30 ++++++++-------- src/compiler/parse/state/tag.ts | 26 +++++++++----- src/compiler/preprocess/index.ts | 22 +++++++----- src/compiler/utils/extract_svelte_ignore.ts | 7 ++-- src/compiler/utils/get_code_frame.ts | 4 ++- src/compiler/utils/mapped_code.ts | 10 ++++-- src/compiler/utils/names.ts | 12 ++++--- src/compiler/utils/patterns.ts | 28 ++++++++++++--- src/compiler/utils/trim.ts | 6 ++-- 42 files changed, 283 insertions(+), 147 deletions(-) diff --git a/src/compiler/compile/Component.ts b/src/compiler/compile/Component.ts index 2f8874de7a..1bbaac3ff4 100644 --- a/src/compiler/compile/Component.ts +++ b/src/compiler/compile/Component.ts @@ -47,6 +47,10 @@ interface ComponentOptions { preserveWhitespace?: boolean; } +const regex_leading_directory_separator = /^[/\\]/; +const regex_starts_with_term_export = /^Export/; +const regex_contains_term_function = /Function/; + export default class Component { stats: Stats; warnings: Warning[]; @@ -136,7 +140,7 @@ export default class Component { (typeof process !== 'undefined' ? compile_options.filename .replace(process.cwd(), '') - .replace(/^[/\\]/, '') + .replace(regex_leading_directory_separator, '') : compile_options.filename); this.locate = getLocator(this.source, { offsetLine: 1 }); @@ -638,7 +642,7 @@ export default class Component { body.splice(i, 1); } - if (/^Export/.test(node.type)) { + if (regex_starts_with_term_export.test(node.type)) { const replacement = this.extract_exports(node, true); if (replacement) { body[i] = replacement; @@ -795,7 +799,7 @@ export default class Component { return this.skip(); } - if (/^Export/.test(node.type)) { + if (regex_starts_with_term_export.test(node.type)) { const replacement = component.extract_exports(node); if (replacement) { this.replace(replacement); @@ -918,7 +922,7 @@ export default class Component { } if (name[1] !== '$' && scope.has(name.slice(1)) && scope.find_owner(name.slice(1)) !== this.instance_scope) { - if (!((/Function/.test(parent.type) && prop === 'params') || (parent.type === 'VariableDeclarator' && prop === 'id'))) { + if (!((regex_contains_term_function.test(parent.type) && prop === 'params') || (parent.type === 'VariableDeclarator' && prop === 'id'))) { return this.error(node as any, compiler_errors.contextual_store); } } @@ -965,7 +969,7 @@ export default class Component { walk(this.ast.instance.content, { enter(node: Node) { - if (/Function/.test(node.type)) { + if (regex_contains_term_function.test(node.type)) { return this.skip(); } @@ -1089,7 +1093,7 @@ export default class Component { this.replace(b` ${node.declarations.length ? node : null} - ${ props.length > 0 && b`let { ${ props } } = $$props;`} + ${ props.length > 0 && b`let { ${props} } = $$props;`} ${inserts} ` as any); return this.skip(); @@ -1460,6 +1464,8 @@ export default class Component { } } +const regex_valid_tag_name = /^[a-zA-Z][a-zA-Z0-9]*-[a-zA-Z0-9-]+$/; + function process_component_options(component: Component, nodes) { const component_options: ComponentOptions = { immutable: component.compile_options.immutable || false, @@ -1473,7 +1479,7 @@ function process_component_options(component: Component, nodes) { const node = nodes.find(node => node.name === 'svelte:options'); - function get_value(attribute, {code, message}) { + function get_value(attribute, { code, message }) { const { value } = attribute; const chunk = value[0]; @@ -1505,7 +1511,7 @@ function process_component_options(component: Component, nodes) { return component.error(attribute, compiler_errors.invalid_tag_attribute); } - if (tag && !/^[a-zA-Z][a-zA-Z0-9]*-[a-zA-Z0-9-]+$/.test(tag)) { + if (tag && !regex_valid_tag_name.test(tag)) { return component.error(attribute, compiler_errors.invalid_tag_property); } diff --git a/src/compiler/compile/css/Selector.ts b/src/compiler/compile/css/Selector.ts index 17302c4abd..28cf5ba6af 100644 --- a/src/compiler/compile/css/Selector.ts +++ b/src/compiler/compile/css/Selector.ts @@ -9,6 +9,7 @@ import EachBlock from '../nodes/EachBlock'; import IfBlock from '../nodes/IfBlock'; import AwaitBlock from '../nodes/AwaitBlock'; import compiler_errors from '../compiler_errors'; +import { regex_starts_with_whitespace, regex_ends_with_whitespace } from '../../utils/patterns'; enum BlockAppliesToNode { NotPossible, @@ -25,6 +26,8 @@ const whitelist_attribute_selector = new Map([ ['dialog', new Set(['open'])] ]); +const regex_is_single_css_selector = /[^\\],(?!([^([]+[^\\]|[^([\\])[)\]])/; + export default class Selector { node: CssNode; stylesheet: Stylesheet; @@ -157,7 +160,7 @@ export default class Selector { for (const block of this.blocks) { for (const selector of block.selectors) { if (selector.type === 'PseudoClassSelector' && selector.name === 'global') { - if (/[^\\],(?!([^([]+[^\\]|[^([\\])[)\]])/.test(selector.children[0].value)) { + if (regex_is_single_css_selector.test(selector.children[0].value)) { component.error(selector, compiler_errors.css_invalid_global_selector); } } @@ -281,12 +284,14 @@ function apply_selector(blocks: Block[], node: Element, to_encapsulate: Array<{ return true; } +const regex_backslash_and_following_character = /\\(.)/g; + function block_might_apply_to_node(block: Block, node: Element): BlockAppliesToNode { let i = block.selectors.length; while (i--) { const selector = block.selectors[i]; - const name = typeof selector.name === 'string' && selector.name.replace(/\\(.)/g, '$1'); + const name = typeof selector.name === 'string' && selector.name.replace(regex_backslash_and_following_character, '$1'); if (selector.type === 'PseudoClassSelector' && (name === 'host' || name === 'root')) { return BlockAppliesToNode.NotPossible; @@ -371,7 +376,7 @@ function attribute_matches(node: CssNode, name: string, expected_value: string, const start_with_space = []; const remaining = []; current_possible_values.forEach((current_possible_value: string) => { - if (/^\s/.test(current_possible_value)) { + if (regex_starts_with_whitespace.test(current_possible_value)) { start_with_space.push(current_possible_value); } else { remaining.push(current_possible_value); @@ -392,7 +397,7 @@ function attribute_matches(node: CssNode, name: string, expected_value: string, prev_values = combined; start_with_space.forEach((value: string) => { - if (/\s$/.test(value)) { + if (regex_ends_with_whitespace.test(value)) { possible_values.add(value); } else { prev_values.push(value); @@ -406,7 +411,7 @@ function attribute_matches(node: CssNode, name: string, expected_value: string, } current_possible_values.forEach((current_possible_value: string) => { - if (/\s$/.test(current_possible_value)) { + if (regex_ends_with_whitespace.test(current_possible_value)) { possible_values.add(current_possible_value); } else { prev_values.push(current_possible_value); diff --git a/src/compiler/compile/css/Stylesheet.ts b/src/compiler/compile/css/Stylesheet.ts index 1a9ea7feeb..9a3cbe9d13 100644 --- a/src/compiler/compile/css/Stylesheet.ts +++ b/src/compiler/compile/css/Stylesheet.ts @@ -9,9 +9,12 @@ import hash from '../utils/hash'; import compiler_warnings from '../compiler_warnings'; import { extract_ignores_above_position } from '../../utils/extract_svelte_ignore'; import { push_array } from '../../utils/push_array'; +import { regex_only_whitespaces, regex_whitespace } from '../../utils/patterns'; + +const regex_css_browser_prefix = /^-((webkit)|(moz)|(o)|(ms))-/; function remove_css_prefix(name: string): string { - return name.replace(/^-((webkit)|(moz)|(o)|(ms))-/, ''); + return name.replace(regex_css_browser_prefix, ''); } const is_keyframes_node = (node: CssNode) => @@ -147,10 +150,10 @@ class Declaration { // Don't minify whitespace in custom properties, since some browsers (Chromium < 99) // treat --foo: ; and --foo:; differently - if (first.type === 'Raw' && /^\s+$/.test(first.value)) return; + if (first.type === 'Raw' && regex_only_whitespaces.test(first.value)) return; let start = first.start; - while (/\s/.test(code.original[start])) start += 1; + while (regex_whitespace.test(code.original[start])) start += 1; if (start - c > 1) { code.overwrite(c, start, ':'); diff --git a/src/compiler/compile/index.ts b/src/compiler/compile/index.ts index afe9c56cf4..a5edc3a6f7 100644 --- a/src/compiler/compile/index.ts +++ b/src/compiler/compile/index.ts @@ -35,6 +35,9 @@ const valid_options = [ 'cssHash' ]; +const regex_valid_identifier = /^[a-zA-Z_$][a-zA-Z_$0-9]*$/; +const regex_starts_with_lowercase_character = /^[a-z]/; + function validate_options(options: CompileOptions, warnings: Warning[]) { const { name, filename, loopGuardTimeout, dev, namespace } = options; @@ -48,11 +51,11 @@ function validate_options(options: CompileOptions, warnings: Warning[]) { } }); - if (name && !/^[a-zA-Z_$][a-zA-Z_$0-9]*$/.test(name)) { + if (name && !regex_valid_identifier.test(name)) { throw new Error(`options.name must be a valid identifier (got '${name}')`); } - if (name && /^[a-z]/.test(name)) { + if (name && regex_starts_with_lowercase_character.test(name)) { const message = 'options.name should be capitalised'; warnings.push({ code: 'options-lowercase-name', diff --git a/src/compiler/compile/nodes/Binding.ts b/src/compiler/compile/nodes/Binding.ts index 594490a5fb..f826df4828 100644 --- a/src/compiler/compile/nodes/Binding.ts +++ b/src/compiler/compile/nodes/Binding.ts @@ -3,7 +3,7 @@ import get_object from '../utils/get_object'; import Expression from './shared/Expression'; import Component from '../Component'; import TemplateScope from './shared/TemplateScope'; -import {dimensions} from '../../utils/patterns'; +import { regex_dimensions } from '../../utils/patterns'; import { Node as ESTreeNode } from 'estree'; import { TemplateNode } from '../../interfaces'; import Element from './Element'; @@ -88,7 +88,7 @@ export default class Binding extends Node { const type = parent.get_static_attribute_value('type'); this.is_readonly = - dimensions.test(this.name) || + regex_dimensions.test(this.name) || (isElement(parent) && ((parent.is_media_node() && read_only_media_attributes.has(this.name)) || (parent.name === 'input' && type === 'file')) /* TODO others? */); diff --git a/src/compiler/compile/nodes/Element.ts b/src/compiler/compile/nodes/Element.ts index 79f2800437..d5fad18f54 100644 --- a/src/compiler/compile/nodes/Element.ts +++ b/src/compiler/compile/nodes/Element.ts @@ -11,7 +11,7 @@ import StyleDirective from './StyleDirective'; import Text from './Text'; import { namespaces } from '../../utils/namespaces'; import map_children from './shared/map_children'; -import { dimensions, start_newline } from '../../utils/patterns'; +import { regex_dimensions, regex_starts_with_newline, regex_non_whitespace_character } from '../../utils/patterns'; import fuzzymatch from '../../utils/fuzzymatch'; import list from '../../utils/list'; import Let from './Let'; @@ -203,6 +203,10 @@ function is_valid_aria_attribute_value(schema: ARIAPropertyDefinition, value: st } } +const regex_any_repeated_whitespaces = /[\s]+/g; +const regex_heading_tags = /^h[1-6]$/; +const regex_illegal_attribute_character = /(^[0-9-.])|[\^$@%&#?!|()[\]{}^*+~;]/; + export default class Element extends Node { type: 'Element'; name: string; @@ -253,7 +257,7 @@ export default class Element extends Node { // places if there's another newline afterwards. // see https://html.spec.whatwg.org/multipage/syntax.html#element-restrictions // see https://html.spec.whatwg.org/multipage/grouping-content.html#the-pre-element - first.data = first.data.replace(start_newline, ''); + first.data = first.data.replace(regex_starts_with_newline, ''); } } @@ -398,7 +402,7 @@ export default class Element extends Node { // Errors - if (/(^[0-9-.])|[\^$@%&#?!|()[\]{}^*+~;]/.test(name)) { + if (regex_illegal_attribute_character.test(name)) { return component.error(attribute, compiler_errors.illegal_attribute(name)); } @@ -464,7 +468,7 @@ export default class Element extends Node { component.warn(attribute, compiler_warnings.a11y_unknown_aria_attribute(type, match)); } - if (name === 'aria-hidden' && /^h[1-6]$/.test(this.name)) { + if (name === 'aria-hidden' && regex_heading_tags.test(this.name)) { component.warn(attribute, compiler_warnings.a11y_hidden(this.name)); } @@ -729,7 +733,7 @@ export default class Element extends Node { if (this.name === 'figure') { const children = this.children.filter(node => { if (node.type === 'Comment') return false; - if (node.type === 'Text') return /\S/.test(node.data); + if (node.type === 'Text') return regex_non_whitespace_character.test(node.data); return true; }); @@ -861,7 +865,7 @@ export default class Element extends Node { if (this.name !== 'video') { return component.error(binding, compiler_errors.invalid_binding_element_with('