bunshin-clone 1.0.7 → 1.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -12
- package/dist/index.cjs +40 -22
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +40 -22
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,14 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
High-performance deep clone utility with descriptor support. Supports circular references and complex built-in types.
|
|
4
4
|
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
5
|
+
* Fast (no unnecessary overhead)
|
|
6
|
+
* Deep clone (no structural sharing)
|
|
7
|
+
* Supports circular ref
|
|
8
|
+
* Handles Map, Set, Array, TypedArray, Date, RegExp, etc.
|
|
9
|
+
* Optional descriptor preservation
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm i bunshin-clone
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
// npm
|
|
21
|
+
import bunshinClone from 'bunshin-clone';
|
|
22
|
+
|
|
23
|
+
// CDN
|
|
24
|
+
import bunshinClone from 'https://cdn.jsdelivr.net/npm/bunshin-clone/+esm';
|
|
25
|
+
```
|
|
26
|
+
|
|
13
27
|
## Usage
|
|
14
28
|
|
|
15
29
|
```ts
|
|
@@ -36,15 +50,15 @@ bunshinClone(target, options)
|
|
|
36
50
|
## Options
|
|
37
51
|
|
|
38
52
|
```ts
|
|
39
|
-
|
|
40
|
-
preserveDescriptors
|
|
41
|
-
strictDescriptors
|
|
53
|
+
BunshinCloneOptions {
|
|
54
|
+
preserveDescriptors: false;
|
|
55
|
+
strictDescriptors: false;
|
|
42
56
|
}
|
|
43
57
|
```
|
|
44
58
|
|
|
45
|
-
|
|
59
|
+
**preserveDescriptors**
|
|
46
60
|
|
|
47
|
-
* `false
|
|
61
|
+
* `false`: use standard merge (faster, ignores property descriptors)
|
|
48
62
|
* `true`: preserve property descriptors (getters/setters, etc.)
|
|
49
63
|
|
|
50
64
|
<details>
|
|
@@ -64,9 +78,9 @@ Object.getOwnPropertyDescriptor(result, 'x')?.get;
|
|
|
64
78
|
```
|
|
65
79
|
</details>
|
|
66
80
|
|
|
67
|
-
|
|
81
|
+
**strictDescriptors**
|
|
68
82
|
|
|
69
|
-
* `false
|
|
83
|
+
* `false`: skip incompatible descriptors
|
|
70
84
|
* `true`: throw if descriptor cannot be merged (e.g. non-configurable or non-writable)
|
|
71
85
|
|
|
72
86
|
<details>
|
|
@@ -80,6 +94,8 @@ bunshinClone(obj, { strictDescriptors: true });
|
|
|
80
94
|
```
|
|
81
95
|
</details>
|
|
82
96
|
|
|
97
|
+
---
|
|
98
|
+
|
|
83
99
|
## Supported Types
|
|
84
100
|
|
|
85
101
|
bunshin-clone correctly handles:
|
package/dist/index.cjs
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
var EMPTY_OPTIONS = {};
|
|
5
5
|
var { hasOwnProperty: HAS_OWN } = Object.prototype;
|
|
6
|
-
var { toString: OBJECT_TO_STRING } = Object.prototype;
|
|
7
6
|
function bunshinClone(source, options) {
|
|
8
7
|
return clone(source, options ?? EMPTY_OPTIONS, /* @__PURE__ */ new WeakMap());
|
|
9
8
|
}
|
|
@@ -85,9 +84,7 @@ function clone(node, options, ref) {
|
|
|
85
84
|
}
|
|
86
85
|
}
|
|
87
86
|
if (node instanceof Error || typeof DOMException !== "undefined" && node instanceof DOMException) {
|
|
88
|
-
|
|
89
|
-
ref.set(node, result);
|
|
90
|
-
return result;
|
|
87
|
+
return cloneError(node, options, ref);
|
|
91
88
|
}
|
|
92
89
|
if (typeof Blob !== "undefined" && node instanceof Blob) {
|
|
93
90
|
const result = node.slice(0, node.size, node.type);
|
|
@@ -120,10 +117,18 @@ function clone(node, options, ref) {
|
|
|
120
117
|
return node;
|
|
121
118
|
}
|
|
122
119
|
function cloneError(value, options, ref) {
|
|
120
|
+
if (value instanceof DOMException) {
|
|
121
|
+
const result2 = new DOMException(value.message, value.name);
|
|
122
|
+
ref.set(value, result2);
|
|
123
|
+
return result2;
|
|
124
|
+
}
|
|
123
125
|
const name = value.name || "Error";
|
|
124
126
|
const message = value.message || "";
|
|
125
127
|
let result;
|
|
126
128
|
switch (name) {
|
|
129
|
+
case "EvalError":
|
|
130
|
+
result = new EvalError(message);
|
|
131
|
+
break;
|
|
127
132
|
case "RangeError":
|
|
128
133
|
result = new RangeError(message);
|
|
129
134
|
break;
|
|
@@ -136,36 +141,32 @@ function cloneError(value, options, ref) {
|
|
|
136
141
|
case "TypeError":
|
|
137
142
|
result = new TypeError(message);
|
|
138
143
|
break;
|
|
144
|
+
case "URIError":
|
|
145
|
+
result = new URIError(message);
|
|
146
|
+
break;
|
|
139
147
|
default:
|
|
140
148
|
result = new Error(message);
|
|
141
149
|
result.name = name;
|
|
142
150
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
result.cause = clone(cause, options, ref);
|
|
147
|
-
}
|
|
151
|
+
ref.set(value, result);
|
|
152
|
+
if ("cause" in value && value.cause !== void 0) {
|
|
153
|
+
result.cause = clone(value.cause, options, ref);
|
|
148
154
|
}
|
|
149
155
|
if (value.stack) {
|
|
150
156
|
result.stack = value.stack;
|
|
151
157
|
}
|
|
152
|
-
for (const key of Object.keys(value)) {
|
|
153
|
-
if (key === "name" || key === "message" || key === "stack") {
|
|
154
|
-
continue;
|
|
155
|
-
}
|
|
156
|
-
result[key] = value[key];
|
|
157
|
-
}
|
|
158
158
|
return result;
|
|
159
159
|
}
|
|
160
160
|
function cloneWithDescriptors(node, options, ref) {
|
|
161
161
|
const result = Object.create(Object.getPrototypeOf(node));
|
|
162
162
|
ref.set(node, result);
|
|
163
163
|
const descs = Object.getOwnPropertyDescriptors(node);
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
164
|
+
forEachOwnKey(descs, (key) => {
|
|
165
|
+
if (!key) {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
167
168
|
if (isUnsafeKey(key)) {
|
|
168
|
-
|
|
169
|
+
return;
|
|
169
170
|
}
|
|
170
171
|
const desc = { ...descs[key] };
|
|
171
172
|
if ("value" in desc) {
|
|
@@ -178,14 +179,31 @@ function cloneWithDescriptors(node, options, ref) {
|
|
|
178
179
|
throw error;
|
|
179
180
|
}
|
|
180
181
|
}
|
|
181
|
-
}
|
|
182
|
+
});
|
|
182
183
|
return result;
|
|
183
184
|
}
|
|
185
|
+
function forEachOwnKey(object, callback) {
|
|
186
|
+
for (const key of Object.keys(object)) {
|
|
187
|
+
callback(key);
|
|
188
|
+
}
|
|
189
|
+
const symbols = Object.getOwnPropertySymbols(object);
|
|
190
|
+
for (let i = 0, l = symbols.length; i < l; i++) {
|
|
191
|
+
const symbol = symbols[i];
|
|
192
|
+
if (!symbol) {
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
callback(symbol);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
184
198
|
function isObject(value) {
|
|
185
199
|
return typeof value === "object" && value !== null;
|
|
186
200
|
}
|
|
187
201
|
function isPlainObject(value) {
|
|
188
|
-
|
|
202
|
+
if (value === null || typeof value !== "object") {
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
const proto = Object.getPrototypeOf(value);
|
|
206
|
+
return proto === Object.prototype || proto === null;
|
|
189
207
|
}
|
|
190
208
|
function isUnsafeKey(key) {
|
|
191
209
|
return typeof key === "string" && (key === "__proto__" || key === "prototype" || key === "constructor");
|
|
@@ -195,7 +213,7 @@ function isUnsafeKey(key) {
|
|
|
195
213
|
* High-performance deep clone utility with descriptor support.
|
|
196
214
|
* Supports circular ref and complex built-in types.
|
|
197
215
|
*
|
|
198
|
-
* @version 1.0.
|
|
216
|
+
* @version 1.0.9
|
|
199
217
|
* @author Yusuke Kamiyamane
|
|
200
218
|
* @license MIT
|
|
201
219
|
* @copyright Copyright (c) 2026 Yusuke Kamiyamane
|
package/dist/index.d.cts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
var EMPTY_OPTIONS = {};
|
|
3
3
|
var { hasOwnProperty: HAS_OWN } = Object.prototype;
|
|
4
|
-
var { toString: OBJECT_TO_STRING } = Object.prototype;
|
|
5
4
|
function bunshinClone(source, options) {
|
|
6
5
|
return clone(source, options ?? EMPTY_OPTIONS, /* @__PURE__ */ new WeakMap());
|
|
7
6
|
}
|
|
@@ -83,9 +82,7 @@ function clone(node, options, ref) {
|
|
|
83
82
|
}
|
|
84
83
|
}
|
|
85
84
|
if (node instanceof Error || typeof DOMException !== "undefined" && node instanceof DOMException) {
|
|
86
|
-
|
|
87
|
-
ref.set(node, result);
|
|
88
|
-
return result;
|
|
85
|
+
return cloneError(node, options, ref);
|
|
89
86
|
}
|
|
90
87
|
if (typeof Blob !== "undefined" && node instanceof Blob) {
|
|
91
88
|
const result = node.slice(0, node.size, node.type);
|
|
@@ -118,10 +115,18 @@ function clone(node, options, ref) {
|
|
|
118
115
|
return node;
|
|
119
116
|
}
|
|
120
117
|
function cloneError(value, options, ref) {
|
|
118
|
+
if (value instanceof DOMException) {
|
|
119
|
+
const result2 = new DOMException(value.message, value.name);
|
|
120
|
+
ref.set(value, result2);
|
|
121
|
+
return result2;
|
|
122
|
+
}
|
|
121
123
|
const name = value.name || "Error";
|
|
122
124
|
const message = value.message || "";
|
|
123
125
|
let result;
|
|
124
126
|
switch (name) {
|
|
127
|
+
case "EvalError":
|
|
128
|
+
result = new EvalError(message);
|
|
129
|
+
break;
|
|
125
130
|
case "RangeError":
|
|
126
131
|
result = new RangeError(message);
|
|
127
132
|
break;
|
|
@@ -134,36 +139,32 @@ function cloneError(value, options, ref) {
|
|
|
134
139
|
case "TypeError":
|
|
135
140
|
result = new TypeError(message);
|
|
136
141
|
break;
|
|
142
|
+
case "URIError":
|
|
143
|
+
result = new URIError(message);
|
|
144
|
+
break;
|
|
137
145
|
default:
|
|
138
146
|
result = new Error(message);
|
|
139
147
|
result.name = name;
|
|
140
148
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
result.cause = clone(cause, options, ref);
|
|
145
|
-
}
|
|
149
|
+
ref.set(value, result);
|
|
150
|
+
if ("cause" in value && value.cause !== void 0) {
|
|
151
|
+
result.cause = clone(value.cause, options, ref);
|
|
146
152
|
}
|
|
147
153
|
if (value.stack) {
|
|
148
154
|
result.stack = value.stack;
|
|
149
155
|
}
|
|
150
|
-
for (const key of Object.keys(value)) {
|
|
151
|
-
if (key === "name" || key === "message" || key === "stack") {
|
|
152
|
-
continue;
|
|
153
|
-
}
|
|
154
|
-
result[key] = value[key];
|
|
155
|
-
}
|
|
156
156
|
return result;
|
|
157
157
|
}
|
|
158
158
|
function cloneWithDescriptors(node, options, ref) {
|
|
159
159
|
const result = Object.create(Object.getPrototypeOf(node));
|
|
160
160
|
ref.set(node, result);
|
|
161
161
|
const descs = Object.getOwnPropertyDescriptors(node);
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
162
|
+
forEachOwnKey(descs, (key) => {
|
|
163
|
+
if (!key) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
165
166
|
if (isUnsafeKey(key)) {
|
|
166
|
-
|
|
167
|
+
return;
|
|
167
168
|
}
|
|
168
169
|
const desc = { ...descs[key] };
|
|
169
170
|
if ("value" in desc) {
|
|
@@ -176,14 +177,31 @@ function cloneWithDescriptors(node, options, ref) {
|
|
|
176
177
|
throw error;
|
|
177
178
|
}
|
|
178
179
|
}
|
|
179
|
-
}
|
|
180
|
+
});
|
|
180
181
|
return result;
|
|
181
182
|
}
|
|
183
|
+
function forEachOwnKey(object, callback) {
|
|
184
|
+
for (const key of Object.keys(object)) {
|
|
185
|
+
callback(key);
|
|
186
|
+
}
|
|
187
|
+
const symbols = Object.getOwnPropertySymbols(object);
|
|
188
|
+
for (let i = 0, l = symbols.length; i < l; i++) {
|
|
189
|
+
const symbol = symbols[i];
|
|
190
|
+
if (!symbol) {
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
callback(symbol);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
182
196
|
function isObject(value) {
|
|
183
197
|
return typeof value === "object" && value !== null;
|
|
184
198
|
}
|
|
185
199
|
function isPlainObject(value) {
|
|
186
|
-
|
|
200
|
+
if (value === null || typeof value !== "object") {
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
const proto = Object.getPrototypeOf(value);
|
|
204
|
+
return proto === Object.prototype || proto === null;
|
|
187
205
|
}
|
|
188
206
|
function isUnsafeKey(key) {
|
|
189
207
|
return typeof key === "string" && (key === "__proto__" || key === "prototype" || key === "constructor");
|
|
@@ -193,7 +211,7 @@ function isUnsafeKey(key) {
|
|
|
193
211
|
* High-performance deep clone utility with descriptor support.
|
|
194
212
|
* Supports circular ref and complex built-in types.
|
|
195
213
|
*
|
|
196
|
-
* @version 1.0.
|
|
214
|
+
* @version 1.0.9
|
|
197
215
|
* @author Yusuke Kamiyamane
|
|
198
216
|
* @license MIT
|
|
199
217
|
* @copyright Copyright (c) 2026 Yusuke Kamiyamane
|