Comparing version 3.0.0-beta.7 to 3.0.0-beta.8
@@ -16,2 +16,3 @@ # fast-copy CHANGELOG | ||
- Can now create a custom copier, allowing maximum performance for specific use-cases | ||
- Correctly handle primitive wrappers, e.g. `new String('foo')` | ||
@@ -18,0 +19,0 @@ ## 2.1.7 |
import type { Cache } from './utils'; | ||
export declare type InternalCopier<Value = any> = (value: Value, state: State) => Value; | ||
export declare type InternalCopier<Value> = (value: Value, state: State) => Value; | ||
export interface State { | ||
Constructor: any; | ||
cache: Cache; | ||
copier: InternalCopier; | ||
copier: InternalCopier<any>; | ||
prototype: any; | ||
} | ||
/** | ||
* Deeply copy the indexed values in the array. | ||
*/ | ||
export declare function copyArrayLoose(array: any[], state: State): any; | ||
/** | ||
* Deeply copy the indexed values in the array, as well as any custom properties. | ||
*/ | ||
export declare function copyArrayStrict<Value extends any[]>(array: Value, state: State): Value; | ||
/** | ||
* Copy the contents of the ArrayBuffer. | ||
*/ | ||
export declare function copyArrayBuffer<Value extends ArrayBuffer>(arrayBuffer: Value, _state: State): Value; | ||
/** | ||
* Create a new Blob with the contents of the original. | ||
*/ | ||
export declare function copyBlob<Value extends Blob>(blob: Value, _state: State): Value; | ||
/** | ||
* Create a new DataView with the contents of the original. | ||
*/ | ||
export declare function copyDataView<Value extends DataView>(dataView: Value, state: State): Value; | ||
/** | ||
* Create a new Date based on the time of the original. | ||
*/ | ||
export declare function copyDate<Value extends Date>(date: Value, state: State): Value; | ||
/** | ||
* Deeply copy the keys and values of the original. | ||
*/ | ||
export declare function copyMapLoose<Value extends Map<any, any>>(map: Value, state: State): Value; | ||
/** | ||
* Deeply copy the keys and values of the original, as well as any custom properties. | ||
*/ | ||
export declare function copyMapStrict<Value extends Map<any, any>>(map: Value, state: State): Value; | ||
declare function copyObjectLooseModern<Value extends {}>(object: Value, state: State): Value; | ||
declare function copyObjectLooseModern<Value extends Record<string, any>>(object: Value, state: State): Value; | ||
/** | ||
* Get a copy of the object based on loose rules, meaning all enumerable keys | ||
* and symbols are copied, but property descriptors are not considered. | ||
* Deeply copy the properties (keys and symbols) and values of the original. | ||
*/ | ||
export declare const copyObjectLoose: typeof copyObjectLooseModern; | ||
/** | ||
* Get a copy of the object based on strict rules, meaning all keys and symbols | ||
* are copied based on the original property descriptors. | ||
* Deeply copy the properties (keys and symbols) and values of the original, as well | ||
* as any hidden or non-enumerable properties. | ||
*/ | ||
export declare function copyObjectStrict<Value extends {}>(object: Value, state: State): Value; | ||
export declare function copyObjectStrict<Value extends Record<string, any>>(object: Value, state: State): Value; | ||
/** | ||
* Create a new primitive wrapper from the value of the original. | ||
*/ | ||
export declare function copyPrimitiveWrapper<Value extends Boolean | Number | String>(primitiveObject: Value, state: State): Value; | ||
/** | ||
* Create a new RegExp based on the value and flags of the original. | ||
*/ | ||
export declare function copyRegExp<Value extends RegExp>(regExp: Value, state: State): Value; | ||
/** | ||
* Return the original value (an identity function). | ||
* | ||
* @note | ||
* THis is used for objects that cannot be copied, such as WeakMap. | ||
*/ | ||
export declare function copySelf<Value>(value: Value, _state: State): Value; | ||
/** | ||
* Deeply copy the values of the original. | ||
*/ | ||
export declare function copySetLoose<Value extends Set<any>>(set: Value, state: State): Value; | ||
/** | ||
* Deeply copy the values of the original, as well as any custom properties. | ||
*/ | ||
export declare function copySetStrict<Value extends Set<any>>(set: Value, state: State): Value; | ||
export {}; |
export interface Cache { | ||
_keys?: any[]; | ||
_values?: any[]; | ||
has: (value: any) => boolean; | ||
@@ -22,7 +20,7 @@ set: (key: any, value: any) => void; | ||
export declare const getRegExpFlags: typeof getRegExpFlagsModern; | ||
declare function getTagModern(value: any): string; | ||
declare function getTagLegacy(value: any): string; | ||
/** | ||
* Get the tag of the value passed, so that the correct copier can be used. | ||
*/ | ||
export declare const getTag: typeof getTagModern; | ||
export declare const getTag: typeof getTagLegacy; | ||
export {}; |
import type { Cache } from './utils'; | ||
export declare type InternalCopier<Value = any> = (value: Value, state: State) => Value; | ||
export declare type InternalCopier<Value> = (value: Value, state: State) => Value; | ||
export interface State { | ||
Constructor: any; | ||
cache: Cache; | ||
copier: InternalCopier; | ||
copier: InternalCopier<any>; | ||
prototype: any; | ||
} | ||
/** | ||
* Deeply copy the indexed values in the array. | ||
*/ | ||
export declare function copyArrayLoose(array: any[], state: State): any; | ||
/** | ||
* Deeply copy the indexed values in the array, as well as any custom properties. | ||
*/ | ||
export declare function copyArrayStrict<Value extends any[]>(array: Value, state: State): Value; | ||
/** | ||
* Copy the contents of the ArrayBuffer. | ||
*/ | ||
export declare function copyArrayBuffer<Value extends ArrayBuffer>(arrayBuffer: Value, _state: State): Value; | ||
/** | ||
* Create a new Blob with the contents of the original. | ||
*/ | ||
export declare function copyBlob<Value extends Blob>(blob: Value, _state: State): Value; | ||
/** | ||
* Create a new DataView with the contents of the original. | ||
*/ | ||
export declare function copyDataView<Value extends DataView>(dataView: Value, state: State): Value; | ||
/** | ||
* Create a new Date based on the time of the original. | ||
*/ | ||
export declare function copyDate<Value extends Date>(date: Value, state: State): Value; | ||
/** | ||
* Deeply copy the keys and values of the original. | ||
*/ | ||
export declare function copyMapLoose<Value extends Map<any, any>>(map: Value, state: State): Value; | ||
/** | ||
* Deeply copy the keys and values of the original, as well as any custom properties. | ||
*/ | ||
export declare function copyMapStrict<Value extends Map<any, any>>(map: Value, state: State): Value; | ||
declare function copyObjectLooseModern<Value extends {}>(object: Value, state: State): Value; | ||
declare function copyObjectLooseModern<Value extends Record<string, any>>(object: Value, state: State): Value; | ||
/** | ||
* Get a copy of the object based on loose rules, meaning all enumerable keys | ||
* and symbols are copied, but property descriptors are not considered. | ||
* Deeply copy the properties (keys and symbols) and values of the original. | ||
*/ | ||
export declare const copyObjectLoose: typeof copyObjectLooseModern; | ||
/** | ||
* Get a copy of the object based on strict rules, meaning all keys and symbols | ||
* are copied based on the original property descriptors. | ||
* Deeply copy the properties (keys and symbols) and values of the original, as well | ||
* as any hidden or non-enumerable properties. | ||
*/ | ||
export declare function copyObjectStrict<Value extends {}>(object: Value, state: State): Value; | ||
export declare function copyObjectStrict<Value extends Record<string, any>>(object: Value, state: State): Value; | ||
/** | ||
* Create a new primitive wrapper from the value of the original. | ||
*/ | ||
export declare function copyPrimitiveWrapper<Value extends Boolean | Number | String>(primitiveObject: Value, state: State): Value; | ||
/** | ||
* Create a new RegExp based on the value and flags of the original. | ||
*/ | ||
export declare function copyRegExp<Value extends RegExp>(regExp: Value, state: State): Value; | ||
/** | ||
* Return the original value (an identity function). | ||
* | ||
* @note | ||
* THis is used for objects that cannot be copied, such as WeakMap. | ||
*/ | ||
export declare function copySelf<Value>(value: Value, _state: State): Value; | ||
/** | ||
* Deeply copy the values of the original. | ||
*/ | ||
export declare function copySetLoose<Value extends Set<any>>(set: Value, state: State): Value; | ||
/** | ||
* Deeply copy the values of the original, as well as any custom properties. | ||
*/ | ||
export declare function copySetStrict<Value extends Set<any>>(set: Value, state: State): Value; | ||
export {}; |
export interface Cache { | ||
_keys?: any[]; | ||
_values?: any[]; | ||
has: (value: any) => boolean; | ||
@@ -22,7 +20,7 @@ set: (key: any, value: any) => void; | ||
export declare const getRegExpFlags: typeof getRegExpFlagsModern; | ||
declare function getTagModern(value: any): string; | ||
declare function getTagLegacy(value: any): string; | ||
/** | ||
* Get the tag of the value passed, so that the correct copier can be used. | ||
*/ | ||
export declare const getTag: typeof getTagModern; | ||
export declare const getTag: typeof getTagLegacy; | ||
export {}; |
@@ -1,2 +0,2 @@ | ||
!function(t,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports):"function"==typeof define&&define.amd?define(["exports"],r):r((t="undefined"!=typeof globalThis?globalThis:t||self)["fast-copy"]={})}(this,(function(t){"use strict";var r=Function.prototype.toString,e=Object.create,n=Object.prototype.toString,o=function(){function t(){this._keys=[],this._values=[]}return t.prototype.has=function(t){return!!~this._keys.indexOf(t)},t.prototype.get=function(t){return this._values[this._keys.indexOf(t)]},t.prototype.set=function(t,r){this._keys.push(t),this._values.push(r)},t}();var c="undefined"!=typeof WeakMap?function(){return new WeakMap}:function(){return new o};function i(t){if(!t)return e(null);var n=t.constructor;if(n===Object)return t===Object.prototype?{}:e(t);if(~r.call(n).indexOf("[native code]"))try{return new n}catch(t){}return e(t)}var u="g"===/test/g.flags?function(t){return t.flags}:function(t){var r="";return t.global&&(r+="g"),t.ignoreCase&&(r+="i"),t.multiline&&(r+="m"),t.unicode&&(r+="u"),t.sticky&&(r+="y"),r};function a(t){var r=n.call(t);return r.substring(8,r.length-1)}var f="undefined"!=typeof Symbol?function(t){return t[Symbol.toStringTag]||a(t)}:a,s=Object.defineProperty,p=Object.getOwnPropertyDescriptor,y=Object.getOwnPropertyNames,l=Object.getOwnPropertySymbols,v=Object.prototype,d=v.hasOwnProperty,h=v.propertyIsEnumerable,b="function"==typeof l;var g=b?function(t){return y(t).concat(l(t))}:y;function O(t,r,e){for(var n=g(t),o=e.copier,c=0,i=n.length,u=void 0,a=void 0;c<i;++c)if("callee"!==(u=n[c])&&"caller"!==u)if(a=p(t,u)){a.get||a.set||(a.value=o(a.value,e));try{s(r,u,a)}catch(t){r[u]=a.value}}else r[u]=o(t[u],e);return r}function j(t,r){var e=new r.Constructor,n=r.cache,o=r.copier;n.set(t,e);for(var c=0,i=t.length;c<i;++c)e[c]=o(t[c],r);return e}function w(t,r){var e=new r.Constructor;return r.cache.set(t,e),O(t,e,r)}function C(t,r){return t.slice(0)}function m(t,r){return t.slice(0,t.size,t.type)}function A(t,r){return new r.Constructor(C(t.buffer))}function _(t,r){return new r.Constructor(t.getTime())}function x(t,r){var e=new r.Constructor,n=r.cache,o=r.copier;return n.set(t,e),t.forEach((function(t,n){e.set(n,o(t,r))})),e}function S(t,r){return O(t,x(t,r),r)}var k=b?function(t,r){var e=i(r.prototype),n=r.cache,o=r.copier;for(var c in n.set(t,e),t)d.call(t,c)&&(e[c]=o(t[c],r));for(var u=l(t),a=0,f=u.length,s=void 0;a<f;++a)s=u[a],h.call(t,s)&&(e[s]=o(t[s],r));return e}:function(t,r){var e=i(r.prototype),n=r.cache,o=r.copier;for(var c in n.set(t,e),t)d.call(t,c)&&(e[c]=o(t[c],r));return e};function P(t,r){var e=i(r.prototype);return r.cache.set(t,e),O(t,e,r)}function E(t,r){var e=new r.Constructor(t.source,u(t));return e.lastIndex=t.lastIndex,e}function I(t,r){return t}function M(t,r){var e=new r.Constructor,n=r.cache,o=r.copier;return n.set(t,e),t.forEach((function(t){e.add(o(t,r))})),e}function U(t,r){return O(t,M(t,r),r)}var T=Array.isArray,W=Object.getPrototypeOf;function B(t){var r=t.array,e=void 0===r?j:r,n=t.arrayBuffer,o=void 0===n?C:n,i=t.blob,u=void 0===i?m:i,a=t.dataView,s=void 0===a?A:a,p=t.date,y=void 0===p?_:p,l=t.error,v=void 0===l?I:l,d=t.map,h=void 0===d?x:d,b=t.object,g=void 0===b?k:b,O=t.regExp,w=void 0===O?E:O,S=t.set,P={Array:e,ArrayBuffer:o,Blob:u,DataView:s,Date:y,Error:v,Float32Array:o,Float64Array:o,Int8Array:o,Int16Array:o,Int32Array:o,Map:h,Object:g,Promise:I,RegExp:w,Set:void 0===S?M:S,WeakMap:I,WeakSet:I,Uint8Array:o,Uint8ClampedArray:o,Uint16Array:o,Uint32Array:o,Uint64Array:o};function U(t,r){if(r.prototype=r.Constructor=void 0,!t||"object"!=typeof t)return t;if(r.cache.has(t))return r.cache.get(t);if(r.prototype=t.__proto__||W(t),r.Constructor=r.prototype&&r.prototype.constructor,!r.Constructor||r.Constructor===Object)return g(t,r);if(T(t))return e(t,r);var n=P[f(t)];return n?n(t,r):"function"==typeof t.then?t:g(t,r)}return function(t){return U(t,{Constructor:void 0,cache:c(),copier:U,prototype:void 0})}}function D(t){return B(Object.assign({array:w,map:S,object:P,set:U},t))}var F=D({}),V=B({});t.copyStrict=F,t.createCopier=B,t.createStrictCopier=D,t.default=V,Object.defineProperty(t,"__esModule",{value:!0})})); | ||
!function(r,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((r="undefined"!=typeof globalThis?globalThis:r||self)["fast-copy"]={})}(this,(function(r){"use strict";var t=Function.prototype.toString,e=Object.create,n=Object.prototype.toString,o=function(){function r(){this._keys=[],this._values=[]}return r.prototype.has=function(r){return!!~this._keys.indexOf(r)},r.prototype.get=function(r){return this._values[this._keys.indexOf(r)]},r.prototype.set=function(r,t){this._keys.push(r),this._values.push(t)},r}();var a="undefined"!=typeof WeakMap?function(){return new WeakMap}:function(){return new o};function c(r){if(!r)return e(null);var n=r.constructor;if(n===Object)return r===Object.prototype?{}:e(r);if(~t.call(n).indexOf("[native code]"))try{return new n}catch(r){}return e(r)}var u="g"===/test/g.flags?function(r){return r.flags}:function(r){var t="";return r.global&&(t+="g"),r.ignoreCase&&(t+="i"),r.multiline&&(t+="m"),r.unicode&&(t+="u"),r.sticky&&(t+="y"),t};function i(r){var t=n.call(r);return t.substring(8,t.length-1)}var f="undefined"!=typeof Symbol?function(r){return r[Symbol.toStringTag]||i(r)}:i,s=Object.defineProperty,p=Object.getOwnPropertyDescriptor,y=Object.getOwnPropertyNames,l=Object.getOwnPropertySymbols,v=Object.prototype,d=v.hasOwnProperty,b=v.propertyIsEnumerable,h="function"==typeof l;var g=h?function(r){return y(r).concat(l(r))}:y;function O(r,t,e){for(var n=g(r),o=0,a=n.length,c=void 0,u=void 0;o<a;++o)if("callee"!==(c=n[o])&&"caller"!==c)if(u=p(r,c)){u.get||u.set||(u.value=e.copier(u.value,e));try{s(t,c,u)}catch(r){t[c]=u.value}}else t[c]=e.copier(r[c],e);return t}function j(r,t){return r.slice(0)}function w(r,t){var e=new t.Constructor;return t.cache.set(r,e),r.forEach((function(r,n){e.set(n,t.copier(r,t))})),e}var m=h?function(r,t){var e=c(t.prototype);for(var n in t.cache.set(r,e),r)d.call(r,n)&&(e[n]=t.copier(r[n],t));for(var o=l(r),a=0,u=o.length,i=void 0;a<u;++a)i=o[a],b.call(r,i)&&(e[i]=t.copier(r[i],t));return e}:function(r,t){var e=c(t.prototype);for(var n in t.cache.set(r,e),r)d.call(r,n)&&(e[n]=t.copier(r[n],t));return e};function C(r,t){return new t.Constructor(r.valueOf())}function A(r,t){return r}function B(r,t){var e=new t.Constructor;return t.cache.set(r,e),r.forEach((function(r){e.add(t.copier(r,t))})),e}var _=Array.isArray,x=Object.assign,S=Object.getPrototypeOf,k={array:function(r,t){var e=new t.Constructor;t.cache.set(r,e);for(var n=0,o=r.length;n<o;++n)e[n]=t.copier(r[n],t);return e},arrayBuffer:j,blob:function(r,t){return r.slice(0,r.size,r.type)},dataView:function(r,t){return new t.Constructor(j(r.buffer))},date:function(r,t){return new t.Constructor(r.getTime())},error:A,map:w,object:m,regExp:function(r,t){var e=new t.Constructor(r.source,u(r));return e.lastIndex=r.lastIndex,e},set:B},P=x({},k,{array:function(r,t){var e=new t.Constructor;return t.cache.set(r,e),O(r,e,t)},map:function(r,t){return O(r,w(r,t),t)},object:function(r,t){var e=c(t.prototype);return t.cache.set(r,e),O(r,e,t)},set:function(r,t){return O(r,B(r,t),t)}});function E(r){var t=function(r){return{Arguments:r.object,Array:r.array,ArrayBuffer:r.arrayBuffer,Blob:r.blob,Boolean:C,DataView:r.dataView,Date:r.date,Error:r.error,Float32Array:r.arrayBuffer,Float64Array:r.arrayBuffer,Int8Array:r.arrayBuffer,Int16Array:r.arrayBuffer,Int32Array:r.arrayBuffer,Map:r.map,Number:C,Object:r.object,Promise:A,RegExp:r.regExp,Set:r.set,String:C,WeakMap:A,WeakSet:A,Uint8Array:r.arrayBuffer,Uint8ClampedArray:r.arrayBuffer,Uint16Array:r.arrayBuffer,Uint32Array:r.arrayBuffer,Uint64Array:r.arrayBuffer}}(x({},k,r)),e=t.Array,n=t.Object;function o(r,o){if(o.prototype=o.Constructor=void 0,!r||"object"!=typeof r)return r;if(o.cache.has(r))return o.cache.get(r);if(o.prototype=r.__proto__||S(r),o.Constructor=o.prototype&&o.prototype.constructor,!o.Constructor||o.Constructor===Object)return n(r,o);if(_(r))return e(r,o);var a=t[f(r)];return a?a(r,o):"function"==typeof r.then?r:n(r,o)}return function(r){return o(r,{Constructor:void 0,cache:a(),copier:o,prototype:void 0})}}function I(r){return E(x({},P,r))}var M=I({}),U=E({});r.copyStrict=M,r.createCopier=E,r.createStrictCopier=I,r.default=U,Object.defineProperty(r,"__esModule",{value:!0})})); | ||
//# sourceMappingURL=index.js.map |
import type { Cache } from './utils'; | ||
export declare type InternalCopier<Value = any> = (value: Value, state: State) => Value; | ||
export declare type InternalCopier<Value> = (value: Value, state: State) => Value; | ||
export interface State { | ||
Constructor: any; | ||
cache: Cache; | ||
copier: InternalCopier; | ||
copier: InternalCopier<any>; | ||
prototype: any; | ||
} | ||
/** | ||
* Deeply copy the indexed values in the array. | ||
*/ | ||
export declare function copyArrayLoose(array: any[], state: State): any; | ||
/** | ||
* Deeply copy the indexed values in the array, as well as any custom properties. | ||
*/ | ||
export declare function copyArrayStrict<Value extends any[]>(array: Value, state: State): Value; | ||
/** | ||
* Copy the contents of the ArrayBuffer. | ||
*/ | ||
export declare function copyArrayBuffer<Value extends ArrayBuffer>(arrayBuffer: Value, _state: State): Value; | ||
/** | ||
* Create a new Blob with the contents of the original. | ||
*/ | ||
export declare function copyBlob<Value extends Blob>(blob: Value, _state: State): Value; | ||
/** | ||
* Create a new DataView with the contents of the original. | ||
*/ | ||
export declare function copyDataView<Value extends DataView>(dataView: Value, state: State): Value; | ||
/** | ||
* Create a new Date based on the time of the original. | ||
*/ | ||
export declare function copyDate<Value extends Date>(date: Value, state: State): Value; | ||
/** | ||
* Deeply copy the keys and values of the original. | ||
*/ | ||
export declare function copyMapLoose<Value extends Map<any, any>>(map: Value, state: State): Value; | ||
/** | ||
* Deeply copy the keys and values of the original, as well as any custom properties. | ||
*/ | ||
export declare function copyMapStrict<Value extends Map<any, any>>(map: Value, state: State): Value; | ||
declare function copyObjectLooseModern<Value extends {}>(object: Value, state: State): Value; | ||
declare function copyObjectLooseModern<Value extends Record<string, any>>(object: Value, state: State): Value; | ||
/** | ||
* Get a copy of the object based on loose rules, meaning all enumerable keys | ||
* and symbols are copied, but property descriptors are not considered. | ||
* Deeply copy the properties (keys and symbols) and values of the original. | ||
*/ | ||
export declare const copyObjectLoose: typeof copyObjectLooseModern; | ||
/** | ||
* Get a copy of the object based on strict rules, meaning all keys and symbols | ||
* are copied based on the original property descriptors. | ||
* Deeply copy the properties (keys and symbols) and values of the original, as well | ||
* as any hidden or non-enumerable properties. | ||
*/ | ||
export declare function copyObjectStrict<Value extends {}>(object: Value, state: State): Value; | ||
export declare function copyObjectStrict<Value extends Record<string, any>>(object: Value, state: State): Value; | ||
/** | ||
* Create a new primitive wrapper from the value of the original. | ||
*/ | ||
export declare function copyPrimitiveWrapper<Value extends Boolean | Number | String>(primitiveObject: Value, state: State): Value; | ||
/** | ||
* Create a new RegExp based on the value and flags of the original. | ||
*/ | ||
export declare function copyRegExp<Value extends RegExp>(regExp: Value, state: State): Value; | ||
/** | ||
* Return the original value (an identity function). | ||
* | ||
* @note | ||
* THis is used for objects that cannot be copied, such as WeakMap. | ||
*/ | ||
export declare function copySelf<Value>(value: Value, _state: State): Value; | ||
/** | ||
* Deeply copy the values of the original. | ||
*/ | ||
export declare function copySetLoose<Value extends Set<any>>(set: Value, state: State): Value; | ||
/** | ||
* Deeply copy the values of the original, as well as any custom properties. | ||
*/ | ||
export declare function copySetStrict<Value extends Set<any>>(set: Value, state: State): Value; | ||
export {}; |
export interface Cache { | ||
_keys?: any[]; | ||
_values?: any[]; | ||
has: (value: any) => boolean; | ||
@@ -22,7 +20,7 @@ set: (key: any, value: any) => void; | ||
export declare const getRegExpFlags: typeof getRegExpFlagsModern; | ||
declare function getTagModern(value: any): string; | ||
declare function getTagLegacy(value: any): string; | ||
/** | ||
* Get the tag of the value passed, so that the correct copier can be used. | ||
*/ | ||
export declare const getTag: typeof getTagModern; | ||
export declare const getTag: typeof getTagLegacy; | ||
export {}; |
@@ -10,2 +10,5 @@ (function (global, factory) { | ||
var toStringObject = Object.prototype.toString; | ||
/** | ||
* @classdesc Fallback cache for when WeakMap is not natively supported | ||
*/ | ||
var LegacyCache = /** @class */ (function () { | ||
@@ -101,8 +104,13 @@ function LegacyCache() { | ||
} | ||
/** | ||
* Get the properites used when copying objects strictly. This includes both keys and symbols. | ||
*/ | ||
var getStrictProperties = SUPPORTS_SYMBOL | ||
? getStrictPropertiesModern | ||
: getOwnPropertyNames; | ||
/** | ||
* Striclty copy all properties contained on the object. | ||
*/ | ||
function copyOwnPropertiesStrict(value, clone, state) { | ||
var properties = getStrictProperties(value); | ||
var copier = state.copier; | ||
for (var index = 0, length_1 = properties.length, property = void 0, descriptor = void 0; index < length_1; ++index) { | ||
@@ -117,3 +125,3 @@ property = properties[index]; | ||
// the loose assignment. | ||
clone[property] = copier(value[property], state); | ||
clone[property] = state.copier(value[property], state); | ||
continue; | ||
@@ -123,3 +131,3 @@ } | ||
if (!descriptor.get && !descriptor.set) { | ||
descriptor.value = copier(descriptor.value, state); | ||
descriptor.value = state.copier(descriptor.value, state); | ||
} | ||
@@ -136,37 +144,62 @@ try { | ||
} | ||
/** | ||
* Deeply copy the indexed values in the array. | ||
*/ | ||
function copyArrayLoose(array, state) { | ||
var clone = new state.Constructor(); | ||
var cache = state.cache, copier = state.copier; | ||
cache.set(array, clone); | ||
// set in the cache immediately to be able to reuse the object recursively | ||
state.cache.set(array, clone); | ||
for (var index = 0, length_2 = array.length; index < length_2; ++index) { | ||
clone[index] = copier(array[index], state); | ||
clone[index] = state.copier(array[index], state); | ||
} | ||
return clone; | ||
} | ||
/** | ||
* Deeply copy the indexed values in the array, as well as any custom properties. | ||
*/ | ||
function copyArrayStrict(array, state) { | ||
var clone = new state.Constructor(); | ||
// set in the cache immediately to be able to reuse the object recursively | ||
state.cache.set(array, clone); | ||
return copyOwnPropertiesStrict(array, clone, state); | ||
} | ||
/** | ||
* Copy the contents of the ArrayBuffer. | ||
*/ | ||
function copyArrayBuffer(arrayBuffer, _state) { | ||
return arrayBuffer.slice(0); | ||
} | ||
/** | ||
* Create a new Blob with the contents of the original. | ||
*/ | ||
function copyBlob(blob, _state) { | ||
return blob.slice(0, blob.size, blob.type); | ||
} | ||
/** | ||
* Create a new DataView with the contents of the original. | ||
*/ | ||
function copyDataView(dataView, state) { | ||
return new state.Constructor(copyArrayBuffer(dataView.buffer)); | ||
} | ||
/** | ||
* Create a new Date based on the time of the original. | ||
*/ | ||
function copyDate(date, state) { | ||
return new state.Constructor(date.getTime()); | ||
} | ||
/** | ||
* Deeply copy the keys and values of the original. | ||
*/ | ||
function copyMapLoose(map, state) { | ||
var clone = new state.Constructor(); | ||
var cache = state.cache, copier = state.copier; | ||
cache.set(map, clone); | ||
// set in the cache immediately to be able to reuse the object recursively | ||
state.cache.set(map, clone); | ||
map.forEach(function (value, key) { | ||
clone.set(key, copier(value, state)); | ||
clone.set(key, state.copier(value, state)); | ||
}); | ||
return clone; | ||
} | ||
/** | ||
* Deeply copy the keys and values of the original, as well as any custom properties. | ||
*/ | ||
function copyMapStrict(map, state) { | ||
@@ -177,8 +210,7 @@ return copyOwnPropertiesStrict(map, copyMapLoose(map, state), state); | ||
var clone = getCleanClone(state.prototype); | ||
var cache = state.cache, copier = state.copier; | ||
// set in the cache immediately to be able to reuse the object recursively | ||
cache.set(object, clone); | ||
state.cache.set(object, clone); | ||
for (var key in object) { | ||
if (hasOwnProperty.call(object, key)) { | ||
clone[key] = copier(object[key], state); | ||
clone[key] = state.copier(object[key], state); | ||
} | ||
@@ -190,8 +222,7 @@ } | ||
var clone = getCleanClone(state.prototype); | ||
var cache = state.cache, copier = state.copier; | ||
// set in the cache immediately to be able to reuse the object recursively | ||
cache.set(object, clone); | ||
state.cache.set(object, clone); | ||
for (var key in object) { | ||
if (hasOwnProperty.call(object, key)) { | ||
clone[key] = copier(object[key], state); | ||
clone[key] = state.copier(object[key], state); | ||
} | ||
@@ -203,3 +234,3 @@ } | ||
if (propertyIsEnumerable.call(object, symbol)) { | ||
clone[symbol] = copier(object[symbol], state); | ||
clone[symbol] = state.copier(object[symbol], state); | ||
} | ||
@@ -210,4 +241,3 @@ } | ||
/** | ||
* Get a copy of the object based on loose rules, meaning all enumerable keys | ||
* and symbols are copied, but property descriptors are not considered. | ||
* Deeply copy the properties (keys and symbols) and values of the original. | ||
*/ | ||
@@ -218,4 +248,4 @@ var copyObjectLoose = SUPPORTS_SYMBOL | ||
/** | ||
* Get a copy of the object based on strict rules, meaning all keys and symbols | ||
* are copied based on the original property descriptors. | ||
* Deeply copy the properties (keys and symbols) and values of the original, as well | ||
* as any hidden or non-enumerable properties. | ||
*/ | ||
@@ -228,2 +258,11 @@ function copyObjectStrict(object, state) { | ||
} | ||
/** | ||
* Create a new primitive wrapper from the value of the original. | ||
*/ | ||
function copyPrimitiveWrapper(primitiveObject, state) { | ||
return new state.Constructor(primitiveObject.valueOf()); | ||
} | ||
/** | ||
* Create a new RegExp based on the value and flags of the original. | ||
*/ | ||
function copyRegExp(regExp, state) { | ||
@@ -234,14 +273,26 @@ var clone = new state.Constructor(regExp.source, getRegExpFlags(regExp)); | ||
} | ||
/** | ||
* Return the original value (an identity function). | ||
* | ||
* @note | ||
* THis is used for objects that cannot be copied, such as WeakMap. | ||
*/ | ||
function copySelf(value, _state) { | ||
return value; | ||
} | ||
/** | ||
* Deeply copy the values of the original. | ||
*/ | ||
function copySetLoose(set, state) { | ||
var clone = new state.Constructor(); | ||
var cache = state.cache, copier = state.copier; | ||
cache.set(set, clone); | ||
// set in the cache immediately to be able to reuse the object recursively | ||
state.cache.set(set, clone); | ||
set.forEach(function (value) { | ||
clone.add(copier(value, state)); | ||
clone.add(state.copier(value, state)); | ||
}); | ||
return clone; | ||
} | ||
/** | ||
* Deeply copy the values of the original, as well as any custom properties. | ||
*/ | ||
function copySetStrict(set, state) { | ||
@@ -252,33 +303,62 @@ return copyOwnPropertiesStrict(set, copySetLoose(set, state), state); | ||
var isArray = Array.isArray; | ||
var getPrototypeOf = Object.getPrototypeOf; | ||
var assign = Object.assign, getPrototypeOf = Object.getPrototypeOf; | ||
var DEFAULT_LOOSE_OPTIONS = { | ||
array: copyArrayLoose, | ||
arrayBuffer: copyArrayBuffer, | ||
blob: copyBlob, | ||
dataView: copyDataView, | ||
date: copyDate, | ||
error: copySelf, | ||
map: copyMapLoose, | ||
object: copyObjectLoose, | ||
regExp: copyRegExp, | ||
set: copySetLoose, | ||
}; | ||
var DEFAULT_STRICT_OPTIONS = assign({}, DEFAULT_LOOSE_OPTIONS, { | ||
array: copyArrayStrict, | ||
map: copyMapStrict, | ||
object: copyObjectStrict, | ||
set: copySetStrict, | ||
}); | ||
/** | ||
* Create a custom copier based on the object-specific copy methods passed. | ||
* Get the copiers used for each specific object tag. | ||
*/ | ||
function createCopier(options) { | ||
var _a = options.array, array = _a === void 0 ? copyArrayLoose : _a, _b = options.arrayBuffer, arrayBuffer = _b === void 0 ? copyArrayBuffer : _b, _c = options.blob, blob = _c === void 0 ? copyBlob : _c, _d = options.dataView, dataView = _d === void 0 ? copyDataView : _d, _e = options.date, date = _e === void 0 ? copyDate : _e, _f = options.error, error = _f === void 0 ? copySelf : _f, _g = options.map, map = _g === void 0 ? copyMapLoose : _g, _h = options.object, object = _h === void 0 ? copyObjectLoose : _h, _j = options.regExp, regExp = _j === void 0 ? copyRegExp : _j, _k = options.set, set = _k === void 0 ? copySetLoose : _k; | ||
var tagSpecificCopiers = { | ||
Array: array, | ||
ArrayBuffer: arrayBuffer, | ||
Blob: blob, | ||
DataView: dataView, | ||
Date: date, | ||
Error: error, | ||
Float32Array: arrayBuffer, | ||
Float64Array: arrayBuffer, | ||
Int8Array: arrayBuffer, | ||
Int16Array: arrayBuffer, | ||
Int32Array: arrayBuffer, | ||
Map: map, | ||
Object: object, | ||
function getTagSpecificCopiers(options) { | ||
return { | ||
Arguments: options.object, | ||
Array: options.array, | ||
ArrayBuffer: options.arrayBuffer, | ||
Blob: options.blob, | ||
Boolean: copyPrimitiveWrapper, | ||
DataView: options.dataView, | ||
Date: options.date, | ||
Error: options.error, | ||
Float32Array: options.arrayBuffer, | ||
Float64Array: options.arrayBuffer, | ||
Int8Array: options.arrayBuffer, | ||
Int16Array: options.arrayBuffer, | ||
Int32Array: options.arrayBuffer, | ||
Map: options.map, | ||
Number: copyPrimitiveWrapper, | ||
Object: options.object, | ||
Promise: copySelf, | ||
RegExp: regExp, | ||
Set: set, | ||
RegExp: options.regExp, | ||
Set: options.set, | ||
String: copyPrimitiveWrapper, | ||
WeakMap: copySelf, | ||
WeakSet: copySelf, | ||
Uint8Array: arrayBuffer, | ||
Uint8ClampedArray: arrayBuffer, | ||
Uint16Array: arrayBuffer, | ||
Uint32Array: arrayBuffer, | ||
Uint64Array: arrayBuffer, | ||
Uint8Array: options.arrayBuffer, | ||
Uint8ClampedArray: options.arrayBuffer, | ||
Uint16Array: options.arrayBuffer, | ||
Uint32Array: options.arrayBuffer, | ||
Uint64Array: options.arrayBuffer, | ||
}; | ||
} | ||
/** | ||
* Create a custom copier based on the object-specific copy methods passed. | ||
*/ | ||
function createCopier(options) { | ||
var normalizedOptions = assign({}, DEFAULT_LOOSE_OPTIONS, options); | ||
var tagSpecificCopiers = getTagSpecificCopiers(normalizedOptions); | ||
var array = tagSpecificCopiers.Array, object = tagSpecificCopiers.Object; | ||
function copier(value, state) { | ||
@@ -322,8 +402,3 @@ state.prototype = state.Constructor = undefined; | ||
function createStrictCopier(options) { | ||
return createCopier(Object.assign({ | ||
array: copyArrayStrict, | ||
map: copyMapStrict, | ||
object: copyObjectStrict, | ||
set: copySetStrict, | ||
}, options)); | ||
return createCopier(assign({}, DEFAULT_STRICT_OPTIONS, options)); | ||
} | ||
@@ -330,0 +405,0 @@ /** |
import type { Cache } from './utils'; | ||
export declare type InternalCopier<Value = any> = (value: Value, state: State) => Value; | ||
export declare type InternalCopier<Value> = (value: Value, state: State) => Value; | ||
export interface State { | ||
Constructor: any; | ||
cache: Cache; | ||
copier: InternalCopier; | ||
copier: InternalCopier<any>; | ||
prototype: any; | ||
} | ||
/** | ||
* Deeply copy the indexed values in the array. | ||
*/ | ||
export declare function copyArrayLoose(array: any[], state: State): any; | ||
/** | ||
* Deeply copy the indexed values in the array, as well as any custom properties. | ||
*/ | ||
export declare function copyArrayStrict<Value extends any[]>(array: Value, state: State): Value; | ||
/** | ||
* Copy the contents of the ArrayBuffer. | ||
*/ | ||
export declare function copyArrayBuffer<Value extends ArrayBuffer>(arrayBuffer: Value, _state: State): Value; | ||
/** | ||
* Create a new Blob with the contents of the original. | ||
*/ | ||
export declare function copyBlob<Value extends Blob>(blob: Value, _state: State): Value; | ||
/** | ||
* Create a new DataView with the contents of the original. | ||
*/ | ||
export declare function copyDataView<Value extends DataView>(dataView: Value, state: State): Value; | ||
/** | ||
* Create a new Date based on the time of the original. | ||
*/ | ||
export declare function copyDate<Value extends Date>(date: Value, state: State): Value; | ||
/** | ||
* Deeply copy the keys and values of the original. | ||
*/ | ||
export declare function copyMapLoose<Value extends Map<any, any>>(map: Value, state: State): Value; | ||
/** | ||
* Deeply copy the keys and values of the original, as well as any custom properties. | ||
*/ | ||
export declare function copyMapStrict<Value extends Map<any, any>>(map: Value, state: State): Value; | ||
declare function copyObjectLooseModern<Value extends {}>(object: Value, state: State): Value; | ||
declare function copyObjectLooseModern<Value extends Record<string, any>>(object: Value, state: State): Value; | ||
/** | ||
* Get a copy of the object based on loose rules, meaning all enumerable keys | ||
* and symbols are copied, but property descriptors are not considered. | ||
* Deeply copy the properties (keys and symbols) and values of the original. | ||
*/ | ||
export declare const copyObjectLoose: typeof copyObjectLooseModern; | ||
/** | ||
* Get a copy of the object based on strict rules, meaning all keys and symbols | ||
* are copied based on the original property descriptors. | ||
* Deeply copy the properties (keys and symbols) and values of the original, as well | ||
* as any hidden or non-enumerable properties. | ||
*/ | ||
export declare function copyObjectStrict<Value extends {}>(object: Value, state: State): Value; | ||
export declare function copyObjectStrict<Value extends Record<string, any>>(object: Value, state: State): Value; | ||
/** | ||
* Create a new primitive wrapper from the value of the original. | ||
*/ | ||
export declare function copyPrimitiveWrapper<Value extends Boolean | Number | String>(primitiveObject: Value, state: State): Value; | ||
/** | ||
* Create a new RegExp based on the value and flags of the original. | ||
*/ | ||
export declare function copyRegExp<Value extends RegExp>(regExp: Value, state: State): Value; | ||
/** | ||
* Return the original value (an identity function). | ||
* | ||
* @note | ||
* THis is used for objects that cannot be copied, such as WeakMap. | ||
*/ | ||
export declare function copySelf<Value>(value: Value, _state: State): Value; | ||
/** | ||
* Deeply copy the values of the original. | ||
*/ | ||
export declare function copySetLoose<Value extends Set<any>>(set: Value, state: State): Value; | ||
/** | ||
* Deeply copy the values of the original, as well as any custom properties. | ||
*/ | ||
export declare function copySetStrict<Value extends Set<any>>(set: Value, state: State): Value; | ||
export {}; |
export interface Cache { | ||
_keys?: any[]; | ||
_values?: any[]; | ||
has: (value: any) => boolean; | ||
@@ -22,7 +20,7 @@ set: (key: any, value: any) => void; | ||
export declare const getRegExpFlags: typeof getRegExpFlagsModern; | ||
declare function getTagModern(value: any): string; | ||
declare function getTagLegacy(value: any): string; | ||
/** | ||
* Get the tag of the value passed, so that the correct copier can be used. | ||
*/ | ||
export declare const getTag: typeof getTagModern; | ||
export declare const getTag: typeof getTagLegacy; | ||
export {}; |
@@ -21,3 +21,3 @@ interface Cache { | ||
type InternalCopier<Value = any> = (value: Value, state: State) => Value; | ||
type InternalCopier<Value> = (value: Value, state: State) => Value; | ||
@@ -27,3 +27,3 @@ export interface State { | ||
cache: Cache; | ||
copier: InternalCopier; | ||
copier: InternalCopier<any>; | ||
prototype: any; | ||
@@ -30,0 +30,0 @@ } |
@@ -88,3 +88,3 @@ { | ||
"dist": "npm run clean && npm run build", | ||
"lint": "eslint 'src/*.ts'", | ||
"lint": "eslint 'src/*.ts' '__tests__/*.ts' 'DEV_ONLY/*.ts'", | ||
"lint:fix": "npm run lint -- --fix", | ||
@@ -99,7 +99,7 @@ "prepublishOnly": "npm run lint && npm run typecheck && npm run test && npm run dist", | ||
"test:watch": "npm run test -- --watch", | ||
"typecheck": "tsc src/*.ts --noEmit" | ||
"typecheck": "tsc --noEmit" | ||
}, | ||
"type": "module", | ||
"types": "index.d.ts", | ||
"version": "3.0.0-beta.7" | ||
"version": "3.0.0-beta.8" | ||
} |
166
README.md
@@ -18,2 +18,6 @@ # fast-copy | ||
- [`createCopier`](#createcopier) | ||
- [Copier state](#copier-state) | ||
- [`cache`](#cache) | ||
- [`copier`](#copier) | ||
- [`Constructor` / `prototype`](#constructor--prototype) | ||
- [`createStrictCopier`](#createstrictcopier) | ||
@@ -102,2 +106,89 @@ - [Copier methods](#copier-methods) | ||
Each internal copier method has the following contract: | ||
```ts | ||
type InternalCopier<Value> = (value: Value, state: State) => Value; | ||
interface State { | ||
Constructor: any; | ||
cache: WeakMap; | ||
copier: InternalCopier<any>; | ||
prototype: any; | ||
} | ||
``` | ||
Any method overriding the defaults must maintain this contract. | ||
#### Copier state | ||
##### `cache` | ||
If you want to maintain circular reference handling, then you'll need the methods to handle cache population for future lookups: | ||
```ts | ||
function shallowlyCloneArray<Value extends any[]>( | ||
value: Value, | ||
state: State | ||
): Value { | ||
const clone = [...value]; | ||
state.cache.set(value, clone); | ||
return clone; | ||
} | ||
``` | ||
##### `copier` | ||
`copier` is provided for recursive calls with deeply-nested objects. | ||
```ts | ||
function deeplyCloneArray<Value extends any[]>( | ||
value: Value, | ||
state: State | ||
): Value { | ||
const clone = []; | ||
state.cache.set(value, clone); | ||
value.forEach((item) => state.copier(item, state)); | ||
return clone; | ||
} | ||
``` | ||
Note above I am using `forEach` instead of a simple `map`. This is because it is highly recommended to store the clone in [`cache`](#cache) eagerly when deeply copying, so that nested circular references are handled correctly. | ||
##### `Constructor` / `prototype` | ||
Both `Constructor` and `prototype` properties are only populated with complex objects that are not standard objects or arrays. This is mainly useful for custom subclasses of these globals, or maintaining custom prototypes of objects. | ||
```ts | ||
function deeplyCloneSubclassArray<Value extends CustomArray>( | ||
value: Value, | ||
state: State | ||
): Value { | ||
const clone = new state.Constructor(); | ||
state.cache.set(value, clone); | ||
value.forEach((item) => clone.push(item)); | ||
return clone; | ||
} | ||
function deeplyCloneCustomObject<Value extends CustomObject>( | ||
value: Value, | ||
state: State | ||
): Value { | ||
const clone = Object.create(state.prototype); | ||
state.cache.set(value, clone); | ||
Object.entries(value).forEach(([k, v]) => (clone[k] = v)); | ||
return clone; | ||
} | ||
``` | ||
### `createStrictCopier` | ||
@@ -211,9 +302,9 @@ | ||
| ------------------ | ------------------- | | ||
| **fast-copy** | **5,743,509** | | ||
| lodash.cloneDeep | 2,614,035 | | ||
| clone | 2,173,098 | | ||
| fast-clone | 1,341,313 | | ||
| deepclone | 1,238,167 | | ||
| ramda | 1,115,519 | | ||
| fast-copy (strict) | 845,093 | | ||
| **fast-copy** | **5,880,312** | | ||
| lodash.cloneDeep | 2,706,261 | | ||
| clone | 2,207,231 | | ||
| deepclone | 1,274,810 | | ||
| fast-clone | 1,239,952 | | ||
| ramda | 1,146,152 | | ||
| fast-copy (strict) | 852,382 | | ||
@@ -226,9 +317,9 @@ #### Complex objects | ||
| ------------------ | ------------------- | | ||
| **fast-copy** | **160,060** | | ||
| ramda | 134,873 | | ||
| deepclone | 131,345 | | ||
| fast-clone | 49,911 | | ||
| clone | 75,780 | | ||
| fast-copy (strict) | 61,556 | | ||
| lodash.cloneDeep | 59,493 | | ||
| **fast-copy** | **162,858** | | ||
| ramda | 142,104 | | ||
| deepclone | 133,607 | | ||
| fast-clone | 101,143 | | ||
| clone | 70,872 | | ||
| fast-copy (strict) | 62,961 | | ||
| lodash.cloneDeep | 62,060 | | ||
@@ -241,8 +332,8 @@ #### Big data | ||
| ------------------ | ------------------- | | ||
| **fast-copy** | 304 | | ||
| fast-clone | 236 | | ||
| **fast-copy** | 303 | | ||
| fast-clone | 245 | | ||
| deepclone | 151 | | ||
| lodash.cloneDeep | 150 | | ||
| deepclone | 148 | | ||
| clone | 90 | | ||
| fast-copy (strict) | 89 | | ||
| clone | 93 | | ||
| fast-copy (strict) | 90 | | ||
| ramda | 42 | | ||
@@ -256,8 +347,8 @@ | ||
| ------------------ | ------------------- | | ||
| **fast-copy** | **2,273,405** | | ||
| deepclone | 1,299,928 | | ||
| ramda | 951,721 | | ||
| clone | 945,585 | | ||
| lodash.cloneDeep | 887,775 | | ||
| fast-copy (strict) | 630,221 | | ||
| **fast-copy** | **2,420,466** | | ||
| deepclone | 1,386,896 | | ||
| ramda | 1,024,108 | | ||
| lodash.cloneDeep | 989,796 | | ||
| clone | 987,721 | | ||
| fast-copy (strict) | 617,602 | | ||
| fast-clone | 0 (not supported) | | ||
@@ -271,9 +362,9 @@ | ||
| ------------------ | ------------------- | | ||
| **fast-copy** | **144,616** | | ||
| clone | 68,880 | | ||
| fast-clone | 66,233 | | ||
| lodash.cloneDeep | 63,376 | | ||
| ramda | 52,216 | | ||
| deepclone | 28,394 | | ||
| fast-copy (strict) | 21,033 | | ||
| **fast-copy** | **152,792** | | ||
| clone | 74,347 | | ||
| fast-clone | 66,576 | | ||
| lodash.cloneDeep | 64,760 | | ||
| ramda | 53,542 | | ||
| deepclone | 28,823 | | ||
| fast-copy (strict) | 21,362 | | ||
@@ -285,8 +376,10 @@ ## Development | ||
- benchmark => run benchmark tests against other equality libraries | ||
- build => run `build:files` and `build:types` | ||
- build:files => build dist files with `rollup` | ||
- build:types => build TypeScript types for consumers | ||
- build => run `build:esm`, `build:cjs`, `build:umd`, and `build:min` scripts | ||
- build:cjs => build CJS files and types | ||
- build:esm => build ESM files and types | ||
- build:min => build minified files and types | ||
- build:umd => build UMD files and types | ||
- clean => run `rimraf` on the `dist` folder | ||
- dev => start webpack playground App | ||
- dist => run `build` and `build:minified` scripts | ||
- dist => run `clean` and `build` scripts | ||
- lint => run ESLint on all files in `src` folder (also runs on `dev` script) | ||
@@ -302,1 +395,2 @@ - lint:fix => run `lint` script, but with auto-fixer | ||
- test:watch => run same script as `test` but keep persistent watcher | ||
- typecheck => run `tsc` on the codebase |
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
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
195299
1951
388