diff --git a/documentation/docs/98-reference/.generated/compile-errors.md b/documentation/docs/98-reference/.generated/compile-errors.md index 20f57770d122..957a9f67c7b0 100644 --- a/documentation/docs/98-reference/.generated/compile-errors.md +++ b/documentation/docs/98-reference/.generated/compile-errors.md @@ -364,6 +364,12 @@ The $ name is reserved, and cannot be used for variables and imports The $ prefix is reserved, and cannot be used for variables and imports ``` +### duplicate_class_field + +``` +`%name%` has already been declared +``` + ### each_item_invalid_assignment ``` diff --git a/packages/svelte/CHANGELOG.md b/packages/svelte/CHANGELOG.md index 450ecde53b1e..766c83763acc 100644 --- a/packages/svelte/CHANGELOG.md +++ b/packages/svelte/CHANGELOG.md @@ -1,5 +1,13 @@ # svelte +## 5.36.17 + +### Patch Changes + +- fix: throw on duplicate class field declarations ([#16502](https://github.com/sveltejs/svelte/pull/16502)) + +- fix: add types for `part` attribute to svg attributes ([#16499](https://github.com/sveltejs/svelte/pull/16499)) + ## 5.36.16 ### Patch Changes diff --git a/packages/svelte/elements.d.ts b/packages/svelte/elements.d.ts index 604241592aff..2e1042dfd6b8 100644 --- a/packages/svelte/elements.d.ts +++ b/packages/svelte/elements.d.ts @@ -1553,6 +1553,7 @@ export interface SVGAttributes extends AriaAttributes, DO height?: number | string | undefined | null; id?: string | undefined | null; lang?: string | undefined | null; + part?: string | undefined | null; max?: number | string | undefined | null; media?: string | undefined | null; // On the `textPath` element diff --git a/packages/svelte/messages/compile-errors/script.md b/packages/svelte/messages/compile-errors/script.md index 2b0c5eafdf86..5c1080acedfe 100644 --- a/packages/svelte/messages/compile-errors/script.md +++ b/packages/svelte/messages/compile-errors/script.md @@ -30,6 +30,10 @@ > The $ prefix is reserved, and cannot be used for variables and imports +## duplicate_class_field + +> `%name%` has already been declared + ## each_item_invalid_assignment > Cannot reassign or bind to each block argument in runes mode. Use the array and index variables instead (e.g. `array[i] = value` instead of `entry = value`, or `bind:value={array[i]}` instead of `bind:value={entry}`) diff --git a/packages/svelte/package.json b/packages/svelte/package.json index 07954026b550..22bc8cc8fac6 100644 --- a/packages/svelte/package.json +++ b/packages/svelte/package.json @@ -2,7 +2,7 @@ "name": "svelte", "description": "Cybernetically enhanced web apps", "license": "MIT", - "version": "5.36.16", + "version": "5.36.17", "type": "module", "types": "./types/index.d.ts", "engines": { diff --git a/packages/svelte/src/compiler/errors.js b/packages/svelte/src/compiler/errors.js index 599d3e8248b0..e763a6e0733a 100644 --- a/packages/svelte/src/compiler/errors.js +++ b/packages/svelte/src/compiler/errors.js @@ -152,6 +152,16 @@ export function dollar_prefix_invalid(node) { e(node, 'dollar_prefix_invalid', `The $ prefix is reserved, and cannot be used for variables and imports\nhttps://svelte.dev/e/dollar_prefix_invalid`); } +/** + * `%name%` has already been declared + * @param {null | number | NodeLike} node + * @param {string} name + * @returns {never} + */ +export function duplicate_class_field(node, name) { + e(node, 'duplicate_class_field', `\`${name}\` has already been declared\nhttps://svelte.dev/e/duplicate_class_field`); +} + /** * Cannot reassign or bind to each block argument in runes mode. Use the array and index variables instead (e.g. `array[i] = value` instead of `entry = value`, or `bind:value={array[i]}` instead of `bind:value={entry}`) * @param {null | number | NodeLike} node diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/ClassBody.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/ClassBody.js index ffc39ac00de1..2bfc1dbce36c 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/visitors/ClassBody.js +++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/ClassBody.js @@ -33,6 +33,9 @@ export function ClassBody(node, context) { /** @type {Map} */ const state_fields = new Map(); + /** @type {Map>} */ + const fields = new Map(); + context.state.analysis.classes.set(node, state_fields); /** @type {MethodDefinition | null} */ @@ -54,6 +57,14 @@ export function ClassBody(node, context) { e.state_field_duplicate(node, name); } + const _key = (key.type === 'PrivateIdentifier' ? '#' : '') + name; + const field = fields.get(_key); + + // if there's already a method or assigned field, error + if (field && !(field.length === 1 && field[0] === 'prop')) { + e.duplicate_class_field(node, _key); + } + state_fields.set(name, { node, type: rune, @@ -67,10 +78,48 @@ export function ClassBody(node, context) { for (const child of node.body) { if (child.type === 'PropertyDefinition' && !child.computed && !child.static) { handle(child, child.key, child.value); + const key = (child.key.type === 'PrivateIdentifier' ? '#' : '') + get_name(child.key); + const field = fields.get(key); + if (!field) { + fields.set(key, [child.value ? 'assigned_prop' : 'prop']); + continue; + } + e.duplicate_class_field(child, key); } - if (child.type === 'MethodDefinition' && child.kind === 'constructor') { - constructor = child; + if (child.type === 'MethodDefinition') { + if (child.kind === 'constructor') { + constructor = child; + } else if (!child.computed) { + const key = (child.key.type === 'PrivateIdentifier' ? '#' : '') + get_name(child.key); + const field = fields.get(key); + if (!field) { + fields.set(key, [child.kind]); + continue; + } + if ( + field.includes(child.kind) || + field.includes('prop') || + field.includes('assigned_prop') + ) { + e.duplicate_class_field(child, key); + } + if (child.kind === 'get') { + if (field.length === 1 && field[0] === 'set') { + field.push('get'); + continue; + } + } else if (child.kind === 'set') { + if (field.length === 1 && field[0] === 'get') { + field.push('set'); + continue; + } + } else { + field.push(child.kind); + continue; + } + e.duplicate_class_field(child, key); + } } } diff --git a/packages/svelte/src/version.js b/packages/svelte/src/version.js index 5d76fc3f2963..d2992a3dcd8c 100644 --- a/packages/svelte/src/version.js +++ b/packages/svelte/src/version.js @@ -4,5 +4,5 @@ * The current version, as set in package.json. * @type {string} */ -export const VERSION = '5.36.16'; +export const VERSION = '5.36.17'; export const PUBLIC_VERSION = '5'; diff --git a/packages/svelte/tests/validator/samples/class-state-constructor-9/errors.json b/packages/svelte/tests/validator/samples/class-state-constructor-9/errors.json index b7dd4c8ed457..94b5f191c2f7 100644 --- a/packages/svelte/tests/validator/samples/class-state-constructor-9/errors.json +++ b/packages/svelte/tests/validator/samples/class-state-constructor-9/errors.json @@ -1,14 +1,14 @@ [ { - "code": "state_field_invalid_assignment", - "message": "Cannot assign to a state field before its declaration", + "code": "duplicate_class_field", + "message": "`count` has already been declared", "start": { - "line": 2, - "column": 1 + "line": 5, + "column": 2 }, "end": { - "line": 2, - "column": 12 + "line": 5, + "column": 24 } } ] pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy