proxy-compare
Advanced tools
Comparing version 2.3.0 to 2.4.0
@@ -5,2 +5,7 @@ # Change Log | ||
## [2.4.0] - 2023-01-04 | ||
### Added | ||
- feat: better support of Object.hasOwn and "in" #47 | ||
- feat: add an option to exclude object getters in affectedToPathList util #48 | ||
## [2.3.0] - 2022-08-13 | ||
@@ -7,0 +12,0 @@ ### Added |
@@ -1,2 +0,2 @@ | ||
const e=Symbol(),t=Symbol(),r=Symbol();let n=(e,t)=>new Proxy(e,t);const o=Object.getPrototypeOf,s=new WeakMap,c=e=>e&&(s.has(e)?s.get(e):o(e)===Object.prototype||o(e)===Array.prototype),l=e=>"object"==typeof e&&null!==e,a=new WeakMap,f=e=>e[r]||e,i=(s,l,p)=>{if(!c(s))return s;const y=f(s),u=(e=>Object.isFrozen(e)||Object.values(Object.getOwnPropertyDescriptors(e)).some(e=>!e.writable))(y);let g=p&&p.get(y);return g&&g[1].f===u||(g=((n,o)=>{const s={f:o};let c=!1;const l=(t,r)=>{if(!c){let o=s.a.get(n);o||(o=new Set,s.a.set(n,o)),r&&o.has(e)||o.add(t)}},a={get:(e,t)=>t===r?n:(l(t),i(e[t],s.a,s.c)),has:(e,r)=>r===t?(c=!0,s.a.delete(n),!0):(l(r),r in e),getOwnPropertyDescriptor:(e,t)=>(l(t,!0),Object.getOwnPropertyDescriptor(e,t)),ownKeys:t=>(l(e),Reflect.ownKeys(t))};return o&&(a.set=a.deleteProperty=()=>!1),[a,s]})(y,u),g[1].p=n(u?(e=>{let t=a.get(e);if(!t){if(Array.isArray(e))t=Array.from(e);else{const r=Object.getOwnPropertyDescriptors(e);Object.values(r).forEach(e=>{e.configurable=!0}),t=Object.create(o(e),r)}a.set(e,t)}return t})(y):y,g[0]),p&&p.set(y,g)),g[1].a=l,g[1].c=p,g[1].p},p=(e,t)=>{const r=Reflect.ownKeys(e),n=Reflect.ownKeys(t);return r.length!==n.length||r.some((e,t)=>e!==n[t])},y=(t,r,n,o)=>{if(Object.is(t,r))return!1;if(!l(t)||!l(r))return!0;const s=n.get(f(t));if(!s)return!0;if(o){const e=o.get(t);if(e&&e.n===r)return e.g;o.set(t,{n:r,g:!1})}let c=null;for(const l of s){const s=l===e?p(t,r):y(t[l],r[l],n,o);if(!0!==s&&!1!==s||(c=s),c)break}return null===c&&(c=!0),o&&o.set(t,{n:r,g:c}),c},u=e=>!!c(e)&&t in e,g=e=>c(e)&&e[r]||null,b=(e,t=!0)=>{s.set(e,t)},O=(e,t)=>{const r=[],n=new WeakSet,o=(e,s)=>{if(n.has(e))return;l(e)&&n.add(e);const c=l(e)&&t.get(f(e));c?c.forEach(t=>{o(e[t],s?[...s,t]:[t])}):s&&r.push(s)};return o(e),r},w=e=>{n=e};export{O as affectedToPathList,i as createProxy,g as getUntracked,y as isChanged,b as markToTrack,w as replaceNewProxy,u as trackMemo}; | ||
const e=Symbol(),t=Symbol(),r="a",n="w";let o=(e,t)=>new Proxy(e,t);const s=Object.getPrototypeOf,c=new WeakMap,l=e=>e&&(c.has(e)?c.get(e):s(e)===Object.prototype||s(e)===Array.prototype),f=e=>"object"==typeof e&&null!==e,i=new WeakMap,a=e=>e[t]||e,u=(c,f,p)=>{if(!l(c))return c;const y=a(c),g=(e=>Object.isFrozen(e)||Object.values(Object.getOwnPropertyDescriptors(e)).some(e=>!e.writable))(y);let h=p&&p.get(y);return h&&h[1].f===g||(h=((o,s)=>{const c={f:s};let l=!1;const f=(e,t)=>{if(!l){let s=c[r].get(o);if(s||(s={},c[r].set(o,s)),e===n)s[n]=!0;else{let r=s[e];r||(r=new Set,s[e]=r),r.add(t)}}},i={get:(e,n)=>n===t?o:(f("k",n),u(Reflect.get(e,n),c[r],c.c)),has:(t,n)=>n===e?(l=!0,c[r].delete(o),!0):(f("h",n),Reflect.has(t,n)),getOwnPropertyDescriptor:(e,t)=>(f("o",t),Reflect.getOwnPropertyDescriptor(e,t)),ownKeys:e=>(f(n),Reflect.ownKeys(e))};return s&&(i.set=i.deleteProperty=()=>!1),[i,c]})(y,g),h[1].p=o(g?(e=>{let t=i.get(e);if(!t){if(Array.isArray(e))t=Array.from(e);else{const r=Object.getOwnPropertyDescriptors(e);Object.values(r).forEach(e=>{e.configurable=!0}),t=Object.create(s(e),r)}i.set(e,t)}return t})(y):y,h[0]),p&&p.set(y,h)),h[1][r]=f,h[1].c=p,h[1].p},p=(e,t,r,o)=>{if(Object.is(e,t))return!1;if(!f(e)||!f(t))return!0;const s=r.get(a(e));if(!s)return!0;if(o){const r=o.get(e);if(r&&r.n===t)return r.g;o.set(e,{n:t,g:!1})}let c=null;try{for(const r of s.h||[])if(c=Reflect.has(e,r)!==Reflect.has(t,r),c)return c;if(!0===s[n]){if(c=((e,t)=>{const r=Reflect.ownKeys(e),n=Reflect.ownKeys(t);return r.length!==n.length||r.some((e,t)=>e!==n[t])})(e,t),c)return c}else for(const r of s.o||[])if(c=!!Reflect.getOwnPropertyDescriptor(e,r)!=!!Reflect.getOwnPropertyDescriptor(t,r),c)return c;for(const n of s.k||[])if(c=p(e[n],t[n],r,o),c)return c;return null===c&&(c=!0),c}finally{o&&o.set(e,{n:t,g:c})}},y=t=>!!l(t)&&e in t,g=e=>l(e)&&e[t]||null,h=(e,t=!0)=>{c.set(e,t)},w=(e,t,r)=>{const o=[],s=new WeakSet,c=(e,l)=>{if(s.has(e))return;f(e)&&s.add(e);const i=f(e)&&t.get(a(e));if(i){var u,p;if(null==(u=i.h)||u.forEach(e=>{const t=`:has(${String(e)})`;o.push(l?[...l,t]:[t])}),!0===i[n]){const e=":ownKeys";o.push(l?[...l,e]:[e])}else{var y;null==(y=i.o)||y.forEach(e=>{const t=`:hasOwn(${String(e)})`;o.push(l?[...l,t]:[t])})}null==(p=i.k)||p.forEach(t=>{r&&!("value"in(Object.getOwnPropertyDescriptor(e,t)||{}))||c(e[t],l?[...l,t]:[t])})}else l&&o.push(l)};return c(e),o},O=e=>{o=e};export{w as affectedToPathList,u as createProxy,g as getUntracked,p as isChanged,h as markToTrack,O as replaceNewProxy,y as trackMemo}; | ||
//# sourceMappingURL=index.modern.mjs.map |
@@ -1,2 +0,2 @@ | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e||self).proxyCompare={})}(this,function(e){function t(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=new Array(t);r<t;r++)n[r]=e[r];return n}var r=Symbol(),n=Symbol(),o=Symbol(),i=function(e,t){return new Proxy(e,t)},a=Object.getPrototypeOf,u=new WeakMap,c=function(e){return e&&(u.has(e)?u.get(e):a(e)===Object.prototype||a(e)===Array.prototype)},f=function(e){return"object"==typeof e&&null!==e},l=new WeakMap,s=function(e){return e[o]||e},y=function(e,t,u){if(!c(e))return e;var f=s(e),p=function(e){return Object.isFrozen(e)||Object.values(Object.getOwnPropertyDescriptors(e)).some(function(e){return!e.writable})}(f),b=u&&u.get(f);return b&&b[1].f===p||((b=function(e,t){var i,a=((i={}).f=t,i),u=!1,c=function(t,n){if(!u){var o=a.a.get(e);o||(o=new Set,a.a.set(e,o)),n&&o.has(r)||o.add(t)}},f={get:function(t,r){return r===o?e:(c(r),y(t[r],a.a,a.c))},has:function(t,r){return r===n?(u=!0,a.a.delete(e),!0):(c(r),r in t)},getOwnPropertyDescriptor:function(e,t){return c(t,!0),Object.getOwnPropertyDescriptor(e,t)},ownKeys:function(e){return c(r),Reflect.ownKeys(e)}};return t&&(f.set=f.deleteProperty=function(){return!1}),[f,a]}(f,p))[1].p=i(p?function(e){var t=l.get(e);if(!t){if(Array.isArray(e))t=Array.from(e);else{var r=Object.getOwnPropertyDescriptors(e);Object.values(r).forEach(function(e){e.configurable=!0}),t=Object.create(a(e),r)}l.set(e,t)}return t}(f):f,b[0]),u&&u.set(f,b)),b[1].a=t,b[1].c=u,b[1].p},p=function(e,t){var r=Reflect.ownKeys(e),n=Reflect.ownKeys(t);return r.length!==n.length||r.some(function(e,t){return e!==n[t]})};e.affectedToPathList=function(e,t){var r=[],n=new WeakSet;return function e(o,i){if(!n.has(o)){f(o)&&n.add(o);var a=f(o)&&t.get(s(o));a?a.forEach(function(t){e(o[t],i?[].concat(i,[t]):[t])}):i&&r.push(i)}}(e),r},e.createProxy=y,e.getUntracked=function(e){return c(e)&&e[o]||null},e.isChanged=function e(n,o,i,a){if(Object.is(n,o))return!1;if(!f(n)||!f(o))return!0;var u=i.get(s(n));if(!u)return!0;if(a){var c,l=a.get(n);if(l&&l.n===o)return l.g;a.set(n,((c={}).n=o,c.g=!1,c))}for(var y,b,d=null,g=function(e,r){var n="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(n)return(n=n.call(e)).next.bind(n);if(Array.isArray(e)||(n=function(e,r){if(e){if("string"==typeof e)return t(e,r);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?t(e,r):void 0}}(e))){n&&(e=n);var o=0;return function(){return o>=e.length?{done:!0}:{done:!1,value:e[o++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}(u);!(y=g()).done;){var v=y.value,m=v===r?p(n,o):e(n[v],o[v],i,a);if(!0!==m&&!1!==m||(d=m),d)break}return null===d&&(d=!0),a&&a.set(n,((b={}).n=o,b.g=d,b)),d},e.markToTrack=function(e,t){void 0===t&&(t=!0),u.set(e,t)},e.replaceNewProxy=function(e){i=e},e.trackMemo=function(e){return!!c(e)&&n in e}}); | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e||self).proxyCompare={})}(this,function(e){function t(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=new Array(t);r<t;r++)n[r]=e[r];return n}function r(e,r){var n="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(n)return(n=n.call(e)).next.bind(n);if(Array.isArray(e)||(n=function(e,r){if(e){if("string"==typeof e)return t(e,r);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?t(e,r):void 0}}(e))||r&&e&&"number"==typeof e.length){n&&(e=n);var o=0;return function(){return o>=e.length?{done:!0}:{done:!1,value:e[o++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var n=Symbol(),o=Symbol(),a="a",i="w",f=function(e,t){return new Proxy(e,t)},u=Object.getPrototypeOf,c=new WeakMap,l=function(e){return e&&(c.has(e)?c.get(e):u(e)===Object.prototype||u(e)===Array.prototype)},s=function(e){return"object"==typeof e&&null!==e},p=new WeakMap,y=function(e){return e[o]||e},v=function(e,t,r){if(!l(e))return e;var c=y(e),s=function(e){return Object.isFrozen(e)||Object.values(Object.getOwnPropertyDescriptors(e)).some(function(e){return!e.writable})}(c),g=r&&r.get(c);return g&&g[1].f===s||((g=function(e,t){var r,f=((r={}).f=t,r),u=!1,c=function(t,r){if(!u){var n=f[a].get(e);if(n||f[a].set(e,n={}),t===i)n[i]=!0;else{var o=n[t];o||(o=new Set,n[t]=o),o.add(r)}}},l={get:function(t,r){return r===o?e:(c("k",r),v(Reflect.get(t,r),f[a],f.c))},has:function(t,r){return r===n?(u=!0,f[a].delete(e),!0):(c("h",r),Reflect.has(t,r))},getOwnPropertyDescriptor:function(e,t){return c("o",t),Reflect.getOwnPropertyDescriptor(e,t)},ownKeys:function(e){return c(i),Reflect.ownKeys(e)}};return t&&(l.set=l.deleteProperty=function(){return!1}),[l,f]}(c,s))[1].p=f(s?function(e){var t=p.get(e);if(!t){if(Array.isArray(e))t=Array.from(e);else{var r=Object.getOwnPropertyDescriptors(e);Object.values(r).forEach(function(e){e.configurable=!0}),t=Object.create(u(e),r)}p.set(e,t)}return t}(c):c,g[0]),r&&r.set(c,g)),g[1][a]=t,g[1].c=r,g[1].p};e.affectedToPathList=function(e,t,r){var n=[],o=new WeakSet;return function e(a,f){if(!o.has(a)){s(a)&&o.add(a);var u=s(a)&&t.get(y(a));if(u){var c,l;if(null==(c=u.h)||c.forEach(function(e){var t=":has("+String(e)+")";n.push(f?[].concat(f,[t]):[t])}),!0===u[i]){var p=":ownKeys";n.push(f?[].concat(f,[p]):[p])}else{var v;null==(v=u.o)||v.forEach(function(e){var t=":hasOwn("+String(e)+")";n.push(f?[].concat(f,[t]):[t])})}null==(l=u.k)||l.forEach(function(t){r&&!("value"in(Object.getOwnPropertyDescriptor(a,t)||{}))||e(a[t],f?[].concat(f,[t]):[t])})}else f&&n.push(f)}}(e),n},e.createProxy=v,e.getUntracked=function(e){return l(e)&&e[o]||null},e.isChanged=function e(t,n,o,a){if(Object.is(t,n))return!1;if(!s(t)||!s(n))return!0;var f=o.get(y(t));if(!f)return!0;if(a){var u,c=a.get(t);if(c&&c.n===n)return c.g;a.set(t,((u={}).n=n,u.g=!1,u))}var l=null;try{for(var p,v=r(f.h||[]);!(p=v()).done;){var g=p.value;if(l=Reflect.has(t,g)!==Reflect.has(n,g))return l}if(!0===f[i]){if(l=function(e,t){var r=Reflect.ownKeys(e),n=Reflect.ownKeys(t);return r.length!==n.length||r.some(function(e,t){return e!==n[t]})}(t,n),l)return l}else for(var h,d=r(f.o||[]);!(h=d()).done;){var b=h.value;if(l=!!Reflect.getOwnPropertyDescriptor(t,b)!=!!Reflect.getOwnPropertyDescriptor(n,b))return l}for(var w,m=r(f.k||[]);!(w=m()).done;){var O=w.value;if(l=e(t[O],n[O],o,a))return l}return null===l&&(l=!0),l}finally{var j;a&&a.set(t,((j={}).n=n,j.g=l,j))}},e.markToTrack=function(e,t){void 0===t&&(t=!0),c.set(e,t)},e.replaceNewProxy=function(e){f=e},e.trackMemo=function(e){return!!l(e)&&n in e}}); | ||
//# sourceMappingURL=index.umd.js.map |
@@ -101,3 +101,3 @@ declare let newProxy: <T extends object>(target: T, handler: ProxyHandler<T>) => T; | ||
* @param mark - Boolean indicating whether you want to track this object or not. | ||
* @returns No return. | ||
* @returns - No return. | ||
* | ||
@@ -121,4 +121,16 @@ * @example | ||
export declare const markToTrack: (obj: object, mark?: boolean) => void; | ||
export declare const affectedToPathList: (obj: unknown, affected: WeakMap<object, unknown>) => (string | symbol)[][]; | ||
/** | ||
* Convert `affected` to path list | ||
* | ||
* `affected` is a weak map which is not printable. | ||
* This function is can convert it to printable path list. | ||
* It's for debugging purpose. | ||
* | ||
* @param obj - An object that is used with `createProxy`. | ||
* @param affected - A weak map that is used with `createProxy`. | ||
* @param onlyWithValues - An optional boolean to exclude object getters. | ||
* @returns - An array of paths. | ||
*/ | ||
export declare const affectedToPathList: (obj: unknown, affected: WeakMap<object, unknown>, onlyWithValues?: boolean) => (string | symbol)[][]; | ||
/** | ||
* replace newProxy function. | ||
@@ -125,0 +137,0 @@ * |
{ | ||
"name": "proxy-compare", | ||
"description": "Compare two objects using accessed properties with Proxy", | ||
"version": "2.3.0", | ||
"version": "2.4.0", | ||
"author": "Daishi Kato", | ||
@@ -36,3 +36,3 @@ "repository": { | ||
"tsc-test": "tsc --project . --noEmit", | ||
"apidoc": "documentation readme --section API --markdown-toc false --parse-extension ts src/*.ts" | ||
"apidoc": "documentation readme src --section API --markdown-toc false --parse-extension ts" | ||
}, | ||
@@ -52,15 +52,15 @@ "jest": { | ||
"devDependencies": { | ||
"@types/jest": "^28.1.6", | ||
"@typescript-eslint/eslint-plugin": "^5.33.0", | ||
"@typescript-eslint/parser": "^5.33.0", | ||
"documentation": "^13.2.5", | ||
"eslint": "^8.21.0", | ||
"@types/jest": "^29.2.5", | ||
"@typescript-eslint/eslint-plugin": "^5.48.0", | ||
"@typescript-eslint/parser": "^5.48.0", | ||
"documentation": "^14.0.1", | ||
"eslint": "^8.31.0", | ||
"eslint-config-airbnb-base": "^15.0.0", | ||
"eslint-plugin-import": "^2.26.0", | ||
"jest": "^28.1.3", | ||
"jest": "^29.3.1", | ||
"microbundle": "^0.15.1", | ||
"npm-run-all": "^4.1.5", | ||
"ts-jest": "^28.0.7", | ||
"typescript": "^4.7.4" | ||
"ts-jest": "^29.0.3", | ||
"typescript": "^4.9.4" | ||
} | ||
} |
@@ -188,2 +188,18 @@ # proxy-compare | ||
### affectedToPathList | ||
Convert `affected` to path list | ||
`affected` is a weak map which is not printable. | ||
This function is can convert it to printable path list. | ||
It's for debugging purpose. | ||
#### Parameters | ||
* `obj` **any** An object that is used with `createProxy`. | ||
* `affected` **[WeakMap](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WeakMap)<[object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object), any>** A weak map that is used with `createProxy`. | ||
* `onlyWithValues` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** An optional boolean to exclude object getters. | ||
Returns **any** An array of paths. | ||
### replaceNewProxy | ||
@@ -199,3 +215,3 @@ | ||
* `fn` **any** | ||
* `fn` **any**  | ||
@@ -202,0 +218,0 @@ ## Projects using this library |
138
src/index.ts
// symbols | ||
const OWN_KEYS_SYMBOL = Symbol(); | ||
const TRACK_MEMO_SYMBOL = Symbol(); | ||
@@ -13,2 +12,6 @@ const GET_ORIGINAL_SYMBOL = Symbol(); | ||
const CHANGED_PROPERTY = 'g'; | ||
const HAS_KEY_PROPERTY = 'h'; | ||
const ALL_OWN_KEYS_PROPERTY = 'w'; | ||
const HAS_OWN_KEY_PROPERTY = 'o'; | ||
const KEYS_PROPERTY = 'k'; | ||
@@ -70,3 +73,12 @@ // function to create a new bare proxy | ||
type Affected = WeakMap<object, Set<string | symbol>>; | ||
type HasKeySet = Set<string | symbol> | ||
type HasOwnKeySet = Set<string | symbol> | ||
type KeysSet = Set<string | symbol> | ||
type Used = { | ||
[HAS_KEY_PROPERTY]?: HasKeySet; | ||
[ALL_OWN_KEYS_PROPERTY]?: true; | ||
[HAS_OWN_KEY_PROPERTY]?: HasOwnKeySet; | ||
[KEYS_PROPERTY]?: KeysSet; | ||
}; | ||
type Affected = WeakMap<object, Used>; | ||
type ProxyHandlerState<T extends object> = { | ||
@@ -88,11 +100,25 @@ readonly [FROZEN_PROPERTY]: boolean; | ||
let trackObject = false; // for trackMemo | ||
const recordUsage = (key: string | symbol, skipWithOwnKeys?: boolean) => { | ||
const recordUsage = ( | ||
type: | ||
| typeof HAS_KEY_PROPERTY | ||
| typeof ALL_OWN_KEYS_PROPERTY | ||
| typeof HAS_OWN_KEY_PROPERTY | ||
| typeof KEYS_PROPERTY, | ||
key?: string | symbol, | ||
) => { | ||
if (!trackObject) { | ||
let used = (state[AFFECTED_PROPERTY] as Affected).get(origObj); | ||
if (!used) { | ||
used = new Set(); | ||
used = {}; | ||
(state[AFFECTED_PROPERTY] as Affected).set(origObj, used); | ||
} | ||
if (!skipWithOwnKeys || !used.has(OWN_KEYS_SYMBOL)) { | ||
used.add(key); | ||
if (type === ALL_OWN_KEYS_PROPERTY) { | ||
used[ALL_OWN_KEYS_PROPERTY] = true; | ||
} else { | ||
let set = used[type]; | ||
if (!set) { | ||
set = new Set(); | ||
used[type] = set; | ||
} | ||
set.add(key as string | symbol); | ||
} | ||
@@ -110,5 +136,5 @@ } | ||
} | ||
recordUsage(key); | ||
recordUsage(KEYS_PROPERTY, key); | ||
return createProxy( | ||
(target as any)[key], | ||
Reflect.get(target, key), | ||
(state[AFFECTED_PROPERTY] as Affected), | ||
@@ -123,17 +149,11 @@ state[PROXY_CACHE_PROPERTY], | ||
} | ||
// LIMITATION: We simply record the same as `get`. | ||
// This means { a: {} } and { a: {} } is detected as changed, | ||
// if `'a' in obj` is handled. | ||
recordUsage(key); | ||
return key in target; | ||
recordUsage(HAS_KEY_PROPERTY, key); | ||
return Reflect.has(target, key); | ||
}, | ||
getOwnPropertyDescriptor(target, key) { | ||
// LIMITATION: We simply record the same as `get`. | ||
// This means { a: {} } and { a: {} } is detected as changed, | ||
// if `obj.getOwnPropertyDescriptor('a'))` is handled. | ||
recordUsage(key, true); | ||
return Object.getOwnPropertyDescriptor(target, key); | ||
recordUsage(HAS_OWN_KEY_PROPERTY, key); | ||
return Reflect.getOwnPropertyDescriptor(target, key); | ||
}, | ||
ownKeys(target) { | ||
recordUsage(OWN_KEYS_SYMBOL); | ||
recordUsage(ALL_OWN_KEYS_PROPERTY); | ||
return Reflect.ownKeys(target); | ||
@@ -212,3 +232,3 @@ }, | ||
const isOwnKeysChanged = (prevObj: object, nextObj: object) => { | ||
const isAllOwnKeysChanged = (prevObj: object, nextObj: object) => { | ||
const prevKeys = Reflect.ownKeys(prevObj); | ||
@@ -284,6 +304,20 @@ const nextKeys = Reflect.ownKeys(nextObj); | ||
let changed: boolean | null = null; | ||
// eslint-disable-next-line no-restricted-syntax | ||
for (const key of used) { | ||
const c = key === OWN_KEYS_SYMBOL ? isOwnKeysChanged(prevObj, nextObj) | ||
: isChanged( | ||
try { | ||
for (const key of used[HAS_KEY_PROPERTY] || []) { | ||
changed = Reflect.has(prevObj, key) !== Reflect.has(nextObj, key); | ||
if (changed) return changed; | ||
} | ||
if (used[ALL_OWN_KEYS_PROPERTY] === true) { | ||
changed = isAllOwnKeysChanged(prevObj, nextObj); | ||
if (changed) return changed; | ||
} else { | ||
for (const key of used[HAS_OWN_KEY_PROPERTY] || []) { | ||
const hasPrev = !!Reflect.getOwnPropertyDescriptor(prevObj, key); | ||
const hasNext = !!Reflect.getOwnPropertyDescriptor(nextObj, key); | ||
changed = hasPrev !== hasNext; | ||
if (changed) return changed; | ||
} | ||
} | ||
for (const key of used[KEYS_PROPERTY] || []) { | ||
changed = isChanged( | ||
(prevObj as any)[key], | ||
@@ -294,13 +328,14 @@ (nextObj as any)[key], | ||
); | ||
if (c === true || c === false) changed = c; | ||
if (changed) break; | ||
if (changed) return changed; | ||
} | ||
if (changed === null) changed = true; | ||
return changed; | ||
} finally { | ||
if (cache) { | ||
cache.set(prevObj, { | ||
[NEXT_OBJECT_PROPERTY]: nextObj, | ||
[CHANGED_PROPERTY]: changed, | ||
}); | ||
} | ||
} | ||
if (changed === null) changed = true; | ||
if (cache) { | ||
cache.set(prevObj, { | ||
[NEXT_OBJECT_PROPERTY]: nextObj, | ||
[CHANGED_PROPERTY]: changed, | ||
}); | ||
} | ||
return changed; | ||
}; | ||
@@ -353,3 +388,3 @@ | ||
* @param mark - Boolean indicating whether you want to track this object or not. | ||
* @returns No return. | ||
* @returns - No return. | ||
* | ||
@@ -376,6 +411,18 @@ * @example | ||
// convert affected to path list | ||
/** | ||
* Convert `affected` to path list | ||
* | ||
* `affected` is a weak map which is not printable. | ||
* This function is can convert it to printable path list. | ||
* It's for debugging purpose. | ||
* | ||
* @param obj - An object that is used with `createProxy`. | ||
* @param affected - A weak map that is used with `createProxy`. | ||
* @param onlyWithValues - An optional boolean to exclude object getters. | ||
* @returns - An array of paths. | ||
*/ | ||
export const affectedToPathList = ( | ||
obj: unknown, | ||
affected: WeakMap<object, unknown>, | ||
onlyWithValues?: boolean, | ||
) => { | ||
@@ -394,5 +441,20 @@ const list: (string | symbol)[][] = []; | ||
if (used) { | ||
used.forEach((key) => { | ||
walk((x as any)[key], path ? [...path, key] : [key]); | ||
used[HAS_KEY_PROPERTY]?.forEach((key) => { | ||
const segment = `:has(${String(key)})`; | ||
list.push(path ? [...path, segment] : [segment]); | ||
}); | ||
if (used[ALL_OWN_KEYS_PROPERTY] === true) { | ||
const segment = ':ownKeys'; | ||
list.push(path ? [...path, segment] : [segment]); | ||
} else { | ||
used[HAS_OWN_KEY_PROPERTY]?.forEach((key) => { | ||
const segment = `:hasOwn(${String(key)})`; | ||
list.push(path ? [...path, segment] : [segment]); | ||
}); | ||
} | ||
used[KEYS_PROPERTY]?.forEach((key) => { | ||
if (!onlyWithValues || 'value' in (Object.getOwnPropertyDescriptor(x, key) || {})) { | ||
walk((x as any)[key], path ? [...path, key] : [key]); | ||
} | ||
}); | ||
} else if (path) { | ||
@@ -399,0 +461,0 @@ list.push(path); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
103601
624
229