Skip to content

Commit

Permalink
fix: muted reactive without bind and select/autofocus attributes …
Browse files Browse the repository at this point in the history
…working with function calls

Co-authored-by: Joel Howse <[email protected]>
  • Loading branch information
paoloricciuti and jhwz committed Feb 17, 2025
1 parent 575900d commit e26d8ff
Show file tree
Hide file tree
Showing 8 changed files with 82 additions and 10 deletions.
5 changes: 5 additions & 0 deletions .changeset/silver-ties-itch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'svelte': patch
---

fix: `muted` reactive without `bind` and select/autofocus attributes working with function calls
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ import {
build_render_statement,
build_template_chunk,
build_update_assignment,
get_expression_id
get_expression_id,
memoize_expression
} from './shared/utils.js';
import { visit_event_attribute } from './shared/events.js';

Expand Down Expand Up @@ -532,18 +533,28 @@ function build_element_attribute_update_assignment(
const is_svg = context.state.metadata.namespace === 'svg' || element.name === 'svg';
const is_mathml = context.state.metadata.namespace === 'mathml';

const is_autofocus = name === 'autofocus';

let { value, has_state } = build_attribute_value(attribute.value, context, (value, metadata) =>
metadata.has_call ? get_expression_id(state, value) : value
metadata.has_call
? is_autofocus
? memoize_expression(state, value)
: get_expression_id(state, value)
: value
);

if (name === 'autofocus') {
if (is_autofocus) {
state.init.push(b.stmt(b.call('$.autofocus', node_id, value)));
return false;
}

// Special case for Firefox who needs it set as a property in order to work
if (name === 'muted') {
state.init.push(b.stmt(b.assignment('=', b.member(node_id, b.id('muted')), value)));
if (!has_state) {
state.init.push(b.stmt(b.assignment('=', b.member(node_id, b.id('muted')), value)));
return false;
}
state.update.push(b.stmt(b.assignment('=', b.member(node_id, b.id('muted')), value)));
return false;
}

Expand Down Expand Up @@ -660,8 +671,17 @@ function build_custom_element_attribute_update_assignment(node_id, attribute, co
*/
function build_element_special_value_attribute(element, node_id, attribute, context) {
const state = context.state;
const is_select_with_value =
// attribute.metadata.dynamic would give false negatives because even if the value does not change,
// the inner options could still change, so we need to always treat it as reactive
element === 'select' && attribute.value !== true && !is_text_attribute(attribute);

const { value, has_state } = build_attribute_value(attribute.value, context, (value, metadata) =>
metadata.has_call ? get_expression_id(state, value) : value
metadata.has_call
? is_select_with_value
? memoize_expression(context.state, value)
: get_expression_id(state, value)
: value
);

const inner_assignment = b.assignment(
Expand All @@ -674,11 +694,6 @@ function build_element_special_value_attribute(element, node_id, attribute, cont
)
);

const is_select_with_value =
// attribute.metadata.dynamic would give false negatives because even if the value does not change,
// the inner options could still change, so we need to always treat it as reactive
element === 'select' && attribute.value !== true && !is_text_attribute(attribute);

const update = b.stmt(
is_select_with_value
? b.sequence([
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { test } from '../../test';

export default test({
async test({ assert, errors }) {
assert.deepEqual(errors, []);
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<svelte:options runes />
<script>
function test(){}
</script>

<input autofocus={test()} />
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { flushSync } from 'svelte';
import { ok, test } from '../../test';

export default test({
async test({ assert, target, logs }) {
const btn = target.querySelector('button');
ok(btn);
flushSync(() => {
btn.click();
});
assert.deepEqual(logs, [true]);
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<script>
let muted = $state(false);
function volume_change(node){
node.addEventListener("volumechange", () => {
console.log(node.muted);
});
}
</script>

<audio use:volume_change {muted}></audio>
<button onclick={() => (muted = !muted)}></button>

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { test } from '../../test';

export default test({
async test({ assert, errors }) {
assert.deepEqual(errors, []);
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<svelte:options runes />
<script>
function test(){}
</script>

<select value={test()}></select>

0 comments on commit e26d8ff

Please sign in to comment.