Skip to content

Commit

Permalink
V3 (#74)
Browse files Browse the repository at this point in the history
* initial setup

* fix webpack setup

* fix benchmark

* use named instead of default exports

* update CHANGELOG

* Release 3.0.0-beta.0

* Update README.md

Co-authored-by: Matteo Pietro Dazzi <matteopietro.dazzi@gmail.com>

* remove default export accidentally left in

* update types setup to include UMD and minified output

* Release 3.0.0-beta.1

* update CHANGELOG with better description of breaking changes

* update benchmark with named exports

* code golf for minified output

* scope variables to avoid unnecessary allocations

* fix DEV app and wording of `copyStrict` documentation

* Release 3.0.0-beta.2

* eliminate `realm` in favor of object class

* unify and simplify implementation

* remove options entirely

* reduce code size

* update documentation

* pass prototype through for clean clones, for faster object copying

* Release 3.0.0-beta.3

* code cleanup, and optimize for runtime speed on object clones

* split out copiers from utils, and use more defined copiers for JIT optimizations

* code cleanup and better circular management for maps / sets

* remove unnecessary caching of `DataView` / `ArrayBuffer` values

* better colocation of `createCopier`

* restore default export for easier migration (CJS is only impacted consumer now)

* Release 3.0.0-beta.4

* surface `createCopier` as public API

* store object-specific copiers in closure

* remove local variable reference

* Release 3.0.0-beta.5

* update dependencies

* cleanup of rollup / tsconfig infrastructure

* add custom transformer for errors

* avoid use of global `toString`

* use `toStringTag` when available

* reuse `copyArrayBuffer` for `copyDataView`, to ensure custom logic is consistent

* update benchmarks

* Release 3.0.0-beta.6

* change min output file to just `index.js` since it is already scoped in folder

* improve strictness of Map / Set

* Release 3.0.0-beta.7

* update README

* avoid local variable use

* make `_keys` and `_values` private and not part of expected `Cache` contract

* lean into `assign` for runtime merging of options

* types and documentation cleanup

* improve JSDoc for copiers

* improve linting setup

* add formal support for primitive wrappers

* remove unnecessary types

* Release 3.0.0-beta.8

* clarify verbiage in README, and add blurb about copying generators

* update dependencies to latest

* cleanup of README

Co-authored-by: Matteo Pietro Dazzi <matteopietro.dazzi@gmail.com>
  • Loading branch information
planttheidea and ilteoood committed Oct 3, 2022
1 parent 7a4d7e6 commit dae3321
Show file tree
Hide file tree
Showing 31 changed files with 2,238 additions and 2,175 deletions.
6 changes: 5 additions & 1 deletion .eslintrc
@@ -1,4 +1,5 @@
{
"extends": ["plugin:@typescript-eslint/recommended"],
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint"],
"settings": {
Expand All @@ -8,5 +9,8 @@
}
}
},
"rules": {}
"rules": {
"@typescript-eslint/no-explicit-any": 0,
"@typescript-eslint/no-unused-vars": 0
}
}
15 changes: 15 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,20 @@
# fast-copy CHANGELOG

## 3.0.0

**Breaking changes**

- Exports are now always named, so if using CJS the `.default` suffix is required, e.g. `require('fast-copy').default`
- `copy.strict` is no longer available; it is now available as the explicit `copyStrict` named import
- Options have been removed
- `isStrict` option has been replaced with importing the separate `copyStrict` method
- `realm` has been removed entirely, as `instanceof` is no longer used internally

**Enhancements**

- Can now create a custom copier, allowing maximum performance for specific use-cases
- Correctly handle primitive wrappers, e.g. `new String('foo')`

## 2.1.7

- Republish of [`2.1.6`](#216), as the release process failed mid-publish
Expand Down
67 changes: 60 additions & 7 deletions DEV_ONLY/App.ts
@@ -1,7 +1,7 @@
import React from 'react';
import cloneDeep from 'lodash/cloneDeep';

import src from '../src';
import copy, { copyStrict, createCopier, createStrictCopier } from '../src';

// import '../benchmarks';

Expand All @@ -19,12 +19,15 @@ class Foo {

const object: PlainObject = {
arguments: (function (foo, bar, baz) {
// Specifically testing arguments object
// eslint-disable-next-line prefer-rest-params
return arguments;
})('foo', 'bar', 'baz'),
array: ['foo', { bar: 'baz' }],
arrayBuffer: new ArrayBuffer(8),
blob: new Blob(['<a id="a">hey!</a>'], {type : 'text/html'}),
blob: new Blob(['<a id="a">hey!</a>'], { type: 'text/html' }),
boolean: true,
booleanConstructor: new Boolean(true),
customPrototype: Object.create({
method() {
return 'foo';
Expand All @@ -43,10 +46,18 @@ const object: PlainObject = {
return 'foo';
},
foo: new Foo('value'),
map: new Map().set('foo', { bar: 'baz' }),
map: (() => {
const map = new Map().set('foo', { bar: 'baz' });

// @ts-expect-error - Testing non-standard property on map.
map.foo = 'bar';

return map;
})(),
nan: NaN,
nil: null,
number: 123,
numberConstructor: new Number('123'),
object: { foo: { bar: 'baz' } },
promise: Promise.resolve('foo'),
react: React.createElement('main', {
Expand Down Expand Up @@ -74,10 +85,14 @@ const object: PlainObject = {
regexp: /foo/gi,
set: new Set().add('foo').add({ bar: 'baz' }),
string: 'foo',
stringConstructor: new String('foo'),
symbol: Symbol('foo'),
typedArray: new Uint8Array([12, 15]),
undef: undefined,
weakmap: new WeakMap([[{}, 'foo'], [{}, 'bar']]),
weakmap: new WeakMap([
[{}, 'foo'],
[{}, 'bar'],
]),
weakset: new WeakSet([{}, {}]),
[Symbol('key')]: 'value',
};
Expand Down Expand Up @@ -105,7 +120,45 @@ Object.defineProperty(object.object, 'readonly', {

object.deeply.nested.reference = object;

const cloned = src(object);
const copyShallow = createCopier({
array: (array) => [...array],
map: (map) => new Map(map.entries()),
object: (object) => ({ ...object }),
set: (set) => new Set(set.values()),
});

const copyOwnProperties = (value, clone) =>
Object.getOwnPropertyNames(value).reduce(
(clone, property) =>
Object.defineProperty(
clone,
property,
Object.getOwnPropertyDescriptor(value, property) || {
configurable: true,
enumerable: true,
value: clone[property],
writable: true,
}
),
clone
);

const copyStrictShallow = createStrictCopier({
array: (array) => copyOwnProperties(array, []),
map: (map) => copyOwnProperties(map, new Map(map.entries())),
object: (object) => copyOwnProperties(object, {}),
set: (set) => copyOwnProperties(set, new Set(set.values())),
});

console.group('fast-copy');
console.log('original', object);
console.log('copy', copy(object));
console.log('copyStrict', copyStrict(object));
console.log('copyShallow', copyShallow(object));
console.log('copyStrictShallow', copyStrictShallow(object));
console.groupEnd();

console.log(cloned);
console.log(cloneDeep(object));
console.group('lodash.cloneDeep');
console.log('original', object);
console.log('copy', cloneDeep(object));
console.groupEnd();

0 comments on commit dae3321

Please sign in to comment.