diff --git a/packages/alpinejs/src/scope.js b/packages/alpinejs/src/scope.js index 5a629b6ca..7028b5e96 100644 --- a/packages/alpinejs/src/scope.js +++ b/packages/alpinejs/src/scope.js @@ -64,14 +64,14 @@ let mergeProxyTrap = { ) }, - set({ objects }, name, value) { - return Reflect.set( - objects.find((obj) => + set({ objects }, name, value, thisProxy) { + const target = objects.find((obj) => Object.prototype.hasOwnProperty.call(obj, name) - ) || objects[objects.length-1], - name, - value - ) + ) || objects[objects.length - 1]; + const descriptor = Object.getOwnPropertyDescriptor(target, name); + if (descriptor?.set && descriptor?.get) + return Reflect.set(target, name, value, thisProxy); + return Reflect.set(target, name, value); }, } diff --git a/tests/cypress/integration/scope.spec.js b/tests/cypress/integration/scope.spec.js new file mode 100644 index 000000000..b5fcfbbf9 --- /dev/null +++ b/tests/cypress/integration/scope.spec.js @@ -0,0 +1,58 @@ +import { haveText, html, test } from "../utils"; + +test( + "properly merges the datastack", + [ + html` +
+
+ +
+
+ `, + ], + ({ get }) => { + get("span").should(haveText("fizzbuzz")); + } +); + +test( + "merges stack from bottom up", + [ + html` +
+
+ +
+ +
+ `, + ], + ({ get }) => { + get("span#one").should(haveText("buzzbuzz")); + get("span#two").should(haveText("fizz")); + } +); + +test( + "handles getter setter pairs", + [ + html` +
+
+ +
+ +
+ `, + ], + ({ get }) => { + get("span#one").should(haveText("fizzbuzz")); + get("span#two").should(haveText("fizzbuzz")); + get("span#one").click(); + get("span#one").should(haveText("foobar")); + get("span#two").should(haveText("foobar")); + } +);