fix adjacent bug around wrong value getting return upon mutation

pull/12123/head
Simon Holthausen 2 years ago
parent 48eef0d5b4
commit 82f47f3f37

@ -391,19 +391,20 @@ export function serialize_set_binding(node, context, fallback, prefix, options)
), ),
b.call('$.untrack', b.id('$' + left_name)) b.call('$.untrack', b.id('$' + left_name))
); );
} else if (!state.analysis.runes || (binding.mutated && binding.kind === 'bindable_prop')) { } else if (
!state.analysis.runes ||
// this condition can go away once legacy mode is gone; only necessary for interop with legacy parent bindings
(binding.mutated && binding.kind === 'bindable_prop')
) {
if (binding.kind === 'bindable_prop') { if (binding.kind === 'bindable_prop') {
return b.call( return b.call(
left, left,
b.sequence([ b.assignment(
b.assignment( node.operator,
node.operator, /** @type {import('estree').Pattern} */ (visit(node.left)),
/** @type {import('estree').Pattern} */ (visit(node.left)), value
value ),
), b.call(left)
b.call(left)
]),
b.true
); );
} else { } else {
return b.call( return b.call(

@ -268,16 +268,18 @@ export function prop(props, key, flags, fallback) {
// `bind:foo` which means we can just call `$$props.foo = value` directly // `bind:foo` which means we can just call `$$props.foo = value` directly
if (setter) { if (setter) {
var legacy_parent = props.$$legacy; var legacy_parent = props.$$legacy;
return function (/** @type {V} */ value, /** @type {boolean} */ mutation) { return function (/** @type {any} */ assigned_value, /** @type {V} */ new_value) {
if (arguments.length > 0) { if (arguments.length > 0) {
// We don't want to notify if the value was mutated and the parent is in runes mode. // We don't want to notify if the value was mutated and the parent is in runes mode.
// In that case the state proxy (if it exists) should take care of the notification. // In that case the state proxy (if it exists) should take care of the notification.
// If the parent is not in runes mode, we need to notify on mutation, too, that the prop // If the parent is not in runes mode, we need to notify on mutation, too, that the prop
// has changed because the parent will not be able to detect the change otherwise. // has changed because the parent will not be able to detect the change otherwise.
let mutation = arguments.length === 2;
if (!runes || !mutation || legacy_parent) { if (!runes || !mutation || legacy_parent) {
/** @type {Function} */ (setter)(value); // upon reassignment only the first argument is used
/** @type {Function} */ (setter)(!mutation ? assigned_value : new_value);
} }
return value; return assigned_value;
} else { } else {
return getter(); return getter();
} }
@ -309,7 +311,7 @@ export function prop(props, key, flags, fallback) {
if (!immutable) current_value.equals = safe_equals; if (!immutable) current_value.equals = safe_equals;
return function (/** @type {V} */ value) { return function (/** @type {any} */ reassigned_value, /** @type {V} */ new_value) {
var current = get(current_value); var current = get(current_value);
// legacy nonsense — need to ensure the source is invalidated when necessary // legacy nonsense — need to ensure the source is invalidated when necessary
@ -325,13 +327,15 @@ export function prop(props, key, flags, fallback) {
} }
if (arguments.length > 0) { if (arguments.length > 0) {
// upon reassignment only the first argument is used
const value = arguments.length === 1 ? reassigned_value : new_value;
if (!current_value.equals(value)) { if (!current_value.equals(value)) {
from_child = true; from_child = true;
set(inner_current_value, value); set(inner_current_value, value);
get(current_value); // force a synchronisation immediately get(current_value); // force a synchronisation immediately
} }
return value; return reassigned_value;
} }
return current; return current;

@ -0,0 +1,8 @@
import { test } from '../../test';
export default test({
mode: ['client'],
test({ assert, logs }) {
assert.deepEqual(logs, [true]);
}
});

@ -0,0 +1,4 @@
<script>
export let a = {};
console.log((a.b = true));
</script>
Loading…
Cancel
Save