Skip to content

Commit

Permalink
refactor(array): refactor array method proxy
Browse files Browse the repository at this point in the history
  • Loading branch information
unadlib committed Mar 9, 2025
1 parent 0967533 commit 252a441
Show file tree
Hide file tree
Showing 7 changed files with 28 additions and 67 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@
"json2csv": "^5.0.7",
"lodash": "^4.17.21",
"lodash.clonedeep": "^4.5.0",
"mitata": "^1.0.25",
"mitata": "^1.0.34",
"prettier": "^3.3.3",
"quickchart-js": "^3.1.2",
"redux": "^5.0.1",
Expand Down
59 changes: 18 additions & 41 deletions src/draft.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import {
Finalities,
Patches,
ProxyDraft,
Options,
Operation,
DraftOptions,
} from './interface';
import { dataTypes, PROXY_DRAFT } from './constant';
import { mapHandler, mapHandlerKeys } from './map';
Expand All @@ -29,16 +29,13 @@ import {
finalizeSetValue,
markFinalization,
finalizePatches,
isDraft,
} from './utils';
import { checkReadable } from './unsafe';
import { generatePatches } from './patch';

const draftsCache = new WeakSet<object>();

let arrayHandling = false;

const proxyArrayMethods = ['splice', 'shift', 'unshift', 'reverse'];
const proxyArrayMethods = ['splice', 'shift', 'unshift'];

