Skip to content

Commit

Permalink
fix(cloneDeep): Do not clone uncloneable objects
Browse files Browse the repository at this point in the history
  • Loading branch information
raon0211 committed Jan 29, 2025
1 parent b7c0972 commit 3aba4da
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 3 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@
"eslint-plugin-vue": "^9.28.0",
"execa": "^9.3.0",
"globals": "^15.9.0",
"happy-dom": "^16.7.3",
"jscodeshift": "^17.0.0",
"prettier": "^3.2.5",
"prettier-plugin-sort-re-exports": "^0.1.0",
Expand Down Expand Up @@ -205,4 +206,4 @@
"format": "prettier --write .",
"transform": "jscodeshift -t ./.scripts/tests/transform-lodash-test.ts $0 && prettier --write $0"
}
}
}
18 changes: 18 additions & 0 deletions src/object/cloneDeep.dom.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* @vitest-environment happy-dom
*/
import { describe, expect, it } from 'vitest';
import { cloneDeep } from './cloneDeep';

describe('cloneDeep', () => {
it('should not clone uncloneable objects like `HTMLElement`s', () => {
const element = document.createElement('div');
element.textContent = 'Hello, World!';

const clonedElement = cloneDeep(element);

expect(clonedElement).toBe(element);
expect(clonedElement.nodeType).toBe(element.nodeType);
expect(clonedElement.textContent).toBe('Hello, World!');
});
});
4 changes: 3 additions & 1 deletion src/object/cloneDeep.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,9 @@ describe('cloneDeep', () => {
it('should clone File objects', () => {
// For legacy NodeJS support
if (typeof File !== 'undefined') {
const file = new File(['es-toolkit'], 'es-toolkit.txt', { type: 'text/plain' });
const file = new File(['es-toolkit'], 'es-toolkit.txt', {
type: 'text/plain',
});
const clonedFile = cloneDeep(file);
expect(clonedFile).not.toBe(file);
expect(clonedFile.name).toBe(file.name);
Expand Down
59 changes: 58 additions & 1 deletion src/object/cloneDeepWith.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,29 @@
import { getSymbols } from '../compat/_internal/getSymbols.ts';
import { getTag } from '../compat/_internal/getTag.ts';
import {
argumentsTag,
arrayBufferTag,
arrayTag,
booleanTag,
dataViewTag,
dateTag,
float32ArrayTag,
float64ArrayTag,
int8ArrayTag,
int16ArrayTag,
int32ArrayTag,
mapTag,
numberTag,
objectTag,
regexpTag,
setTag,
stringTag,
symbolTag,
uint8ArrayTag,
uint8ClampedArrayTag,
uint16ArrayTag,
uint32ArrayTag,
} from '../compat/_internal/tags.ts';
import { isPrimitive } from '../predicate/isPrimitive.ts';
import { isTypedArray } from '../predicate/isTypedArray.ts';

Expand Down Expand Up @@ -197,7 +222,7 @@ export function cloneDeepWithImpl<T>(
return result as T;
}

if (typeof valueToClone === 'object' && valueToClone !== null) {
if (typeof valueToClone === 'object' && isCloneableObject(valueToClone)) {
const result = Object.create(Object.getPrototypeOf(valueToClone));

stack.set(valueToClone, result);
Expand Down Expand Up @@ -228,3 +253,35 @@ export function copyProperties<T>(
}
}
}

function isCloneableObject(object: object) {
switch (getTag(object)) {
case argumentsTag:
case arrayTag:
case arrayBufferTag:
case dataViewTag:
case booleanTag:
case dateTag:
case float32ArrayTag:
case float64ArrayTag:
case int8ArrayTag:
case int16ArrayTag:
case int32ArrayTag:
case mapTag:
case numberTag:
case objectTag:
case regexpTag:
case setTag:
case stringTag:
case symbolTag:
case uint8ArrayTag:
case uint8ClampedArrayTag:
case uint16ArrayTag:
case uint32ArrayTag: {
return true;
}
default: {
return false;
}
}
}
25 changes: 25 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4511,6 +4511,7 @@ __metadata:
eslint-plugin-vue: "npm:^9.28.0"
execa: "npm:^9.3.0"
globals: "npm:^15.9.0"
happy-dom: "npm:^16.7.3"
jscodeshift: "npm:^17.0.0"
prettier: "npm:^3.2.5"
prettier-plugin-sort-re-exports: "npm:^0.1.0"
Expand Down Expand Up @@ -5623,6 +5624,16 @@ __metadata:
languageName: node
linkType: hard

"happy-dom@npm:^16.7.3":
version: 16.7.3
resolution: "happy-dom@npm:16.7.3"
dependencies:
webidl-conversions: "npm:^7.0.0"
whatwg-mimetype: "npm:^3.0.0"
checksum: 10c0/94497b686a545a3995646d85198456d7b1e0a9ef0785124e0c0bdd7b5feeb9b61b366cdcc22f880effbb0a5924405eadca56ac8d43f2d81450803d48d2fecf61
languageName: node
linkType: hard

"har-schema@npm:^2.0.0":
version: 2.0.0
resolution: "har-schema@npm:2.0.0"
Expand Down Expand Up @@ -9641,6 +9652,20 @@ __metadata:
languageName: node
linkType: hard

"webidl-conversions@npm:^7.0.0":
version: 7.0.0
resolution: "webidl-conversions@npm:7.0.0"
checksum: 10c0/228d8cb6d270c23b0720cb2d95c579202db3aaf8f633b4e9dd94ec2000a04e7e6e43b76a94509cdb30479bd00ae253ab2371a2da9f81446cc313f89a4213a2c4
languageName: node
linkType: hard

"whatwg-mimetype@npm:^3.0.0":
version: 3.0.0
resolution: "whatwg-mimetype@npm:3.0.0"
checksum: 10c0/323895a1cda29a5fb0b9ca82831d2c316309fede0365047c4c323073e3239067a304a09a1f4b123b9532641ab604203f33a1403b5ca6a62ef405bcd7a204080f
languageName: node
linkType: hard

"whatwg-url@npm:^5.0.0":
version: 5.0.0
resolution: "whatwg-url@npm:5.0.0"
Expand Down

0 comments on commit 3aba4da

Please sign in to comment.