From 9a28416aa36ca0426569b356810ee4e8de1b3d0b Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Wed, 3 Mar 2021 09:23:18 +0800 Subject: [PATCH 01/18] should not extend scope for across slots --- src/compiler/compile/nodes/Slot.ts | 22 ------------------- .../Nested.svelte | 11 ++++++++++ .../component-slot-default-in-each/_config.js | 7 ++++++ .../main.svelte | 7 ++++++ .../Nested.svelte | 2 -- .../_config.js | 4 ++-- 6 files changed, 27 insertions(+), 26 deletions(-) create mode 100644 test/runtime/samples/component-slot-default-in-each/Nested.svelte create mode 100644 test/runtime/samples/component-slot-default-in-each/_config.js create mode 100644 test/runtime/samples/component-slot-default-in-each/main.svelte diff --git a/src/compiler/compile/nodes/Slot.ts b/src/compiler/compile/nodes/Slot.ts index c21a48f5d665..0ad5cc849e27 100644 --- a/src/compiler/compile/nodes/Slot.ts +++ b/src/compiler/compile/nodes/Slot.ts @@ -37,28 +37,6 @@ export default class Slot extends Element { if (!this.slot_name) this.slot_name = 'default'; - if (this.slot_name === 'default') { - // if this is the default slot, add our dependencies to any - // other slots (which inherit our slot values) that were - // previously encountered - component.slots.forEach((slot) => { - this.values.forEach((attribute, name) => { - if (!slot.values.has(name)) { - slot.values.set(name, attribute); - } - }); - }); - } else if (component.slots.has('default')) { - // otherwise, go the other way — inherit values from - // a previously encountered default slot - const default_slot = component.slots.get('default'); - default_slot.values.forEach((attribute, name) => { - if (!this.values.has(name)) { - this.values.set(name, attribute); - } - }); - } - component.slots.set(this.slot_name, this); } } diff --git a/test/runtime/samples/component-slot-default-in-each/Nested.svelte b/test/runtime/samples/component-slot-default-in-each/Nested.svelte new file mode 100644 index 000000000000..d21684310196 --- /dev/null +++ b/test/runtime/samples/component-slot-default-in-each/Nested.svelte @@ -0,0 +1,11 @@ + + +{#each {length: 3} as _, i} + +{/each} + +{#await promise then value} + +{/await} diff --git a/test/runtime/samples/component-slot-default-in-each/_config.js b/test/runtime/samples/component-slot-default-in-each/_config.js new file mode 100644 index 000000000000..5c0fd13871d5 --- /dev/null +++ b/test/runtime/samples/component-slot-default-in-each/_config.js @@ -0,0 +1,7 @@ +export default { + html: ` +
0 - undefined
+
1 - undefined
+
2 - undefined
+ ` +}; diff --git a/test/runtime/samples/component-slot-default-in-each/main.svelte b/test/runtime/samples/component-slot-default-in-each/main.svelte new file mode 100644 index 000000000000..2ff707e04db3 --- /dev/null +++ b/test/runtime/samples/component-slot-default-in-each/main.svelte @@ -0,0 +1,7 @@ + + + +
{item} - {value}
+
\ No newline at end of file diff --git a/test/runtime/samples/component-slot-named-inherits-default-lets/Nested.svelte b/test/runtime/samples/component-slot-named-inherits-default-lets/Nested.svelte index 472af6278ea8..cecce8db0196 100644 --- a/test/runtime/samples/component-slot-named-inherits-default-lets/Nested.svelte +++ b/test/runtime/samples/component-slot-named-inherits-default-lets/Nested.svelte @@ -1,6 +1,4 @@ diff --git a/test/validator/samples/lets-on-component/input.svelte b/test/validator/samples/lets-on-component/input.svelte new file mode 100644 index 000000000000..b72ee8c07440 --- /dev/null +++ b/test/validator/samples/lets-on-component/input.svelte @@ -0,0 +1,27 @@ + + + +

+ count in default slot: {count} +

+

+ count in bar slot: {count} +

+
+ + +

+ count in default slot: {count} +

+

+ count in bar slot: {count} +

+
+ + +

+ count in bar slot: {count} +

+
diff --git a/test/validator/samples/lets-on-component/warnings.json b/test/validator/samples/lets-on-component/warnings.json new file mode 100644 index 000000000000..54debf49c69f --- /dev/null +++ b/test/validator/samples/lets-on-component/warnings.json @@ -0,0 +1,62 @@ +[ + { + "code": "let-on-component", + "message": "let: bindings on Component are meant for default slot template only, it is better to define them on instead.", + "pos": 59, + "start": { + "character": 59, + "column": 0, + "line": 5 + }, + "end": { + "character": 182, + "column": 9, + "line": 12 + } + }, + { + "code": "missing-declaration", + "message": "'count' is not defined", + "pos": 160, + "start": { + "character": 160, + "column": 22, + "line": 10 + }, + "end": { + "character": 165, + "column": 27, + "line": 10 + } + }, + { + "code": "let-on-component", + "message": "let: bindings on Component are meant for default slot template only, it is better to define them on instead.", + "pos": 298, + "start": { + "character": 298, + "column": 0, + "line": 23 + }, + "end": { + "character": 377, + "column": 9, + "line": 27 + } + }, + { + "code": "missing-declaration", + "message": "'count' is not defined", + "pos": 355, + "start": { + "character": 355, + "column": 22, + "line": 25 + }, + "end": { + "character": 360, + "column": 27, + "line": 25 + } + } +] From bc115a8731238fa5fb0bfca4365016252fa0fad6 Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Thu, 4 Mar 2021 10:43:33 +0800 Subject: [PATCH 03/18] fix tests --- src/compiler/compile/render_ssr/handlers/Slot.ts | 6 ------ .../samples/component-slot-nested-in-slot/One.svelte | 6 ++++-- .../component-svelte-fragment-let-aliased/main.svelte | 4 ++-- .../samples/component-svelte-fragment-let-b/main.svelte | 4 ++-- .../samples/component-svelte-fragment-let-e/A.svelte | 4 ++-- .../samples/component-svelte-fragment-let-e/_config.js | 4 ---- .../samples/component-svelte-fragment-let-e/main.svelte | 6 ------ 7 files changed, 10 insertions(+), 24 deletions(-) diff --git a/src/compiler/compile/render_ssr/handlers/Slot.ts b/src/compiler/compile/render_ssr/handlers/Slot.ts index f89b619c466d..781e62bb0024 100644 --- a/src/compiler/compile/render_ssr/handlers/Slot.ts +++ b/src/compiler/compile/render_ssr/handlers/Slot.ts @@ -26,12 +26,6 @@ export default function(node: Slot, renderer: Renderer, options: RenderOptions & `); if (slot && nearest_inline_component) { - const lets = node.lets; - const seen = new Set(lets.map(l => l.name.name)); - - nearest_inline_component.lets.forEach(l => { - if (!seen.has(l.name.name)) lets.push(l); - }); options.slot_scopes.set(slot, { input: get_slot_scope(node.lets), output: renderer.pop() diff --git a/test/runtime/samples/component-slot-nested-in-slot/One.svelte b/test/runtime/samples/component-slot-nested-in-slot/One.svelte index e27437c450fc..acb6a03358be 100644 --- a/test/runtime/samples/component-slot-nested-in-slot/One.svelte +++ b/test/runtime/samples/component-slot-nested-in-slot/One.svelte @@ -3,6 +3,8 @@ export let a, b; - - + + + + diff --git a/test/runtime/samples/component-svelte-fragment-let-aliased/main.svelte b/test/runtime/samples/component-svelte-fragment-let-aliased/main.svelte index dabf1d65ef0c..5ca0cbbd100c 100644 --- a/test/runtime/samples/component-svelte-fragment-let-aliased/main.svelte +++ b/test/runtime/samples/component-svelte-fragment-let-aliased/main.svelte @@ -4,8 +4,8 @@ export let things; - - + + {x} \ No newline at end of file diff --git a/test/runtime/samples/component-svelte-fragment-let-b/main.svelte b/test/runtime/samples/component-svelte-fragment-let-b/main.svelte index 584240d14d27..bb24b97a3b15 100644 --- a/test/runtime/samples/component-svelte-fragment-let-b/main.svelte +++ b/test/runtime/samples/component-svelte-fragment-let-b/main.svelte @@ -2,8 +2,8 @@ import Nested from './Nested.svelte'; - - + + {count} \ No newline at end of file diff --git a/test/runtime/samples/component-svelte-fragment-let-e/A.svelte b/test/runtime/samples/component-svelte-fragment-let-e/A.svelte index 3ba0e62cd961..f982aef7b14b 100644 --- a/test/runtime/samples/component-svelte-fragment-let-e/A.svelte +++ b/test/runtime/samples/component-svelte-fragment-let-e/A.svelte @@ -3,8 +3,8 @@ export let x; - - + + {reflected} diff --git a/test/runtime/samples/component-svelte-fragment-let-e/_config.js b/test/runtime/samples/component-svelte-fragment-let-e/_config.js index 967955dfd856..74de38be02cc 100644 --- a/test/runtime/samples/component-svelte-fragment-let-e/_config.js +++ b/test/runtime/samples/component-svelte-fragment-let-e/_config.js @@ -2,8 +2,6 @@ export default { html: ` 1 1 - 1 - 1 `, async test({ assert, target, component }) { @@ -12,8 +10,6 @@ export default { assert.htmlEqual(target.innerHTML, ` 2 2 - 2 - 2 `); } }; diff --git a/test/runtime/samples/component-svelte-fragment-let-e/main.svelte b/test/runtime/samples/component-svelte-fragment-let-e/main.svelte index 80c9a868cd44..e95c8d927414 100644 --- a/test/runtime/samples/component-svelte-fragment-let-e/main.svelte +++ b/test/runtime/samples/component-svelte-fragment-let-e/main.svelte @@ -8,9 +8,3 @@ {reflected} - - - - {reflected} - - \ No newline at end of file From a4fbc314cf615dacb13c5c51ac25617931b79687 Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Thu, 4 Mar 2021 13:26:11 +0800 Subject: [PATCH 04/18] fix test --- src/compiler/compile/nodes/shared/Expression.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/compile/nodes/shared/Expression.ts b/src/compiler/compile/nodes/shared/Expression.ts index 0603c15589d2..d35a3cbb5cbd 100644 --- a/src/compiler/compile/nodes/shared/Expression.ts +++ b/src/compiler/compile/nodes/shared/Expression.ts @@ -323,8 +323,8 @@ export default class Expression { const func_expression = func_declaration[0]; - if (node.type === 'InlineComponent' || node.type === 'SlotTemplate') { - // + if (node.type === 'SlotTemplate') { + // this.replace(func_expression); } else { // {#each}, {#await} From bd1bd4f42fc4453882413d95c64bddc604b3b4e5 Mon Sep 17 00:00:00 2001 From: gtmnayan Date: Wed, 24 May 2023 13:30:05 +0545 Subject: [PATCH 05/18] fix --- src/compiler/compile/nodes/InlineComponent.js | 1 - .../samples/lets-on-component/warnings.json | 12 ------------ 2 files changed, 13 deletions(-) diff --git a/src/compiler/compile/nodes/InlineComponent.js b/src/compiler/compile/nodes/InlineComponent.js index 53ba44408233..7eed473f37b9 100644 --- a/src/compiler/compile/nodes/InlineComponent.js +++ b/src/compiler/compile/nodes/InlineComponent.js @@ -81,7 +81,6 @@ export default class InlineComponent extends Node { break; case 'Let': let_attributes.push(node); - this.lets.push(new Let(component, this, scope, node)); break; case 'Transition': return component.error(node, compiler_errors.invalid_transition); diff --git a/test/validator/samples/lets-on-component/warnings.json b/test/validator/samples/lets-on-component/warnings.json index 54debf49c69f..6243a8491b0f 100644 --- a/test/validator/samples/lets-on-component/warnings.json +++ b/test/validator/samples/lets-on-component/warnings.json @@ -2,14 +2,11 @@ { "code": "let-on-component", "message": "let: bindings on Component are meant for default slot template only, it is better to define them on instead.", - "pos": 59, "start": { - "character": 59, "column": 0, "line": 5 }, "end": { - "character": 182, "column": 9, "line": 12 } @@ -17,14 +14,11 @@ { "code": "missing-declaration", "message": "'count' is not defined", - "pos": 160, "start": { - "character": 160, "column": 22, "line": 10 }, "end": { - "character": 165, "column": 27, "line": 10 } @@ -32,14 +26,11 @@ { "code": "let-on-component", "message": "let: bindings on Component are meant for default slot template only, it is better to define them on instead.", - "pos": 298, "start": { - "character": 298, "column": 0, "line": 23 }, "end": { - "character": 377, "column": 9, "line": 27 } @@ -47,14 +38,11 @@ { "code": "missing-declaration", "message": "'count' is not defined", - "pos": 355, "start": { - "character": 355, "column": 22, "line": 25 }, "end": { - "character": 360, "column": 27, "line": 25 } From 6111352451967a7a44d6a5525e734ab16dc59aab Mon Sep 17 00:00:00 2001 From: gtmnayan Date: Wed, 24 May 2023 13:53:41 +0545 Subject: [PATCH 06/18] add runtime tests --- .../samples/component-slot-let-scope-2/Nested.svelte | 3 +++ .../runtime/samples/component-slot-let-scope-2/_config.js | 3 +++ .../samples/component-slot-let-scope-2/main.svelte | 8 ++++++++ .../samples/component-slot-let-scope/Nested.svelte | 2 ++ test/runtime/samples/component-slot-let-scope/_config.js | 3 +++ test/runtime/samples/component-slot-let-scope/main.svelte | 8 ++++++++ 6 files changed, 27 insertions(+) create mode 100644 test/runtime/samples/component-slot-let-scope-2/Nested.svelte create mode 100644 test/runtime/samples/component-slot-let-scope-2/_config.js create mode 100644 test/runtime/samples/component-slot-let-scope-2/main.svelte create mode 100644 test/runtime/samples/component-slot-let-scope/Nested.svelte create mode 100644 test/runtime/samples/component-slot-let-scope/_config.js create mode 100644 test/runtime/samples/component-slot-let-scope/main.svelte diff --git a/test/runtime/samples/component-slot-let-scope-2/Nested.svelte b/test/runtime/samples/component-slot-let-scope-2/Nested.svelte new file mode 100644 index 000000000000..e231bf1a7feb --- /dev/null +++ b/test/runtime/samples/component-slot-let-scope-2/Nested.svelte @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/test/runtime/samples/component-slot-let-scope-2/_config.js b/test/runtime/samples/component-slot-let-scope-2/_config.js new file mode 100644 index 000000000000..b4a181dc6766 --- /dev/null +++ b/test/runtime/samples/component-slot-let-scope-2/_config.js @@ -0,0 +1,3 @@ +export default { + html: `undefined2` +}; diff --git a/test/runtime/samples/component-slot-let-scope-2/main.svelte b/test/runtime/samples/component-slot-let-scope-2/main.svelte new file mode 100644 index 000000000000..8454c4acd178 --- /dev/null +++ b/test/runtime/samples/component-slot-let-scope-2/main.svelte @@ -0,0 +1,8 @@ + + + + {thing} + {thing} + \ No newline at end of file diff --git a/test/runtime/samples/component-slot-let-scope/Nested.svelte b/test/runtime/samples/component-slot-let-scope/Nested.svelte new file mode 100644 index 000000000000..772955e06efa --- /dev/null +++ b/test/runtime/samples/component-slot-let-scope/Nested.svelte @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/test/runtime/samples/component-slot-let-scope/_config.js b/test/runtime/samples/component-slot-let-scope/_config.js new file mode 100644 index 000000000000..d8fbab2bae68 --- /dev/null +++ b/test/runtime/samples/component-slot-let-scope/_config.js @@ -0,0 +1,3 @@ +export default { + error: `thing is not defined` +}; diff --git a/test/runtime/samples/component-slot-let-scope/main.svelte b/test/runtime/samples/component-slot-let-scope/main.svelte new file mode 100644 index 000000000000..e10a9a858491 --- /dev/null +++ b/test/runtime/samples/component-slot-let-scope/main.svelte @@ -0,0 +1,8 @@ + + + + {thing} + \ No newline at end of file From c4bf84a421e9562016fa4379599700d9010d8e05 Mon Sep 17 00:00:00 2001 From: gtmnayan Date: Fri, 26 May 2023 09:43:57 +0545 Subject: [PATCH 07/18] rename test since it doesn't inherit anymore --- .../Nested.svelte | 0 .../_config.js | 0 .../main.svelte | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename test/runtime/samples/{component-slot-named-inherits-default-lets => component-slot-let-scope-3}/Nested.svelte (100%) rename test/runtime/samples/{component-slot-named-inherits-default-lets => component-slot-let-scope-3}/_config.js (100%) rename test/runtime/samples/{component-slot-named-inherits-default-lets => component-slot-let-scope-3}/main.svelte (100%) diff --git a/test/runtime/samples/component-slot-named-inherits-default-lets/Nested.svelte b/test/runtime/samples/component-slot-let-scope-3/Nested.svelte similarity index 100% rename from test/runtime/samples/component-slot-named-inherits-default-lets/Nested.svelte rename to test/runtime/samples/component-slot-let-scope-3/Nested.svelte diff --git a/test/runtime/samples/component-slot-named-inherits-default-lets/_config.js b/test/runtime/samples/component-slot-let-scope-3/_config.js similarity index 100% rename from test/runtime/samples/component-slot-named-inherits-default-lets/_config.js rename to test/runtime/samples/component-slot-let-scope-3/_config.js diff --git a/test/runtime/samples/component-slot-named-inherits-default-lets/main.svelte b/test/runtime/samples/component-slot-let-scope-3/main.svelte similarity index 100% rename from test/runtime/samples/component-slot-named-inherits-default-lets/main.svelte rename to test/runtime/samples/component-slot-let-scope-3/main.svelte From 3ed219ea1acfe98c7e1676ea448b237a3055915f Mon Sep 17 00:00:00 2001 From: gtmnayan Date: Fri, 26 May 2023 16:52:47 +0545 Subject: [PATCH 08/18] fix lint --- test/runtime/samples/component-slot-let-scope-2/_config.js | 2 +- test/runtime/samples/component-slot-let-scope/_config.js | 2 +- .../runtime/samples/component-svelte-fragment-let-e/_config.js | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/test/runtime/samples/component-slot-let-scope-2/_config.js b/test/runtime/samples/component-slot-let-scope-2/_config.js index b4a181dc6766..6b2059f03d0b 100644 --- a/test/runtime/samples/component-slot-let-scope-2/_config.js +++ b/test/runtime/samples/component-slot-let-scope-2/_config.js @@ -1,3 +1,3 @@ export default { - html: `undefined2` + html: 'undefined2' }; diff --git a/test/runtime/samples/component-slot-let-scope/_config.js b/test/runtime/samples/component-slot-let-scope/_config.js index d8fbab2bae68..c0f4d293055e 100644 --- a/test/runtime/samples/component-slot-let-scope/_config.js +++ b/test/runtime/samples/component-slot-let-scope/_config.js @@ -1,3 +1,3 @@ export default { - error: `thing is not defined` + error: 'thing is not defined' }; diff --git a/test/runtime/samples/component-svelte-fragment-let-e/_config.js b/test/runtime/samples/component-svelte-fragment-let-e/_config.js index 403a198db3eb..1ececbb3efe8 100644 --- a/test/runtime/samples/component-svelte-fragment-let-e/_config.js +++ b/test/runtime/samples/component-svelte-fragment-let-e/_config.js @@ -12,6 +12,7 @@ export default { ` 2 2 - `); + ` + ); } }; From a983324a17d83fa7e3a4d82205c6ecb19ba70b86 Mon Sep 17 00:00:00 2001 From: gtmnayan Date: Fri, 26 May 2023 17:24:09 +0545 Subject: [PATCH 09/18] remove warnings --- src/compiler/compile/nodes/InlineComponent.js | 8 ------- .../samples/lets-on-component/warnings.json | 24 ------------------- 2 files changed, 32 deletions(-) diff --git a/src/compiler/compile/nodes/InlineComponent.js b/src/compiler/compile/nodes/InlineComponent.js index 7eed473f37b9..e41ec37af1f7 100644 --- a/src/compiler/compile/nodes/InlineComponent.js +++ b/src/compiler/compile/nodes/InlineComponent.js @@ -162,20 +162,12 @@ export default class InlineComponent extends Node { } if (let_attributes.length) { - let warned = false; // copy let: attribute from to // as they are for `slot="default"` only children.forEach((child) => { const slot = child.attributes.find((attribute) => attribute.name === 'slot'); if (!slot || slot.value[0].data === 'default') { child.attributes.push(...let_attributes); - } else if (!warned) { - component.warn(info, { - code: 'let-on-component', - message: - 'let: bindings on Component are meant for default slot template only, it is better to define them on instead.' - }); - warned = true; } }); } diff --git a/test/validator/samples/lets-on-component/warnings.json b/test/validator/samples/lets-on-component/warnings.json index 6243a8491b0f..dc5bb7da002f 100644 --- a/test/validator/samples/lets-on-component/warnings.json +++ b/test/validator/samples/lets-on-component/warnings.json @@ -1,16 +1,4 @@ [ - { - "code": "let-on-component", - "message": "let: bindings on Component are meant for default slot template only, it is better to define them on instead.", - "start": { - "column": 0, - "line": 5 - }, - "end": { - "column": 9, - "line": 12 - } - }, { "code": "missing-declaration", "message": "'count' is not defined", @@ -23,18 +11,6 @@ "line": 10 } }, - { - "code": "let-on-component", - "message": "let: bindings on Component are meant for default slot template only, it is better to define them on instead.", - "start": { - "column": 0, - "line": 23 - }, - "end": { - "column": 9, - "line": 27 - } - }, { "code": "missing-declaration", "message": "'count' is not defined", From f7b1ff8ec92c9851dd44fb16e39f11d50e3cb616 Mon Sep 17 00:00:00 2001 From: gtmnayan Date: Fri, 26 May 2023 17:26:42 +0545 Subject: [PATCH 10/18] add compile script --- scripts/compile-test.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 scripts/compile-test.js diff --git a/scripts/compile-test.js b/scripts/compile-test.js new file mode 100644 index 000000000000..bbc0379433c7 --- /dev/null +++ b/scripts/compile-test.js @@ -0,0 +1,28 @@ +import { mkdirSync, readFileSync, writeFileSync } from 'fs'; +import path from 'path'; +import glob from 'tiny-glob/sync.js'; +import { compile } from '../src/compiler/index.js'; + +const cwd = path.resolve(process.argv[2]); + +const options = [ + ['normal', {}], + ['hydrate', { hydratable: true }], + ['ssr', { generate: 'ssr' }] +]; +for (const file of glob('**/*.svelte', { cwd })) { + const contents = readFileSync(`${cwd}/${file}`, 'utf-8').replace(/\r/g, ''); + + for (const [name, opts] of options) { + const dir = `${cwd}/_output/${name}`; + + const { js, css } = compile(contents, { + ...opts, + filename: file + }); + + mkdirSync(dir, { recursive: true }); + js.code && writeFileSync(`${dir}/${file.replace(/\.svelte$/, '.js')}`, js.code); + css.code && writeFileSync(`${dir}/${file.replace(/\.svelte$/, '.css')}`, css.code); + } +} From 36f98aca655fa3249c1b1d66eeb51bc886621ce2 Mon Sep 17 00:00:00 2001 From: gtmnayan Date: Fri, 26 May 2023 19:22:24 +0545 Subject: [PATCH 11/18] document script --- scripts/compile-test.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/scripts/compile-test.js b/scripts/compile-test.js index bbc0379433c7..d2be2183ed49 100644 --- a/scripts/compile-test.js +++ b/scripts/compile-test.js @@ -1,3 +1,6 @@ +// Compile all Svelte files in a directory to JS and CSS files +// Usage: node scripts/compile-test.js + import { mkdirSync, readFileSync, writeFileSync } from 'fs'; import path from 'path'; import glob from 'tiny-glob/sync.js'; @@ -12,17 +15,26 @@ const options = [ ]; for (const file of glob('**/*.svelte', { cwd })) { const contents = readFileSync(`${cwd}/${file}`, 'utf-8').replace(/\r/g, ''); - + let w; for (const [name, opts] of options) { const dir = `${cwd}/_output/${name}`; - const { js, css } = compile(contents, { + const { js, css, warnings } = compile(contents, { ...opts, filename: file }); + if (warnings.length) { + w = warnings; + } + mkdirSync(dir, { recursive: true }); js.code && writeFileSync(`${dir}/${file.replace(/\.svelte$/, '.js')}`, js.code); css.code && writeFileSync(`${dir}/${file.replace(/\.svelte$/, '.css')}`, css.code); } + + if (w) { + console.log(`Warnings for ${file}:`); + console.log(w); + } } From b27dd26cab1e2351e15e8ace2c329bdb52dd11bd Mon Sep 17 00:00:00 2001 From: gtmnayan Date: Fri, 26 May 2023 19:31:18 +0545 Subject: [PATCH 12/18] improve warning --- src/compiler/compile/Component.js | 11 ++++++++++- src/compiler/compile/nodes/InlineComponent.js | 4 +++- src/compiler/compile/nodes/shared/Expression.js | 4 +++- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/compiler/compile/Component.js b/src/compiler/compile/Component.js index 5a4b063651d8..1778f89d27e2 100644 --- a/src/compiler/compile/Component.js +++ b/src/compiler/compile/Component.js @@ -1644,8 +1644,9 @@ export default class Component { * @param {string} name * @param {any} node * @param {import('./nodes/shared/TemplateScope.js').default} template_scope + * @param {import("./nodes/shared/Node.js").default} [owner] */ - warn_if_undefined(name, node, template_scope) { + warn_if_undefined(name, node, template_scope, owner) { if (name[0] === '$') { if (name === '$' || (name[1] === '$' && !is_reserved_keyword(name))) { return this.error(node, compiler_errors.illegal_global(name)); @@ -1657,6 +1658,14 @@ export default class Component { if (this.var_lookup.has(name) && !this.var_lookup.get(name).global) return; if (template_scope && template_scope.names.has(name)) return; if (globals.has(name) && node.type !== 'InlineComponent') return; + + if (owner?.find_nearest(/InlineComponent/)?.let_attributes.find((attr) => attr.name === name)) { + return this.warn(node, { + code: 'missing-declaration', + message: `let:${name} declared on parent component cannot be used inside named slot` + }); + } + this.warn(node, compiler_warnings.missing_declaration(name, !!this.ast.instance)); } diff --git a/src/compiler/compile/nodes/InlineComponent.js b/src/compiler/compile/nodes/InlineComponent.js index e41ec37af1f7..f863f265fe44 100644 --- a/src/compiler/compile/nodes/InlineComponent.js +++ b/src/compiler/compile/nodes/InlineComponent.js @@ -33,6 +33,8 @@ export default class InlineComponent extends Node { /** @type {string} */ namespace; + /** @type {Node[]} */ + let_attributes; /** * @param {import('../Component.js').default} component * @param {import('./shared/Node.js').default} parent @@ -55,7 +57,7 @@ export default class InlineComponent extends Node { ? new Expression(component, this, scope, info.expression) : null; - const let_attributes = []; + const let_attributes = this.let_attributes = []; info.attributes.forEach( /** @param {any} node */ (node) => { /* eslint-disable no-fallthrough */ diff --git a/src/compiler/compile/nodes/shared/Expression.js b/src/compiler/compile/nodes/shared/Expression.js index c9621ab6c45b..c4877f7c84ee 100644 --- a/src/compiler/compile/nodes/shared/Expression.js +++ b/src/compiler/compile/nodes/shared/Expression.js @@ -77,6 +77,7 @@ export default class Expression { this.scope_map = map; const expression = this; let function_expression; + // discover dependencies, but don't change the code yet walk(info, { /** @@ -125,7 +126,7 @@ export default class Expression { dependencies.add(name); } component.add_reference(node, name); - component.warn_if_undefined(name, nodes[0], template_scope); + component.warn_if_undefined(name, nodes[0], template_scope, owner); } this.skip(); } @@ -459,6 +460,7 @@ export default class Expression { } } }); + if (declarations.length > 0) { block.maintain_context = true; declarations.forEach( From c6e3e6d739cf973db22ff8e634e155ac62fd24de Mon Sep 17 00:00:00 2001 From: gtmnayan Date: Fri, 26 May 2023 19:32:08 +0545 Subject: [PATCH 13/18] fix test --- test/validator/samples/lets-on-component/warnings.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/validator/samples/lets-on-component/warnings.json b/test/validator/samples/lets-on-component/warnings.json index dc5bb7da002f..9fb7827b47ea 100644 --- a/test/validator/samples/lets-on-component/warnings.json +++ b/test/validator/samples/lets-on-component/warnings.json @@ -1,7 +1,7 @@ [ { "code": "missing-declaration", - "message": "'count' is not defined", + "message": "let:count declared on parent component cannot be used inside named slot", "start": { "column": 22, "line": 10 @@ -13,7 +13,7 @@ }, { "code": "missing-declaration", - "message": "'count' is not defined", + "message": "let:count declared on parent component cannot be used inside named slot", "start": { "column": 22, "line": 25 From 86802101ff420ef8ace7dc88135b1ab0bb008ffa Mon Sep 17 00:00:00 2001 From: gtmnayan Date: Fri, 26 May 2023 19:45:59 +0545 Subject: [PATCH 14/18] handle renames --- src/compiler/compile/Component.js | 9 ++++++++- test/validator/samples/lets-on-component/input.svelte | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/compiler/compile/Component.js b/src/compiler/compile/Component.js index 1778f89d27e2..fc98a323b848 100644 --- a/src/compiler/compile/Component.js +++ b/src/compiler/compile/Component.js @@ -1659,7 +1659,14 @@ export default class Component { if (template_scope && template_scope.names.has(name)) return; if (globals.has(name) && node.type !== 'InlineComponent') return; - if (owner?.find_nearest(/InlineComponent/)?.let_attributes.find((attr) => attr.name === name)) { + if ( + owner?.find_nearest(/InlineComponent/)?.let_attributes.find((attr) => { + // TODO: let:foo={{ bar }} doesn't work properly cause it's returned as an + // ObjectExpression instead of a Pattern + const names = attr.expression ? extract_names(attr.expression) : [attr.name]; + return names.includes(name); + }) + ) { return this.warn(node, { code: 'missing-declaration', message: `let:${name} declared on parent component cannot be used inside named slot` diff --git a/test/validator/samples/lets-on-component/input.svelte b/test/validator/samples/lets-on-component/input.svelte index b72ee8c07440..8ad7424245e0 100644 --- a/test/validator/samples/lets-on-component/input.svelte +++ b/test/validator/samples/lets-on-component/input.svelte @@ -20,7 +20,7 @@

- +

count in bar slot: {count}

From 46cdb12534f4cf26e1e08b97a75e9f0cf14c6825 Mon Sep 17 00:00:00 2001 From: gtmnayan Date: Fri, 26 May 2023 19:49:12 +0545 Subject: [PATCH 15/18] fix lint --- scripts/compile-test.js | 4 ++-- src/compiler/compile/nodes/InlineComponent.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/compile-test.js b/scripts/compile-test.js index d2be2183ed49..9a83708b3833 100644 --- a/scripts/compile-test.js +++ b/scripts/compile-test.js @@ -25,8 +25,8 @@ for (const file of glob('**/*.svelte', { cwd })) { }); if (warnings.length) { - w = warnings; - } + w = warnings; + } mkdirSync(dir, { recursive: true }); js.code && writeFileSync(`${dir}/${file.replace(/\.svelte$/, '.js')}`, js.code); diff --git a/src/compiler/compile/nodes/InlineComponent.js b/src/compiler/compile/nodes/InlineComponent.js index f863f265fe44..9aafe3965ca6 100644 --- a/src/compiler/compile/nodes/InlineComponent.js +++ b/src/compiler/compile/nodes/InlineComponent.js @@ -57,7 +57,7 @@ export default class InlineComponent extends Node { ? new Expression(component, this, scope, info.expression) : null; - const let_attributes = this.let_attributes = []; + const let_attributes = (this.let_attributes = []); info.attributes.forEach( /** @param {any} node */ (node) => { /* eslint-disable no-fallthrough */ From 7fa1615142b9b81028bf56e94cb777fd9bc9370f Mon Sep 17 00:00:00 2001 From: gtmnayan Date: Fri, 26 May 2023 21:31:51 +0545 Subject: [PATCH 16/18] gather names from all parents instead of just the nearest --- src/compiler/compile/Component.js | 29 ++++++++++++++----- src/compiler/compile/nodes/InlineComponent.js | 2 +- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/compiler/compile/Component.js b/src/compiler/compile/Component.js index fc98a323b848..161633d1e918 100644 --- a/src/compiler/compile/Component.js +++ b/src/compiler/compile/Component.js @@ -28,6 +28,7 @@ import { extract_svelte_ignore_from_comments } from '../utils/extract_svelte_ignore.js'; import check_enable_sourcemap from './utils/check_enable_sourcemap.js'; +import Attribute from './nodes/Attribute.js'; const regex_leading_directory_separator = /^[/\\]/; const regex_starts_with_term_export = /^Export/; @@ -1659,14 +1660,26 @@ export default class Component { if (template_scope && template_scope.names.has(name)) return; if (globals.has(name) && node.type !== 'InlineComponent') return; - if ( - owner?.find_nearest(/InlineComponent/)?.let_attributes.find((attr) => { - // TODO: let:foo={{ bar }} doesn't work properly cause it's returned as an - // ObjectExpression instead of a Pattern - const names = attr.expression ? extract_names(attr.expression) : [attr.name]; - return names.includes(name); - }) - ) { + function has_out_of_scope_let() { + for (let parent = owner.parent; parent; parent = parent.parent) { + if (parent.type === 'InlineComponent') { + const { let_attributes } = parent; + + for (const attr of let_attributes) { + if ( + // @ts-expect-error + (attr.expression && extract_names(attr.expression).includes(name)) || + attr.name === name + ) + return true; + } + } + } + + return false; + } + + if (owner && has_out_of_scope_let()) { return this.warn(node, { code: 'missing-declaration', message: `let:${name} declared on parent component cannot be used inside named slot` diff --git a/src/compiler/compile/nodes/InlineComponent.js b/src/compiler/compile/nodes/InlineComponent.js index 9aafe3965ca6..d30358f6bde7 100644 --- a/src/compiler/compile/nodes/InlineComponent.js +++ b/src/compiler/compile/nodes/InlineComponent.js @@ -33,7 +33,7 @@ export default class InlineComponent extends Node { /** @type {string} */ namespace; - /** @type {Node[]} */ + /** @type {Attribute[]} */ let_attributes; /** * @param {import('../Component.js').default} component From 0cb7561470dad4b290b62f235c9c1add5f6e364e Mon Sep 17 00:00:00 2001 From: gtmnayan Date: Fri, 26 May 2023 21:34:16 +0545 Subject: [PATCH 17/18] remove unused import --- src/compiler/compile/Component.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/compiler/compile/Component.js b/src/compiler/compile/Component.js index 161633d1e918..71802d092fab 100644 --- a/src/compiler/compile/Component.js +++ b/src/compiler/compile/Component.js @@ -28,7 +28,6 @@ import { extract_svelte_ignore_from_comments } from '../utils/extract_svelte_ignore.js'; import check_enable_sourcemap from './utils/check_enable_sourcemap.js'; -import Attribute from './nodes/Attribute.js'; const regex_leading_directory_separator = /^[/\\]/; const regex_starts_with_term_export = /^Export/; From aa0f75694effd973bf7528d60ee0be9601be72db Mon Sep 17 00:00:00 2001 From: gtmnayan Date: Fri, 26 May 2023 21:52:28 +0545 Subject: [PATCH 18/18] add reminder --- src/compiler/compile/Component.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/compiler/compile/Component.js b/src/compiler/compile/Component.js index 71802d092fab..084063aff315 100644 --- a/src/compiler/compile/Component.js +++ b/src/compiler/compile/Component.js @@ -1667,6 +1667,7 @@ export default class Component { for (const attr of let_attributes) { if ( // @ts-expect-error + // TODO extract_names only considers patterns but let attributes return expressions (attr.expression && extract_names(attr.expression).includes(name)) || attr.name === name )