Skip to content

Commit 3d30067

Browse files
fix: mark custom element with virtual class attribute as dynamic (#13435)
Closes #13426
1 parent 65ca213 commit 3d30067

File tree

8 files changed

+36
-3
lines changed

8 files changed

+36
-3
lines changed

.changeset/tiny-ads-press.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
fix: mark custom element with virtual class attribute as dynamic

packages/svelte/src/compiler/phases/1-parse/state/element.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,8 @@ export default function element(parser) {
151151
svg: false,
152152
mathml: false,
153153
scoped: false,
154-
has_spread: false
154+
has_spread: false,
155+
path: []
155156
},
156157
parent: null
157158
}

packages/svelte/src/compiler/phases/2-analyze/index.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { extract_identifiers, is_text_attribute } from '../../utils/ast.js';
99
import * as b from '../../utils/builders.js';
1010
import { Scope, ScopeRoot, create_scopes, get_rune, set_scope } from '../scope.js';
1111
import check_graph_for_cycles from './utils/check_graph_for_cycles.js';
12-
import { create_attribute } from '../nodes.js';
12+
import { create_attribute, is_custom_element_node } from '../nodes.js';
1313
import { analyze_css } from './css/css-analyze.js';
1414
import { prune } from './css/css-prune.js';
1515
import { hash, is_rune } from '../../../utils.js';
@@ -67,6 +67,7 @@ import { UpdateExpression } from './visitors/UpdateExpression.js';
6767
import { UseDirective } from './visitors/UseDirective.js';
6868
import { VariableDeclarator } from './visitors/VariableDeclarator.js';
6969
import is_reference from 'is-reference';
70+
import { mark_subtree_dynamic } from './visitors/shared/fragment.js';
7071

7172
/**
7273
* @type {Visitors}
@@ -743,6 +744,9 @@ export function analyze_component(root, source, options) {
743744
}
744745
])
745746
);
747+
if (is_custom_element_node(element) && element.attributes.length === 1) {
748+
mark_subtree_dynamic(element.metadata.path);
749+
}
746750
}
747751
}
748752
}

packages/svelte/src/compiler/phases/2-analyze/visitors/RegularElement.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ export function RegularElement(node, context) {
2222

2323
check_element(node, context.state);
2424

25+
node.metadata.path = [...context.path];
26+
2527
context.state.analysis.elements.push(node);
2628

2729
// Special case: Move the children of <textarea> into a value attribute if they are dynamic

packages/svelte/src/compiler/phases/nodes.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export function is_element_node(node) {
2323

2424
/**
2525
* @param {AST.RegularElement | AST.SvelteElement} node
26-
* @returns {boolean}
26+
* @returns {node is AST.RegularElement}
2727
*/
2828
export function is_custom_element_node(node) {
2929
return node.type === 'RegularElement' && node.name.includes('-');

packages/svelte/src/compiler/types/template.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,7 @@ export namespace AST {
303303
/** `true` if contains a SpreadAttribute */
304304
has_spread: boolean;
305305
scoped: boolean;
306+
path: SvelteNode[];
306307
};
307308
}
308309

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { test } from '../../test';
2+
3+
export default test({
4+
async test({ assert, target, logs }) {
5+
const [my_element, my_element_1] = target.querySelectorAll('my-element');
6+
assert.equal(my_element.classList.contains('svelte-1koh33s'), true);
7+
assert.equal(my_element_1.classList.contains('svelte-1koh33s'), true);
8+
}
9+
});
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<div>
2+
<my-element></my-element>
3+
</div>
4+
<my-element></my-element>
5+
6+
7+
<style>
8+
my-element{
9+
background: red;
10+
}
11+
</style>

0 commit comments

Comments
 (0)