diff --git a/.changeset/dirty-jars-tap.md b/.changeset/dirty-jars-tap.md new file mode 100644 index 0000000000..35a2772e48 --- /dev/null +++ b/.changeset/dirty-jars-tap.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: error on duplicate style and class directive diff --git a/packages/svelte/src/compiler/phases/1-parse/state/element.js b/packages/svelte/src/compiler/phases/1-parse/state/element.js index b6184913eb..e1a23822f2 100644 --- a/packages/svelte/src/compiler/phases/1-parse/state/element.js +++ b/packages/svelte/src/compiler/phases/1-parse/state/element.js @@ -189,12 +189,24 @@ export default function element(parser) { let attribute; while ((attribute = read(parser))) { - if (attribute.type === 'Attribute' || attribute.type === 'BindDirective') { - if (unique_names.includes(attribute.name)) { + // animate and transition can only be specified once per element so no need + // to check here, use can be used multiple times, same for the on directive + // finally let already has error handling in case of duplicate variable names + if ( + attribute.type === 'Attribute' || + attribute.type === 'BindDirective' || + attribute.type === 'StyleDirective' || + attribute.type === 'ClassDirective' + ) { + // `bind:attribute` and `attribute` are just the same but `class:attribute`, + // `style:attribute` and `attribute` are different and should be allowed together + // so we concatenate the type while normalizing the type for BindDirective + const type = attribute.type === 'BindDirective' ? 'Attribute' : attribute.type; + if (unique_names.includes(type + attribute.name)) { e.attribute_duplicate(attribute); // is allowed } else if (attribute.name !== 'this') { - unique_names.push(attribute.name); + unique_names.push(type + attribute.name); } } diff --git a/packages/svelte/tests/compiler-errors/samples/attribute-unique-class/_config.js b/packages/svelte/tests/compiler-errors/samples/attribute-unique-class/_config.js new file mode 100644 index 0000000000..1100af993b --- /dev/null +++ b/packages/svelte/tests/compiler-errors/samples/attribute-unique-class/_config.js @@ -0,0 +1,9 @@ +import { test } from '../../test'; + +export default test({ + error: { + code: 'attribute_duplicate', + message: 'Attributes need to be unique', + position: [23, 40] + } +}); diff --git a/packages/svelte/tests/compiler-errors/samples/attribute-unique-class/main.svelte b/packages/svelte/tests/compiler-errors/samples/attribute-unique-class/main.svelte new file mode 100644 index 0000000000..b3a79e704f --- /dev/null +++ b/packages/svelte/tests/compiler-errors/samples/attribute-unique-class/main.svelte @@ -0,0 +1 @@ +
\ No newline at end of file diff --git a/packages/svelte/tests/compiler-errors/samples/attribute-unique-style/_config.js b/packages/svelte/tests/compiler-errors/samples/attribute-unique-style/_config.js new file mode 100644 index 0000000000..17b76e02b4 --- /dev/null +++ b/packages/svelte/tests/compiler-errors/samples/attribute-unique-style/_config.js @@ -0,0 +1,9 @@ +import { test } from '../../test'; + +export default test({ + error: { + code: 'attribute_duplicate', + message: 'Attributes need to be unique', + position: [23, 42] + } +}); diff --git a/packages/svelte/tests/compiler-errors/samples/attribute-unique-style/main.svelte b/packages/svelte/tests/compiler-errors/samples/attribute-unique-style/main.svelte new file mode 100644 index 0000000000..3303929616 --- /dev/null +++ b/packages/svelte/tests/compiler-errors/samples/attribute-unique-style/main.svelte @@ -0,0 +1 @@ +
\ No newline at end of file diff --git a/packages/svelte/tests/validator/samples/attribute-unique-allowed/errors.json b/packages/svelte/tests/validator/samples/attribute-unique-allowed/errors.json new file mode 100644 index 0000000000..fe51488c70 --- /dev/null +++ b/packages/svelte/tests/validator/samples/attribute-unique-allowed/errors.json @@ -0,0 +1 @@ +[] diff --git a/packages/svelte/tests/validator/samples/attribute-unique-allowed/input.svelte b/packages/svelte/tests/validator/samples/attribute-unique-allowed/input.svelte new file mode 100644 index 0000000000..475be6f546 --- /dev/null +++ b/packages/svelte/tests/validator/samples/attribute-unique-allowed/input.svelte @@ -0,0 +1 @@ +
\ No newline at end of file