Skip to content

Commit

Permalink
fix(utilities): added support for unwrapping reactives during clone
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewcourtice committed Aug 18, 2021
1 parent 04dcc0d commit e77ee3f
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 17 deletions.
25 changes: 18 additions & 7 deletions packages/utilities/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,18 @@
"author": "Andrew Courtice <[email protected]>",
"description": "Harlem utilities package",
"homepage": "https://harlemjs.com",
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"exports": "./dist/index.js",
"unpkg": "./dist/index.global.js",
"types": "./dist/index.d.ts",
"source": "./src/index.ts",
"source": "src/index.ts",
"main": "dist/index.js",
"module": "dist/esm/index.js",
"unpkg": "dist/iife/index.js",
"jsdelivr": "dist/iife/index.js",
"types": "dist/index.d.ts",
"exports": {
".": {
"import": "./dist/esm/index.js",
"require": "./dist/index.js"
}
},
"keywords": [
"vue",
"state",
Expand All @@ -31,5 +36,11 @@
"dev": "tsup --watch src",
"build": "tsup",
"prepublish": "yarn build"
},
"peerDependencies": {
"vue": "^3.2.0"
},
"devDependencies": {
"vue": "^3.2.0"
}
}
37 changes: 27 additions & 10 deletions packages/utilities/src/object/clone.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import getType from '../type/get-type';

import {
unref,
UnwrapRef
} from 'vue';

import type {
Constructable,
RuntimeType,
Expand All @@ -13,6 +18,13 @@ function cloneBasic(input: Constructable): unknown {
return new input.constructor(input);
}

function cloneRegex(input: RegExp): RegExp {
const clonedRegex = new RegExp(input.source);
clonedRegex.lastIndex = input.lastIndex;

return clonedRegex;
}

function cloneSymbol(input: symbol): symbol {
return Object(Symbol.prototype.valueOf.call(input));
}
Expand Down Expand Up @@ -52,15 +64,19 @@ function cloneMap(input: Map<unknown, unknown>): Map<unknown, unknown> {
}

const CLONE_MAP = {
default: () => null,
null: () => null,
undefined: () => null,
boolean: cloneBasic,
number: cloneBasic,
string: cloneBasic,
default: cloneIdentity,

// Primitives
null: cloneIdentity,
undefined: cloneIdentity,
boolean: cloneBasic, // only for new Boolean()
number: cloneBasic, // only for new Number()
string: cloneBasic, // only for new String()

// Objects
error: cloneBasic,
date: cloneBasic,
regexp: cloneBasic,
regexp: cloneRegex,
function: cloneIdentity,
symbol: cloneSymbol,
array: cloneArray,
Expand All @@ -69,13 +85,14 @@ const CLONE_MAP = {
set: cloneSet,
} as Record<RuntimeType | 'default', ((value: unknown) => unknown)>;

export default function clone<TValue = unknown>(value: TValue): TValue {
export default function clone<TValue = unknown>(value: TValue): UnwrapRef<TValue> {
if (typeof value !== 'object' || value === null) {
return value;
return value as UnwrapRef<TValue>;
}

const type = getType(value);
const cloner = CLONE_MAP[type] || CLONE_MAP.default;
const input = unref(value);

return cloner(value) as TValue;
return cloner(input) as UnwrapRef<TValue>;
}
27 changes: 27 additions & 0 deletions packages/utilities/test/clone.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import clone from '../src/object/clone';

import {
isReactive,
isRef,
reactive,
ref,
} from 'vue';

function getSimpleTypes(): Record<string, unknown> {
return {
num: 1,
und: undefined,
str: 'hello world',
func1: () => console.log('test'),
func2: function (a: number, b: number) {
return a + b;
Expand Down Expand Up @@ -58,6 +66,25 @@ describe('Utilities', () => {
}
});


test('Should unwrap reactive objects', () => {
const source = {
a: ref(4),
b: ref([1, 2, 3]),
c: {
d: reactive({
e: 1,
}),
},
};

const copy = clone(source);

expect(isRef(copy.a)).toBe(false);
expect(isRef(copy.b)).toBe(false);
expect(isReactive(copy.c.d)).toBe(false);
});

});

});

0 comments on commit e77ee3f

Please sign in to comment.