Skip to content

Commit

Permalink
adds reconcileWithKeys
Browse files Browse the repository at this point in the history
  • Loading branch information
titoBouzout committed Sep 12, 2024
1 parent e4b2c66 commit c3836a8
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 8 deletions.
42 changes: 35 additions & 7 deletions packages/solid/store/src/modifiers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,20 @@ export type ReconcileOptions = {
key?: string | null;
merge?: boolean;
};
export type ReconcileWithKeysOptions = {
keys?: object | null;
merge?: boolean;
};
const emptyKeys = /* #__PURE__*/ Object.create(null);

function applyState(
target: any,
parent: any,
property: PropertyKey,
merge: boolean | undefined,
key: string | null
key: string | null,
keys: object | null,
useKeys: boolean | null
) {
const previous = parent[property];
if (target === previous) return;
Expand Down Expand Up @@ -43,7 +50,7 @@ function applyState(
(key && previous[start] && target[start] && previous[start][key] === target[start][key]));
start++
) {
applyState(target[start], previous, start, merge, key);
applyState(target[start], previous, start, merge, key, keys, useKeys);
}

const temp = new Array(target.length),
Expand All @@ -65,7 +72,7 @@ function applyState(
for (j = start; j <= newEnd; j++) setProperty(previous, j, target[j]);
for (; j < target.length; j++) {
setProperty(previous, j, temp[j]);
applyState(target[j], previous, j, merge, key);
applyState(target[j], previous, j, merge, key, keys, useKeys);
}
if (previous.length > target.length) setProperty(previous, "length", target.length);
return;
Expand Down Expand Up @@ -95,12 +102,12 @@ function applyState(
for (j = start; j < target.length; j++) {
if (j in temp) {
setProperty(previous, j, temp[j]);
applyState(target[j], previous, j, merge, key);
applyState(target[j], previous, j, merge, key, keys, useKeys);
} else setProperty(previous, j, target[j]);
}
} else {
for (let i = 0, len = target.length; i < len; i++) {
applyState(target[i], previous, i, merge, key);
applyState(target[i], previous, i, merge, key, keys, useKeys);
}
}
if (previous.length > target.length) setProperty(previous, "length", target.length);
Expand All @@ -109,7 +116,15 @@ function applyState(

const targetKeys = Object.keys(target);
for (let i = 0, len = targetKeys.length; i < len; i++) {
applyState(target[targetKeys[i]], previous, targetKeys[i], merge, key);
applyState(
target[targetKeys[i]],
previous,
targetKeys[i],
merge,
!useKeys ? key : isArray ? (keys || emptyKeys)._key : keys[targetKeys[i]]?._key,
!useKeys ? null : isArray ? keys : keys[targetKeys[i]] || emptyKeys,
useKeys
);
}
const previousKeys = Object.keys(previous);
for (let i = 0, len = previousKeys.length; i < len; i++) {
Expand All @@ -126,7 +141,20 @@ export function reconcile<T extends U, U>(
v = unwrap(value);
return state => {
if (!isWrappable(state) || !isWrappable(v)) return v;
const res = applyState(v, { [$ROOT]: state }, $ROOT, merge, key);
const res = applyState(v, { [$ROOT]: state }, $ROOT, merge, key, null, null);
return res === undefined ? (state as T) : res;
};
}

export function reconcileWithKeys<T extends U, U>(
value: T,
options: ReconcileWithKeysOptions = {}
): (state: U) => T {
const { merge, keys = emptyKeys } = options,
v = unwrap(value);
return state => {
if (!isWrappable(state) || !isWrappable(v)) return v;
const res = applyState(v, { [$ROOT]: state }, $ROOT, merge, keys._key, keys, true);
return res === undefined ? (state as T) : res;
};
}
Expand Down
34 changes: 33 additions & 1 deletion packages/solid/store/test/modifiers.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import { createRoot, createSignal, createEffect } from "../../src";
import { createStore, createMutable, reconcile, produce, unwrap, modifyMutable } from "../src";
import {
createStore,
createMutable,
reconcile,
produce,
unwrap,
modifyMutable,
reconcileWithKeys
} from "../src";

describe("setState with reconcile", () => {
test("Reconcile a simple object", () => {
Expand Down Expand Up @@ -357,6 +365,30 @@ describe("modifyMutable with reconcile", () => {
});
});

describe("reconcileWithKeys", () => {
test("simple test", () => {
createRoot(() => {
const [target, setStore] = createStore({
c: [
{ idx: 1, name: "1" },
{ idx: 0, name: "0" }
]
});

const ref1 = target.c[1];

const source = {
c: [{ idx: 0, name: "0 modified" }]
};

setStore("c", reconcile(source.c));

expect(target.c[0]).toBe(ref1);

expect(target).toEqual({ c: [{ idx: 0, name: "0 modified" }] });
});
});
});
// type tests

// reconcile
Expand Down

0 comments on commit c3836a8

Please sign in to comment.