diff --git a/CHANGELOG.md b/CHANGELOG.md index 406f2a591ad7..759aabfd7dc1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Unreleased * Fix indirect bindings involving elements with spreads ([#3680](https://github.com/sveltejs/svelte/issues/3680)) +* Warn when using `` and `Foo` is dynamic ([#4331](https://github.com/sveltejs/svelte/issues/4331)) * Fix unneeded updating of keyed each blocks ([#4373](https://github.com/sveltejs/svelte/issues/4373)) ## 3.18.2 diff --git a/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts b/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts index 631c172576d9..f1c57ed09415 100644 --- a/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts +++ b/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts @@ -106,11 +106,28 @@ export default class InlineComponentWrapper extends Wrapper { block.add_outro(); } + warn_if_reactive() { + const { name } = this.node; + const variable = this.renderer.component.var_lookup.get(name); + if (!variable) { + return; + } + + if (variable.reassigned || variable.export_name || variable.is_reactive_dependency) { + this.renderer.component.warn(this.node, { + code: 'reactive-component', + message: `<${name}/> will not be reactive if ${name} changes. Use if you want this reactivity.`, + }); + } + } + render( block: Block, parent_node: Identifier, parent_nodes: Identifier ) { + this.warn_if_reactive(); + const { renderer } = this; const { component } = renderer; diff --git a/test/validator/index.js b/test/validator/index.js index 8bf0400d7c53..9bce5e149b4a 100644 --- a/test/validator/index.js +++ b/test/validator/index.js @@ -20,6 +20,7 @@ describe("validate", () => { const input = fs.readFileSync(`${__dirname}/samples/${dir}/input.svelte`, "utf-8").replace(/\s+$/, ""); const expected_warnings = tryToLoadJson(`${__dirname}/samples/${dir}/warnings.json`) || []; const expected_errors = tryToLoadJson(`${__dirname}/samples/${dir}/errors.json`); + const options = tryToLoadJson(`${__dirname}/samples/${dir}/options.json`); let error; @@ -28,7 +29,8 @@ describe("validate", () => { dev: config.dev, legacy: config.legacy, generate: false, - customElement: config.customElement + customElement: config.customElement, + ...options, }); assert.deepEqual(warnings.map(w => ({ diff --git a/test/validator/samples/component-dynamic/input.svelte b/test/validator/samples/component-dynamic/input.svelte new file mode 100644 index 000000000000..f591a84fe14c --- /dev/null +++ b/test/validator/samples/component-dynamic/input.svelte @@ -0,0 +1,18 @@ + + + + + + \ No newline at end of file diff --git a/test/validator/samples/component-dynamic/options.json b/test/validator/samples/component-dynamic/options.json new file mode 100644 index 000000000000..3a50892ebab1 --- /dev/null +++ b/test/validator/samples/component-dynamic/options.json @@ -0,0 +1,3 @@ +{ + "generate": true +} \ No newline at end of file diff --git a/test/validator/samples/component-dynamic/warnings.json b/test/validator/samples/component-dynamic/warnings.json new file mode 100644 index 000000000000..457ef11a1ed7 --- /dev/null +++ b/test/validator/samples/component-dynamic/warnings.json @@ -0,0 +1,47 @@ +[ + { + "code": "reactive-component", + "message": " will not be reactive if Let changes. Use if you want this reactivity.", + "pos": 190, + "end": { + "character": 197, + "column": 7, + "line": 15 + }, + "start": { + "character": 190, + "column": 0, + "line": 15 + } + }, + { + "message": " will not be reactive if ExportLet changes. Use if you want this reactivity.", + "code": "reactive-component", + "pos": 198, + "end": { + "character": 211, + "column": 13, + "line": 16 + }, + "start": { + "character": 198, + "column": 0, + "line": 16 + } + }, + { + "message": " will not be reactive if Reactive changes. Use if you want this reactivity.", + "code": "reactive-component", + "pos": 212, + "end": { + "character": 224, + "column": 12, + "line": 17 + }, + "start": { + "character": 212, + "column": 0, + "line": 17 + } + } +]