Skip to content

Commit 33f7e7f

Browse files
authored
fix: prevent error with bind:this={get, set} (#2781)
This transform bind:this={get, set} with a similar method as bind:this={ele}, but by invoking the set function. The get function is ignored.
1 parent ef92ff3 commit 33f7e7f

File tree

7 files changed

+26
-12
lines changed

7 files changed

+26
-12
lines changed

packages/svelte2tsx/src/htmlxtojsx_v2/nodes/Binding.ts

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,22 @@ export function handleBinding(
6060
isSvelte5Plus: boolean
6161
): void {
6262
const isGetSetBinding = attr.expression.type === 'SequenceExpression';
63+
const [get, set] = isGetSetBinding ? (attr.expression as SequenceExpression).expressions : [];
64+
65+
// bind this
66+
if (attr.name === 'this' && supportsBindThis.includes(parent.type)) {
67+
// bind:this is effectively only works bottom up - the variable is updated by the element, not
68+
// the other way round. So we check if the instance is assignable to the variable.
69+
// Note: If the component unmounts (it's inside an if block, or svelte:component this={null},
70+
// the value becomes null, but we don't add it to the clause because it would introduce
71+
// worse DX for the 99% use case, and because null !== undefined which others might use to type the declaration.
72+
if (isGetSetBinding) {
73+
element.appendToStartEnd(['(', [set.start, getEnd(set)], `)(${element.name});`]);
74+
} else {
75+
appendOneWayBinding(attr, ` = ${element.name}`, element);
76+
}
77+
return;
78+
}
6379

6480
if (!isGetSetBinding) {
6581
// bind group on input
@@ -69,17 +85,6 @@ export function handleBinding(
6985
return;
7086
}
7187

72-
// bind this
73-
if (attr.name === 'this' && supportsBindThis.includes(parent.type)) {
74-
// bind:this is effectively only works bottom up - the variable is updated by the element, not
75-
// the other way round. So we check if the instance is assignable to the variable.
76-
// Note: If the component unmounts (it's inside an if block, or svelte:component this={null},
77-
// the value becomes null, but we don't add it to the clause because it would introduce
78-
// worse DX for the 99% use case, and because null !== undefined which others might use to type the declaration.
79-
appendOneWayBinding(attr, ` = ${element.name}`, element);
80-
return;
81-
}
82-
8388
// one way binding
8489
if (oneWayBindingAttributes.has(attr.name) && element instanceof Element) {
8590
appendOneWayBinding(attr, `= ${element.name}.${attr.name}`, element);
@@ -125,7 +130,6 @@ export function handleBinding(
125130
]
126131
];
127132

128-
const [get, set] = isGetSetBinding ? (attr.expression as SequenceExpression).expressions : [];
129133
const value: TransformationArray | undefined = isShorthand
130134
? preserveBind && element instanceof Element
131135
? [rangeWithTrailingPropertyAccess(str.original, attr.expression)]
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{ const $$_div0 = svelteHTML.createElement("div", { });(set)($$_div0); }
2+
{ const $$_div0 = svelteHTML.createElement("div", { });(new_v => v = new_v)($$_div0); }
3+
4+
{ const $$_tupnI0C = __sveltets_2_ensureComponent(Input); const $$_tupnI0 = new $$_tupnI0C({ target: __sveltets_2_any(), props: { }});(set)($$_tupnI0); Input}
5+
{ const $$_tupnI0C = __sveltets_2_ensureComponent(Input); const $$_tupnI0 = new $$_tupnI0C({ target: __sveltets_2_any(), props: { }});(new_v => v = new_v)($$_tupnI0); Input}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<div bind:this={null, set}></div>
2+
<div bind:this={null, new_v => v = new_v}></div>
3+
4+
<Input bind:this={null, set}></Input>
5+
<Input bind:this={null, new_v => v = new_v}></Input>

0 commit comments

Comments
 (0)