Skip to content

Commit

Permalink
fix class/prototype getters not getting wrapped + tests
Browse files Browse the repository at this point in the history
  • Loading branch information
timbasel committed Oct 20, 2024
1 parent bb6ce8b commit 417eac9
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 2 deletions.
20 changes: 18 additions & 2 deletions packages/solid/store/src/store.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getListener, batch, DEV, $PROXY, $TRACK, createSignal } from "solid-js";
import { $PROXY, $TRACK, batch, createSignal, DEV, getListener } from "solid-js";

export const $RAW = Symbol("store-raw"),
$NODE = Symbol("store-node"),
Expand Down Expand Up @@ -49,11 +49,27 @@ function wrap<T extends StoreNode>(value: T): T {
Object.defineProperty(value, $PROXY, { value: (p = new Proxy(value, proxyTraps)) });
if (!Array.isArray(value)) {
const keys = Object.keys(value),
desc = Object.getOwnPropertyDescriptors(value);
desc = Object.getOwnPropertyDescriptors(value),
proto = Object.getPrototypeOf(value);

const isClass =
proto !== null &&
value !== null &&
typeof value === "object" &&
!Array.isArray(value) &&
proto !== Object.prototype;
if (isClass) {
const descriptors = Object.getOwnPropertyDescriptors(proto);
keys.push(...Object.keys(descriptors));
Object.assign(desc, descriptors);
}

for (let i = 0, l = keys.length; i < l; i++) {
const prop = keys[i];
if (isClass && prop === "constructor") continue;
if (desc[prop].get) {
Object.defineProperty(value, prop, {
configurable: true,
enumerable: desc[prop].enumerable,
get: desc[prop].get!.bind(p)
});
Expand Down
62 changes: 62 additions & 0 deletions packages/solid/store/test/store.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,37 @@ describe("Nested Classes", () => {
expect(sum).toBe(15);
});

test("wrapped nested class getter", () => {
class CustomThing {
a: number;
b: number;
constructor(value: number) {
this.a = value;
this.b = 10;
}
get sum(): number {
return this.a + this.b;
}
}

const [inner] = createStore(new CustomThing(1));
const [store, setStore] = createStore({ inner });

expect(store.inner.sum).toBe(11);

let sum;
createRoot(() => {
createEffect(() => {
sum = store.inner.sum;
});
});
expect(sum).toBe(11);
setStore("inner", "a", 10);
expect(sum).toBe(20);
setStore("inner", "b", 5);
expect(sum).toBe(15);
});

test("not wrapped nested class", () => {
class CustomThing {
a: number;
Expand All @@ -748,6 +779,37 @@ describe("Nested Classes", () => {
setStore("inner", "b", 5);
expect(sum).toBe(11);
});

test("not wrapped nested class getter", () => {
class CustomThing {
a: number;
b: number;
constructor(value: number) {
this.a = value;
this.b = 10;
}
get sum(): number {
return this.a + this.b;
}
}

const [store, setStore] = createStore({ inner: new CustomThing(1) });

let sum;
createRoot(() => {
createEffect(() => {
sum = store.inner.sum;
});
});
expect(sum).toBe(11);
expect(store.inner.sum).toBe(11);
setStore("inner", "a", 10);
expect(sum).toBe(11);
expect(store.inner.sum).toBe(20);
setStore("inner", "b", 5);
expect(sum).toBe(11);
expect(store.inner.sum).toBe(15);
});
});

describe("In Operator", () => {
Expand Down

0 comments on commit 417eac9

Please sign in to comment.