const proxyHandler: ProxyHandler<ProxyDraft> = {
get(target: ProxyDraft, key: string | number | symbol, receiver: any) {
Expand Down Expand Up @@ -99,24 +96,20 @@ const proxyHandler: ProxyHandler<ProxyDraft> = {
proxyArrayMethods.includes(key as string)
) {
return function (this: any, ...args: any[]) {
const proxyDraft = getProxyDraft(this);
ensureShallowCopy(proxyDraft!);
let returnValue: any;
arrayHandling = true;
try {
returnValue = value.apply(this, args);
if (isDraftable(returnValue)) {
returnValue = createDraft({
original: returnValue,
parentDraft: target,
key: undefined,
finalities: target.finalities,
options: target.options,
});
// TODO: support for custom shallow copy function;
}
return returnValue;
} finally {
arrayHandling = false;
returnValue = value.apply(proxyDraft!.copy, args);
if (isDraftable(returnValue)) {
returnValue = createDraft({
original: returnValue,
parentDraft: target,
key: undefined,
finalities: target.finalities,
options: target.options,
});
}
return returnValue;
};
}
return desc
Expand All @@ -134,18 +127,10 @@ const proxyHandler: ProxyHandler<ProxyDraft> = {
return value;
}
// Ensure that the assigned values are not drafted
if (
!arrayHandling &&
(value === peek(target.original, key) ||
target.options.skipFinalization.has(value))
) {
const shouldSkip = target.options.skipFinalization.has(value);
if (shouldSkip) {
target.options.skipFinalization.delete(value);
}
if (value === peek(target.original, key)) {
ensureShallowCopy(target);
target.copy![key] = createDraft({
original: shouldSkip ? target.copy![key] : target.original[key],
original: target.original[key],
parentDraft: target,
key: target.type === DraftType.Array ? Number(key) : key,
finalities: target.finalities,
Expand All @@ -161,10 +146,6 @@ const proxyHandler: ProxyHandler<ProxyDraft> = {
}
return target.copy![key];
}
if (arrayHandling && !isDraft(value) && isDraftable(value)) {
// !case: handle the case of assigning the original array item via array methods(`splice`, `shift``, `unshift`, `reverse`)
target.options.skipFinalization.add(value);
}
return value;
},
set(target: ProxyDraft, key: string | number | symbol, value: any) {
Expand Down Expand Up @@ -270,7 +251,7 @@ export function createDraft<T extends object>(createDraftOptions: {
parentDraft?: ProxyDraft | null;
key?: string | number | symbol;
finalities: Finalities;
options: DraftOptions;
options: Options<any, any>;
}): T {
const { original, parentDraft, key, finalities, options } =
createDraftOptions;
Expand Down Expand Up @@ -317,11 +298,7 @@ export function createDraft<T extends object>(createDraftOptions: {
}
finalizeSetValue(proxyDraft);
finalizePatches(proxyDraft, generatePatches, patches, inversePatches);
if (
__DEV__ &&
target.options.enableAutoFreeze &&
typeof updatedValue === 'object'
) {
if (__DEV__ && target.options.enableAutoFreeze) {
target.options.updatedValues =
target.options.updatedValues ?? new WeakMap();
target.options.updatedValues.set(updatedValue, proxyDraft.original);
Expand Down
4 changes: 2 additions & 2 deletions src/draftify.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {
DraftOptions,
Finalities,
Options,
Patches,
PatchesOptions,
Result,
Expand All @@ -15,7 +15,7 @@ export function draftify<
F extends boolean = false,
>(
baseState: T,
options: DraftOptions
options: Options<O, F>
): [T, (returnedValue: [T] | []) => Result<T, O, F>] {
const finalities: Finalities = {
draft: [],
Expand Down
13 changes: 1 addition & 12 deletions src/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export interface ProxyDraft<T = any> {
copy: T | null;
proxy: T | null;
finalities: Finalities;
options: DraftOptions;
options: Options<any, any> & { updatedValues?: WeakMap<any, any> };
parent?: ProxyDraft | null;
key?: string | number | symbol;
setMap?: Map<any, ProxyDraft>;
Expand Down Expand Up @@ -122,17 +122,6 @@ export interface Options<O extends PatchesOptions, F extends boolean> {
mark?: Mark<O, F>;
}

export type DraftOptions = Options<any, any> & {
/**
* a collection for circular reference check
*/
updatedValues?: WeakMap<any, any>;
/**
* a collection for array item skip deep check
*/
skipFinalization: WeakSet<any>;
};

export interface ExternalOptions<O extends PatchesOptions, F extends boolean> {
/**
* In strict mode, Forbid accessing non-draftable values and forbid returning a non-draft value.
Expand Down
4 changes: 1 addition & 3 deletions src/makeCreator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
ExternalOptions,
PatchesOptions,
Result,
DraftOptions,
} from './interface';
import { draftify } from './draftify';
import {
Expand Down Expand Up @@ -144,12 +143,11 @@ export const makeCreator: MakeCreator = (arg) => {
const enablePatches = options.enablePatches ?? false;
const strict = options.strict ?? false;
const enableAutoFreeze = options.enableAutoFreeze ?? false;
const _options: DraftOptions = {
const _options: Options<any, any> = {
enableAutoFreeze,
mark,
strict,
enablePatches,
skipFinalization: new WeakSet(),
};
if (
!isDraftable(state, _options) &&
Expand Down
5 changes: 1 addition & 4 deletions src/utils/finalize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,7 @@ export function handleValue(
isDraft(target) ||
!isDraftable(target, options) ||
handledSet.has(target) ||
Object.isFrozen(target) ||
options!.skipFinalization!.has(target)
// It should skip the finalization process
// This can avoid unnecessary deep traversal, as these objects are non-draft and do not contain draft in their deep object.
Object.isFrozen(target)
)
return;
const isSet = target instanceof Set;
Expand Down
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5412,10 +5412,10 @@ minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6:
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==

mitata@^1.0.25:
version "1.0.25"
resolved "https://registry.yarnpkg.com/mitata/-/mitata-1.0.25.tgz#918d0d04d2be0aeae7152cc7d8373b3a727b1b4f"
integrity sha512-0v5qZtVW5vwj9FDvYfraR31BMDcRLkhSFWPTLaxx/Z3/EvScfVtAAWtMI2ArIbBcwh7P86dXh0lQWKiXQPlwYA==
mitata@^1.0.34:
version "1.0.34"
resolved "https://registry.yarnpkg.com/mitata/-/mitata-1.0.34.tgz#131f500d58c0bdc958095ab64f637d6fe1cf101a"
integrity sha512-Mc3zrtNBKIMeHSCQ0XqRLo1vbdIx1wvFV9c8NJAiyho6AjNfMY8bVhbS12bwciUdd1t4rj8099CH3N3NFahaUA==

[email protected]:
version "2.1.2"
Expand Down

0 comments on commit 252a441

Please sign in to comment.