Skip to content

Commit 417eac9

Browse files
committed
fix class/prototype getters not getting wrapped + tests
1 parent bb6ce8b commit 417eac9

2 files changed

Lines changed: 80 additions & 2 deletions

File tree

packages/solid/store/src/store.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { getListener, batch, DEV, $PROXY, $TRACK, createSignal } from "solid-js";
1+
import { $PROXY, $TRACK, batch, createSignal, DEV, getListener } from "solid-js";
22

33
export const $RAW = Symbol("store-raw"),
44
$NODE = Symbol("store-node"),
@@ -49,11 +49,27 @@ function wrap<T extends StoreNode>(value: T): T {
4949
Object.defineProperty(value, $PROXY, { value: (p = new Proxy(value, proxyTraps)) });
5050
if (!Array.isArray(value)) {
5151
const keys = Object.keys(value),
52-
desc = Object.getOwnPropertyDescriptors(value);
52+
desc = Object.getOwnPropertyDescriptors(value),
53+
proto = Object.getPrototypeOf(value);
54+
55+
const isClass =
56+
proto !== null &&
57+
value !== null &&
58+
typeof value === "object" &&
59+
!Array.isArray(value) &&
60+
proto !== Object.prototype;
61+
if (isClass) {
62+
const descriptors = Object.getOwnPropertyDescriptors(proto);
63+
keys.push(...Object.keys(descriptors));
64+
Object.assign(desc, descriptors);
65+
}
66+
5367
for (let i = 0, l = keys.length; i < l; i++) {
5468
const prop = keys[i];
69+
if (isClass && prop === "constructor") continue;
5570
if (desc[prop].get) {
5671
Object.defineProperty(value, prop, {
72+
configurable: true,
5773
enumerable: desc[prop].enumerable,
5874
get: desc[prop].get!.bind(p)
5975
});

packages/solid/store/test/store.spec.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -722,6 +722,37 @@ describe("Nested Classes", () => {
722722
expect(sum).toBe(15);
723723
});
724724

725+
test("wrapped nested class getter", () => {
726+
class CustomThing {
727+
a: number;
728+
b: number;
729+
constructor(value: number) {
730+
this.a = value;
731+
this.b = 10;
732+
}
733+
get sum(): number {
734+
return this.a + this.b;
735+
}
736+
}
737+
738+
const [inner] = createStore(new CustomThing(1));
739+
const [store, setStore] = createStore({ inner });
740+
741+
expect(store.inner.sum).toBe(11);
742+
743+
let sum;
744+
createRoot(() => {
745+
createEffect(() => {
746+
sum = store.inner.sum;
747+
});
748+
});
749+
expect(sum).toBe(11);
750+
setStore("inner", "a", 10);
751+
expect(sum).toBe(20);
752+
setStore("inner", "b", 5);
753+
expect(sum).toBe(15);
754+
});
755+
725756
test("not wrapped nested class", () => {
726757
class CustomThing {
727758
a: number;
@@ -748,6 +779,37 @@ describe("Nested Classes", () => {
748779
setStore("inner", "b", 5);
749780
expect(sum).toBe(11);
750781
});
782+
783+
test("not wrapped nested class getter", () => {
784+
class CustomThing {
785+
a: number;
786+
b: number;
787+
constructor(value: number) {
788+
this.a = value;
789+
this.b = 10;
790+
}
791+
get sum(): number {
792+
return this.a + this.b;
793+
}
794+
}
795+
796+
const [store, setStore] = createStore({ inner: new CustomThing(1) });
797+
798+
let sum;
799+
createRoot(() => {
800+
createEffect(() => {
801+
sum = store.inner.sum;
802+
});
803+
});
804+
expect(sum).toBe(11);
805+
expect(store.inner.sum).toBe(11);
806+
setStore("inner", "a", 10);
807+
expect(sum).toBe(11);
808+
expect(store.inner.sum).toBe(20);
809+
setStore("inner", "b", 5);
810+
expect(sum).toBe(11);
811+
expect(store.inner.sum).toBe(15);
812+
});
751813
});
752814

753815
describe("In Operator", () => {

0 commit comments

Comments
 (0)