diff --git a/package.json b/package.json index 7b9a010..d7453c8 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/draft.ts b/src/draft.ts index a0c1b87..9dfe06f 100644 --- a/src/draft.ts +++ b/src/draft.ts @@ -3,8 +3,8 @@ import { Finalities, Patches, ProxyDraft, + Options, Operation, - DraftOptions, } from './interface'; import { dataTypes, PROXY_DRAFT } from './constant'; import { mapHandler, mapHandlerKeys } from './map'; @@ -29,16 +29,13 @@ import { finalizeSetValue, markFinalization, finalizePatches, - isDraft, } from './utils'; import { checkReadable } from './unsafe'; import { generatePatches } from './patch'; const draftsCache = new WeakSet(); -let arrayHandling = false; - -const proxyArrayMethods = ['splice', 'shift', 'unshift', 'reverse']; +const proxyArrayMethods = ['splice', 'shift', 'unshift']; const proxyHandler: ProxyHandler = { get(target: ProxyDraft, key: string | number | symbol, receiver: any) { @@ -99,24 +96,20 @@ const proxyHandler: ProxyHandler = { 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 @@ -134,18 +127,10 @@ const proxyHandler: ProxyHandler = { 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, @@ -161,10 +146,6 @@ const proxyHandler: ProxyHandler = { } 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) { @@ -270,7 +251,7 @@ export function createDraft(createDraftOptions: { parentDraft?: ProxyDraft | null; key?: string | number | symbol; finalities: Finalities; - options: DraftOptions; + options: Options; }): T { const { original, parentDraft, key, finalities, options } = createDraftOptions; @@ -317,11 +298,7 @@ export function createDraft(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); diff --git a/src/draftify.ts b/src/draftify.ts index 8eacfb8..7ad9f2c 100644 --- a/src/draftify.ts +++ b/src/draftify.ts @@ -1,6 +1,6 @@ import { - DraftOptions, Finalities, + Options, Patches, PatchesOptions, Result, @@ -15,7 +15,7 @@ export function draftify< F extends boolean = false, >( baseState: T, - options: DraftOptions + options: Options ): [T, (returnedValue: [T] | []) => Result] { const finalities: Finalities = { draft: [], diff --git a/src/interface.ts b/src/interface.ts index c81b177..0063a8e 100644 --- a/src/interface.ts +++ b/src/interface.ts @@ -42,7 +42,7 @@ export interface ProxyDraft { copy: T | null; proxy: T | null; finalities: Finalities; - options: DraftOptions; + options: Options & { updatedValues?: WeakMap }; parent?: ProxyDraft | null; key?: string | number | symbol; setMap?: Map; @@ -122,17 +122,6 @@ export interface Options { mark?: Mark; } -export type DraftOptions = Options & { - /** - * a collection for circular reference check - */ - updatedValues?: WeakMap; - /** - * a collection for array item skip deep check - */ - skipFinalization: WeakSet; -}; - export interface ExternalOptions { /** * In strict mode, Forbid accessing non-draftable values and forbid returning a non-draft value. diff --git a/src/makeCreator.ts b/src/makeCreator.ts index aae1906..d9e535c 100644 --- a/src/makeCreator.ts +++ b/src/makeCreator.ts @@ -6,7 +6,6 @@ import { ExternalOptions, PatchesOptions, Result, - DraftOptions, } from './interface'; import { draftify } from './draftify'; import { @@ -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 = { enableAutoFreeze, mark, strict, enablePatches, - skipFinalization: new WeakSet(), }; if ( !isDraftable(state, _options) && diff --git a/src/utils/finalize.ts b/src/utils/finalize.ts index ed4bbbf..f545c62 100644 --- a/src/utils/finalize.ts +++ b/src/utils/finalize.ts @@ -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; diff --git a/yarn.lock b/yarn.lock index 722f926..9b4c67d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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== ms@2.1.2: version "2.1.2"