Skip to content

Commit 541cb8e

Browse files
authored
🐛 Fixes issue with setters accessing deeply nested data (#4265)
1 parent 1927cb1 commit 541cb8e

File tree

2 files changed

+50
-1
lines changed

2 files changed

+50
-1
lines changed

packages/alpinejs/src/scope.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ let mergeProxyTrap = {
7272
) || objects[objects.length - 1];
7373
const descriptor = Object.getOwnPropertyDescriptor(target, name);
7474
if (descriptor?.set && descriptor?.get)
75-
return Reflect.set(target, name, value, thisProxy);
75+
// Can't use Reflect.set here due to [upstream bug](https://github.com/vuejs/core/blob/31abdc8adad569d83b476c340e678c4daa901545/packages/reactivity/src/baseHandlers.ts#L148) in @vue/reactivity
76+
return descriptor.set.call(thisProxy, value) || true;
7677
return Reflect.set(target, name, value);
7778
},
7879
}

tests/cypress/integration/scope.spec.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,3 +109,51 @@ test(
109109
get("button").should(haveText("clicked"));
110110
}
111111
);
112+
113+
test(
114+
"properly merges the datastack with nested data",
115+
[
116+
html`
117+
<div x-data="{ foo: { bar: 'fizz' } }">
118+
<div x-data="{ bar: 'buzz' }">
119+
<span
120+
id="1"
121+
x-text="foo.bar + bar"
122+
@click="foo.bar = foo.bar + bar"
123+
></span>
124+
</div>
125+
<span id="2" x-text="foo.bar"></span>
126+
</div>
127+
`,
128+
],
129+
({ get }) => {
130+
get("span#1").should(haveText("fizzbuzz"));
131+
get("span#2").should(haveText("fizz"));
132+
get("span#1").click();
133+
get("span#1").should(haveText("fizzbuzzbuzz"));
134+
get("span#2").should(haveText("fizzbuzz"));
135+
}
136+
);
137+
138+
test(
139+
"handles getter setter pairs of object",
140+
[
141+
html`
142+
<div x-data="{ foo: { bar: 'fizzbuzz' } }">
143+
<div
144+
x-data="{ get bar() { return this.foo.bar }, set bar(value) { this.foo.bar = value } }"
145+
>
146+
<span id="one" x-text="bar" @click="bar = 'foobar'"></span>
147+
</div>
148+
<span id="two" x-text="foo.bar"></span>
149+
</div>
150+
`,
151+
],
152+
({ get }) => {
153+
get("span#one").should(haveText("fizzbuzz"));
154+
get("span#two").should(haveText("fizzbuzz"));
155+
get("span#one").click();
156+
get("span#one").should(haveText("foobar"));
157+
get("span#two").should(haveText("foobar"));
158+
}
159+
);

0 commit comments

Comments
 (0)