Skip to content

Commit

Permalink
fix: deconflict get_name for literal class properties (#14607)
Browse files Browse the repository at this point in the history
  • Loading branch information
paoloricciuti authored Dec 9, 2024
1 parent 38171f6 commit 1176463
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/stupid-buckets-drum.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'svelte': patch
---

fix: deconflict `get_name` for literal class properties
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ export function ClassBody(node, context) {
/** @type {Map<string, StateField>} */
const private_state = new Map();

/** @type {Map<(MethodDefinition|PropertyDefinition)["key"], string>} */
const definition_names = new Map();

/** @type {string[]} */
const private_ids = [];

Expand All @@ -34,9 +37,12 @@ export function ClassBody(node, context) {
definition.key.type === 'Literal')
) {
const type = definition.key.type;
const name = get_name(definition.key);
const name = get_name(definition.key, public_state);
if (!name) continue;

// we store the deconflicted name in the map so that we can access it later
definition_names.set(definition.key, name);

const is_private = type === 'PrivateIdentifier';
if (is_private) private_ids.push(name);

Expand Down Expand Up @@ -96,7 +102,7 @@ export function ClassBody(node, context) {
definition.key.type === 'PrivateIdentifier' ||
definition.key.type === 'Literal')
) {
const name = get_name(definition.key);
const name = definition_names.get(definition.key);
if (!name) continue;

const is_private = definition.key.type === 'PrivateIdentifier';
Expand Down Expand Up @@ -210,10 +216,20 @@ export function ClassBody(node, context) {

/**
* @param {Identifier | PrivateIdentifier | Literal} node
* @param {Map<string, StateField>} public_state
*/
function get_name(node) {
function get_name(node, public_state) {
if (node.type === 'Literal') {
return node.value?.toString().replace(regex_invalid_identifier_chars, '_');
let name = node.value?.toString().replace(regex_invalid_identifier_chars, '_');

// the above could generate conflicts because it has to generate a valid identifier
// so stuff like `0` and `1` or `state%` and `state^` will result in the same string
// so we have to de-conflict. We can only check `public_state` because private state
// can't have literal keys
while (name && public_state.has(name)) {
name = '_' + name;
}
return name;
} else {
return node.name;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { test } from '../../test';

export default test({});
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<script>
class Test {
0 = $state();
1 = $state();
}
</script>

0 comments on commit 1176463

Please sign in to comment.