diff --git a/CHANGELOG.md b/CHANGELOG.md index 9258e5a3b6..05de113ee2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ * Initialize stylesheet with `/* empty */` to enable setting CSP directive that also works in Safari ([#7800](https://github.com/sveltejs/svelte/pull/7800)) * Treat slots as if they don't exist when using CSS adjacent and general sibling combinators ([#8284](https://github.com/sveltejs/svelte/issues/8284)) * Fix transitions so that they don't require a `style-src 'unsafe-inline'` Content Security Policy (CSP) ([#6662](https://github.com/sveltejs/svelte/issues/6662)). +* Explicitly disallow `var` declarations extending the reactive statement scope ([#6800](https://github.com/sveltejs/svelte/pull/6800)) ## Unreleased (3.0) diff --git a/src/compiler/compile/Component.ts b/src/compiler/compile/Component.ts index 2ca04f3adf..f6ef17f641 100644 --- a/src/compiler/compile/Component.ts +++ b/src/compiler/compile/Component.ts @@ -26,7 +26,7 @@ import TemplateScope from './nodes/shared/TemplateScope'; import fuzzymatch from '../utils/fuzzymatch'; import get_object from './utils/get_object'; import Slot from './nodes/Slot'; -import { Node, ImportDeclaration, ExportNamedDeclaration, Identifier, ExpressionStatement, AssignmentExpression, Literal, Property, RestElement, ExportDefaultDeclaration, ExportAllDeclaration, FunctionDeclaration, FunctionExpression, ObjectExpression } from 'estree'; +import { Node, ImportDeclaration, ExportNamedDeclaration, Identifier, ExpressionStatement, AssignmentExpression, Literal, Property, RestElement, ExportDefaultDeclaration, ExportAllDeclaration, FunctionDeclaration, FunctionExpression, VariableDeclarator, ObjectExpression } from 'estree'; import add_to_set from './utils/add_to_set'; import check_graph_for_cycles from './utils/check_graph_for_cycles'; import { print, b } from 'code-red'; @@ -1356,10 +1356,23 @@ export default class Component { const module_dependencies = new Set(); let scope = this.instance_scope; + const { declarations: outset_scope_decalarations } = this.instance_scope; const map = this.instance_scope_map; walk(node.body, { enter(node: Node, parent) { + if (node.type === 'VariableDeclaration' && node.kind === 'var') { + const is_var_in_outset = node.declarations.some((declaration: VariableDeclarator) => { + const names: string[] = extract_names(declaration.id); + return !!names.find((name: string) => { + const var_node = outset_scope_decalarations.get(name); + return var_node === node; + }); + }); + if (is_var_in_outset) { + return component.error(node as any, compiler_errors.invalid_var_declaration); + } + } if (map.has(node)) { scope = map.get(node); } diff --git a/src/compiler/compile/compiler_errors.ts b/src/compiler/compile/compiler_errors.ts index 860fa20d9f..6b891d2574 100644 --- a/src/compiler/compile/compiler_errors.ts +++ b/src/compiler/compile/compiler_errors.ts @@ -300,6 +300,10 @@ export default { code: 'invalid-component-style-directive', message: 'Style directives cannot be used on components' }, + invalid_var_declaration: { + code: 'invalid_var_declaration', + message: '"var" scope should not extend outside the reactive block' + }, invalid_style_directive_modifier: (valid: string) => ({ code: 'invalid-style-directive-modifier', message: `Valid modifiers for style directives are: ${valid}` diff --git a/test/validator/samples/invalid-reactive-var-1/errors.json b/test/validator/samples/invalid-reactive-var-1/errors.json new file mode 100644 index 0000000000..9316d51168 --- /dev/null +++ b/test/validator/samples/invalid-reactive-var-1/errors.json @@ -0,0 +1,6 @@ +[{ + "code": "invalid_var_declaration", + "message": "\"var\" scope should not extend outside the reactive block", + "start": { "line": 14, "column": 7 }, + "end": { "line": 14, "column": 16 } +}] diff --git a/test/validator/samples/invalid-reactive-var-1/input.svelte b/test/validator/samples/invalid-reactive-var-1/input.svelte new file mode 100644 index 0000000000..7fe774959d --- /dev/null +++ b/test/validator/samples/invalid-reactive-var-1/input.svelte @@ -0,0 +1,20 @@ + + +

Hello {a}

diff --git a/test/validator/samples/invalid-reactive-var-2/errors.json b/test/validator/samples/invalid-reactive-var-2/errors.json new file mode 100644 index 0000000000..c28d767778 --- /dev/null +++ b/test/validator/samples/invalid-reactive-var-2/errors.json @@ -0,0 +1,6 @@ +[{ + "code": "invalid_var_declaration", + "message": "\"var\" scope should not extend outside the reactive block", + "start": { "line": 4, "column": 2 }, + "end": { "line": 4, "column": 50 } +}] diff --git a/test/validator/samples/invalid-reactive-var-2/input.svelte b/test/validator/samples/invalid-reactive-var-2/input.svelte new file mode 100644 index 0000000000..b3a1c4272c --- /dev/null +++ b/test/validator/samples/invalid-reactive-var-2/input.svelte @@ -0,0 +1,8 @@ + + +

Hello

diff --git a/test/validator/samples/valid-reactive-vars/errors.json b/test/validator/samples/valid-reactive-vars/errors.json new file mode 100644 index 0000000000..fe51488c70 --- /dev/null +++ b/test/validator/samples/valid-reactive-vars/errors.json @@ -0,0 +1 @@ +[] diff --git a/test/validator/samples/valid-reactive-vars/input.svelte b/test/validator/samples/valid-reactive-vars/input.svelte new file mode 100644 index 0000000000..0052101bd9 --- /dev/null +++ b/test/validator/samples/valid-reactive-vars/input.svelte @@ -0,0 +1,18 @@ + + +

Hello {name}