From cf1f4c22b8e050338bb653d826dd3f3db90af20d Mon Sep 17 00:00:00 2001 From: jfet97 Date: Mon, 7 Jan 2019 22:13:30 +0100 Subject: [PATCH] add indestructible support for Array, Map and Set objects (flag won't be alter thei construction anymore) --- README.md | 3 ++- dist/main.js | 2 +- package.json | 2 +- src/deepClone.js | 21 +++++++++++++++++++-- 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index f18e31a..2688309 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ res instanceof Test; // true res.foo instanceof Test; // true ``` -It is actually a default enabled setting, but you can disable it (loosing the ability to properly clone array, map and set objects).\ +It is actually a default enabled setting, but you can disable it (Array, Map and Set objects will be properly cloned anyway).\ __It is highly discouraged to disable this flag__, do it only if you know what you are doing. If the `invokeConstructors` flag is set to `false`, a plain new object will be created for each object prop and for the resulting object as well. So the `constructor` prop will be set to the `Object` function, and the `[[Prototype]]` prop will be `Object.prototype`.\ @@ -74,6 +74,7 @@ Unless you use the `setPrototype` flag. ### setPrototype (default false) If the `invokeConstructors` flag is setted to `false` we could anyway share the `[[Prototype]]` object between the source object and the resulting object thanks to the `setPrototype` flag, __without calling the constructors__.\ +(Array, Map and Set objects will be properly cloned anyway because for them the constructor will be always called).\ This means that the `constructor` prop will be shared as well because it is related to the `[[Prototype]]` prop.\ This flag affects all the object properties as weel, like the previous flag.\ If the `invokeConstructors` flag is setted to `true`, the `setPrototype` flag will be is ignored. diff --git a/dist/main.js b/dist/main.js index c154071..3952f10 100644 --- a/dist/main.js +++ b/dist/main.js @@ -1 +1 @@ -module.exports=function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=6)}([function(e,t){e.exports=(e=>{if(e)return null;throw new TypeError("TypeError: cannot copy Error objects")})},function(e,t){e.exports=(e=>{const{source:t,flags:n,lastIndex:o}=e,r=new RegExp(t,n);return r.lastIndex=o,r})},function(e,t){e.exports=(e=>new Date(e.getTime()))},function(e,t){e.exports=(e=>e.valueOf())},function(e,t){e.exports=((e,t,n)=>{if(e.has(t)){if(n)return e.get(t);throw new TypeError("TypeError: circular reference found")}return null})},function(e,t){e.exports=((e,t)=>e.has(t)?e.get(t):null)},function(e,t,n){const o=n(7),r=n(0),i=n(1),s=n(2);e.exports=function(e={},{setPrototype:t=!1,invokeConstructors:n=!0,copyNonEnumerables:c=!1,copySymbols:f=!1,copyGettersSetters:a=!1,allowCircularReferences:u=!1,discardErrorObjects:p=!0}={}){if(!e||"object"!=typeof e)throw new TypeError("TypeError: invalid 'obj' argument's type");if(e instanceof Number||e instanceof String||e instanceof Boolean)return null;if(e instanceof Promise||e instanceof WeakMap||e instanceof WeakSet)return e;if(e instanceof Error)return r(p);if(e instanceof RegExp)return i(e);if(e instanceof Date)return s(e);if("boolean"!=typeof t)throw new TypeError("TypeError: invalid 'setPrototype' flag's type");if("boolean"!=typeof n)throw new TypeError("TypeError: invalid 'invokeConstructors' flag's type");if("boolean"!=typeof c)throw new TypeError("TypeError: invalid 'copyNonEnumerables' flag's type");if("boolean"!=typeof f)throw new TypeError("TypeError: invalid 'copySymbols' flag's type");if("boolean"!=typeof a)throw new TypeError("TypeError: invalid 'copyGettersSetters' flag's type");if("boolean"!=typeof u)throw new TypeError("TypeError: invalid 'allowCircularReferences' flag's type");if("boolean"!=typeof p)throw new TypeError("TypeError: invalid 'discardErrorObjects' flag's type");return o(e,{setPrototype:t,invokeConstructors:n,copyNonEnumerables:c,copySymbols:f,copyGettersSetters:a,allowCircularReferences:u,discardErrorObjects:p})}},function(e,t,n){const o=n(8),r=n(12);e.exports=function(e,t){return function e(t,n,i,s){const{setPrototype:c,invokeConstructors:f,allowCircularReferences:a}=n;i.set(t,t);let u=null;if(u=f?new t.constructor:c?Object.create(Object.getPrototypeOf(t)):{},t instanceof Map){const o=[...t.entries()];r(u,{mapEntries:o},n,s,i,e)}else if(t instanceof Set){const o=[...t.values()];r(u,{setEntries:o},n,s,i,e)}else{const o=Object.getOwnPropertyDescriptors(t);r(u,{ownPropsDcps:o},n,s,i,e)}return a&&(i.set(t,u),s===t&&o(u,i)),u}(e,t,new WeakMap,e)}},function(e,t,n){const o=n(9),r=n(10),i=n(11);e.exports=function(e,t){const n=new WeakMap;n.set(e),function e(t,n,s){return t instanceof Map?o(t,n,s,e):t instanceof Set?r(t,n,s,e):i(t,n,s,e)}(e,t,n)}},function(e,t){e.exports=((e,t,n,o)=>{const r=[...e.entries()];for(const[i,s]of r)if(s&&"object"==typeof s)if(t.has(s))e.set(i,t.get(s));else{if(n.has(s))continue;n.set(s),o(s,t,n)}})},function(e,t){e.exports=((e,t,n,o)=>{const r=[...e.values()];for(const i of r)if(i&&"object"==typeof i)if(t.has(i))e.delete(i),e.add(t.get(i));else{if(n.has(i))continue;n.set(i),o(i,t,n)}})},function(e,t){e.exports=((e,t,n,o)=>{Object.entries(e).forEach(([r,i])=>{if(i&&"object"==typeof i)if(t.has(i))e[r]=t.get(i);else{if(n.has(i))return;n.set(i),o(i,t,n)}})})},function(e,t,n){const o=n(13),r=n(14),i=n(15);e.exports=function(e,t,n,s,c,f){return function(e,t,n,c,a){const{mapEntries:u,setEntries:p,ownPropsDcps:l}=t;if(u)return o(e,u,n,s,c,a,f);if(p)return r(e,p,n,s,a,f);if(l)return i(e,l,n,s,c,a,f);throw new Error("wrong data parameter for innerPropsHandler function")}(e,t,n,new WeakMap,c)}},function(e,t,n){const o=n(0),r=n(1),i=n(2),s=n(3),c=n(4),f=n(5);e.exports=((e,t,n,a,u,p,l)=>{const y=t,{allowCircularReferences:d,discardErrorObjects:b}=n;for(const[t,E]of y)if(E&&"object"==typeof E){const y=f(u,E);if(y){e.set(t,y);continue}const w=c(p,E,d);if(w){e.set(t,w);continue}if(p.has(E)){if(d){e.set(t,p.get(E));continue}throw new TypeError("TypeError: circular reference found")}if(E instanceof Error){o(b);continue}if(E instanceof Number||E instanceof Boolean||E instanceof String){e.set(t,s(E));continue}if(E instanceof Date){const n=i(E);e.set(t,n),u.set(E,n);continue}if(E instanceof RegExp){const n=r(E);e.set(t,n),u.set(E,n);continue}if(E instanceof Promise){e.set(t,E);continue}if(E instanceof WeakMap){e.set(t,E);continue}if(E instanceof WeakSet){e.set(t,E);continue}e.set(t,l(E,n,p,a)),u.set(E,e.get(t))}else e.set(t,E)})},function(e,t,n){const o=n(0),r=n(1),i=n(2),s=n(3),c=n(4);e.exports=((e,t,n,f,a,u)=>{const p=t,{allowCircularReferences:l,discardErrorObjects:y}=n;for(const t of p)if(t&&"object"==typeof t){const p=c(a,t,l);if(p){e.add(p);continue}if(t instanceof Error){o(y);continue}if(t instanceof Number||t instanceof Boolean||t instanceof String){e.add(s(t));continue}if(t instanceof Date){const n=i(t);e.add(n);continue}if(t instanceof RegExp){const n=r(t);e.add(n);continue}if(t instanceof Promise){e.add(t);continue}if(t instanceof WeakMap){e.add(t);continue}if(t instanceof WeakSet){e.add(t);continue}const d=u(t,n,a,f);e.add(d)}else e.add(t)})},function(e,t,n){const o=n(0),r=n(1),i=n(2),s=n(3),c=n(4),f=n(5);e.exports=((e,t,n,a,u,p,l)=>{const y=t,{copyNonEnumerables:d,copySymbols:b,copyGettersSetters:E,allowCircularReferences:w,discardErrorObjects:g}=n;Object.entries(y).forEach(([t,y])=>{const{value:v,enumerable:j}=y;if((d||j)&&(b||"symbol"!=typeof v)&&(E||!y.get&&!y.set))if(v&&"object"==typeof v){const d=f(u,v);if(d)return void(e[t]=d);const b=c(p,v,w);if(b)return void(e[t]=b);if(v instanceof Error)return void o(g);if(v instanceof Number||v instanceof Boolean||v instanceof String){const n=s(v);return void Object.defineProperty(e,t,{...y,...{value:n}})}if(v instanceof Date){const n=i(v);return Object.defineProperty(e,t,{...y,...{value:n}}),void u.set(v,n)}if(v instanceof RegExp){const n=r(v);return Object.defineProperty(e,t,{...y,...{value:n}}),void u.set(v,n)}if(v instanceof Promise)return void Object.defineProperty(e,t,y);if(v instanceof WeakMap)return void Object.defineProperty(e,t,y);if(v instanceof WeakSet)return void Object.defineProperty(e,t,y);e[t]=l(v,n,p,a),u.set(v,e[t])}else{const n=Object.getOwnPropertyDescriptor(e,t);n&&!n.configurable||Object.defineProperty(e,t,y)}})})}]); \ No newline at end of file +module.exports=function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=6)}([function(e,t){e.exports=(e=>{if(e)return null;throw new TypeError("TypeError: cannot copy Error objects")})},function(e,t){e.exports=(e=>{const{source:t,flags:n,lastIndex:o}=e,r=new RegExp(t,n);return r.lastIndex=o,r})},function(e,t){e.exports=(e=>new Date(e.getTime()))},function(e,t){e.exports=(e=>e.valueOf())},function(e,t){e.exports=((e,t,n)=>{if(e.has(t)){if(n)return e.get(t);throw new TypeError("TypeError: circular reference found")}return null})},function(e,t){e.exports=((e,t)=>e.has(t)?e.get(t):null)},function(e,t,n){const o=n(7),r=n(0),i=n(1),s=n(2);e.exports=function(e={},{setPrototype:t=!1,invokeConstructors:n=!0,copyNonEnumerables:c=!1,copySymbols:f=!1,copyGettersSetters:a=!1,allowCircularReferences:u=!1,discardErrorObjects:p=!0}={}){if(!e||"object"!=typeof e)throw new TypeError("TypeError: invalid 'obj' argument's type");if(e instanceof Number||e instanceof String||e instanceof Boolean)return null;if(e instanceof Promise||e instanceof WeakMap||e instanceof WeakSet)return e;if(e instanceof Error)return r(p);if(e instanceof RegExp)return i(e);if(e instanceof Date)return s(e);if("boolean"!=typeof t)throw new TypeError("TypeError: invalid 'setPrototype' flag's type");if("boolean"!=typeof n)throw new TypeError("TypeError: invalid 'invokeConstructors' flag's type");if("boolean"!=typeof c)throw new TypeError("TypeError: invalid 'copyNonEnumerables' flag's type");if("boolean"!=typeof f)throw new TypeError("TypeError: invalid 'copySymbols' flag's type");if("boolean"!=typeof a)throw new TypeError("TypeError: invalid 'copyGettersSetters' flag's type");if("boolean"!=typeof u)throw new TypeError("TypeError: invalid 'allowCircularReferences' flag's type");if("boolean"!=typeof p)throw new TypeError("TypeError: invalid 'discardErrorObjects' flag's type");return o(e,{setPrototype:t,invokeConstructors:n,copyNonEnumerables:c,copySymbols:f,copyGettersSetters:a,allowCircularReferences:u,discardErrorObjects:p})}},function(e,t,n){const o=n(8),r=n(12);e.exports=function(e,t){return function e(t,n,i,s){const{setPrototype:c,invokeConstructors:f,allowCircularReferences:a}=n;i.set(t,t);let u=null;if(u=f?new t.constructor:c?Object.create(Object.getPrototypeOf(t)):{},t instanceof Array&&(u=[]),t instanceof Map){u=new Map;const o=[...t.entries()];r(u,{mapEntries:o},n,s,i,e)}else if(t instanceof Set){u=new Set;const o=[...t.values()];r(u,{setEntries:o},n,s,i,e)}else{const o=Object.getOwnPropertyDescriptors(t);r(u,{ownPropsDcps:o},n,s,i,e)}return a&&(i.set(t,u),s===t&&o(u,i)),u}(e,t,new WeakMap,e)}},function(e,t,n){const o=n(9),r=n(10),i=n(11);e.exports=function(e,t){const n=new WeakMap;n.set(e),function e(t,n,s){return t instanceof Map?o(t,n,s,e):t instanceof Set?r(t,n,s,e):i(t,n,s,e)}(e,t,n)}},function(e,t){e.exports=((e,t,n,o)=>{const r=[...e.entries()];for(const[i,s]of r)if(s&&"object"==typeof s)if(t.has(s))e.set(i,t.get(s));else{if(n.has(s))continue;n.set(s),o(s,t,n)}})},function(e,t){e.exports=((e,t,n,o)=>{const r=[...e.values()];for(const i of r)if(i&&"object"==typeof i)if(t.has(i))e.delete(i),e.add(t.get(i));else{if(n.has(i))continue;n.set(i),o(i,t,n)}})},function(e,t){e.exports=((e,t,n,o)=>{Object.entries(e).forEach(([r,i])=>{if(i&&"object"==typeof i)if(t.has(i))e[r]=t.get(i);else{if(n.has(i))return;n.set(i),o(i,t,n)}})})},function(e,t,n){const o=n(13),r=n(14),i=n(15);e.exports=function(e,t,n,s,c,f){return function(e,t,n,c,a){const{mapEntries:u,setEntries:p,ownPropsDcps:l}=t;if(u)return o(e,u,n,s,c,a,f);if(p)return r(e,p,n,s,a,f);if(l)return i(e,l,n,s,c,a,f);throw new Error("wrong data parameter for innerPropsHandler function")}(e,t,n,new WeakMap,c)}},function(e,t,n){const o=n(0),r=n(1),i=n(2),s=n(3),c=n(4),f=n(5);e.exports=((e,t,n,a,u,p,l)=>{const y=t,{allowCircularReferences:d,discardErrorObjects:b}=n;for(const[t,E]of y)if(E&&"object"==typeof E){const y=f(u,E);if(y){e.set(t,y);continue}const w=c(p,E,d);if(w){e.set(t,w);continue}if(p.has(E)){if(d){e.set(t,p.get(E));continue}throw new TypeError("TypeError: circular reference found")}if(E instanceof Error){o(b);continue}if(E instanceof Number||E instanceof Boolean||E instanceof String){e.set(t,s(E));continue}if(E instanceof Date){const n=i(E);e.set(t,n),u.set(E,n);continue}if(E instanceof RegExp){const n=r(E);e.set(t,n),u.set(E,n);continue}if(E instanceof Promise){e.set(t,E);continue}if(E instanceof WeakMap){e.set(t,E);continue}if(E instanceof WeakSet){e.set(t,E);continue}e.set(t,l(E,n,p,a)),u.set(E,e.get(t))}else e.set(t,E)})},function(e,t,n){const o=n(0),r=n(1),i=n(2),s=n(3),c=n(4);e.exports=((e,t,n,f,a,u)=>{const p=t,{allowCircularReferences:l,discardErrorObjects:y}=n;for(const t of p)if(t&&"object"==typeof t){const p=c(a,t,l);if(p){e.add(p);continue}if(t instanceof Error){o(y);continue}if(t instanceof Number||t instanceof Boolean||t instanceof String){e.add(s(t));continue}if(t instanceof Date){const n=i(t);e.add(n);continue}if(t instanceof RegExp){const n=r(t);e.add(n);continue}if(t instanceof Promise){e.add(t);continue}if(t instanceof WeakMap){e.add(t);continue}if(t instanceof WeakSet){e.add(t);continue}const d=u(t,n,a,f);e.add(d)}else e.add(t)})},function(e,t,n){const o=n(0),r=n(1),i=n(2),s=n(3),c=n(4),f=n(5);e.exports=((e,t,n,a,u,p,l)=>{const y=t,{copyNonEnumerables:d,copySymbols:b,copyGettersSetters:E,allowCircularReferences:w,discardErrorObjects:g}=n;Object.entries(y).forEach(([t,y])=>{const{value:v,enumerable:j}=y;if((d||j)&&(b||"symbol"!=typeof v)&&(E||!y.get&&!y.set))if(v&&"object"==typeof v){const d=f(u,v);if(d)return void(e[t]=d);const b=c(p,v,w);if(b)return void(e[t]=b);if(v instanceof Error)return void o(g);if(v instanceof Number||v instanceof Boolean||v instanceof String){const n=s(v);return void Object.defineProperty(e,t,{...y,...{value:n}})}if(v instanceof Date){const n=i(v);return Object.defineProperty(e,t,{...y,...{value:n}}),void u.set(v,n)}if(v instanceof RegExp){const n=r(v);return Object.defineProperty(e,t,{...y,...{value:n}}),void u.set(v,n)}if(v instanceof Promise)return void Object.defineProperty(e,t,y);if(v instanceof WeakMap)return void Object.defineProperty(e,t,y);if(v instanceof WeakSet)return void Object.defineProperty(e,t,y);e[t]=l(v,n,p,a),u.set(v,e[t])}else{const n=Object.getOwnPropertyDescriptor(e,t);n&&!n.configurable||Object.defineProperty(e,t,y)}})})}]); \ No newline at end of file diff --git a/package.json b/package.json index ab213de..c20d5ed 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "omniclone", - "version": "0.5.2", + "version": "0.5.3", "description": "deep cloning function for js objects", "main": "dist/main.js", "scripts": { diff --git a/src/deepClone.js b/src/deepClone.js index bc83a4f..8c52a31 100644 --- a/src/deepClone.js +++ b/src/deepClone.js @@ -27,9 +27,9 @@ function deepClone(source, config) { // result value let res = null; - // invokeConstructors flag indicates if the source constructor - // must be invocated. if (invokeConstructors) { + // invokeConstructors flag indicates if the source constructor + // must be invocated. res = new source.constructor(); // if so, the [[Prototype]] prop is set to constructor.protoype // so it could be different from the source [[Prototype]] @@ -44,7 +44,19 @@ function deepClone(source, config) { res = {}; } + // special case: Array + // to properly create arrays even when invokeConstructors flag is false + // and/or when setPrototype flag is false too + if (source instanceof Array) { + res = []; + } + if (source instanceof Map) { + // special case: Map + // to properly create maps even when invokeConstructors flag is false + // and/or when setPrototype flag is false too + res = new Map(); + // get the entries array const mapEntries = [...source.entries()]; @@ -58,6 +70,11 @@ function deepClone(source, config) { innerDeepClone ); } else if (source instanceof Set) { + // special case: Set + // to properly create sets even when invokeConstructors flag is false + // and/or when setPrototype flag is false too + res = new Set(); + // get the values array const setEntries = [...source.values()];