bunshin-clone 1.0.6 → 1.0.8
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 +24 -18
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +24 -18
- 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
|
@@ -70,25 +70,22 @@ function clone(node, options, ref) {
|
|
|
70
70
|
return result;
|
|
71
71
|
}
|
|
72
72
|
if (ArrayBuffer.isView(node)) {
|
|
73
|
+
const { buffer, byteOffset, byteLength } = node;
|
|
73
74
|
if (node instanceof DataView) {
|
|
74
|
-
const result = new DataView(
|
|
75
|
-
node.buffer.slice(0),
|
|
76
|
-
node.byteOffset,
|
|
77
|
-
node.byteLength
|
|
78
|
-
);
|
|
75
|
+
const result = new DataView(buffer.slice(0), byteOffset, byteLength);
|
|
79
76
|
ref.set(node, result);
|
|
80
77
|
return result;
|
|
81
78
|
} else {
|
|
82
79
|
const Ctor = node.constructor;
|
|
83
|
-
const result = new Ctor(
|
|
80
|
+
const result = new Ctor(
|
|
81
|
+
buffer.slice(byteOffset, byteOffset + byteLength)
|
|
82
|
+
);
|
|
84
83
|
ref.set(node, result);
|
|
85
84
|
return result;
|
|
86
85
|
}
|
|
87
86
|
}
|
|
88
87
|
if (node instanceof Error || typeof DOMException !== "undefined" && node instanceof DOMException) {
|
|
89
|
-
|
|
90
|
-
ref.set(node, result);
|
|
91
|
-
return result;
|
|
88
|
+
return cloneError(node, options, ref);
|
|
92
89
|
}
|
|
93
90
|
if (typeof Blob !== "undefined" && node instanceof Blob) {
|
|
94
91
|
const result = node.slice(0, node.size, node.type);
|
|
@@ -121,10 +118,18 @@ function clone(node, options, ref) {
|
|
|
121
118
|
return node;
|
|
122
119
|
}
|
|
123
120
|
function cloneError(value, options, ref) {
|
|
121
|
+
if (value instanceof DOMException) {
|
|
122
|
+
const result2 = new DOMException(value.message, value.name);
|
|
123
|
+
ref.set(value, result2);
|
|
124
|
+
return result2;
|
|
125
|
+
}
|
|
124
126
|
const name = value.name || "Error";
|
|
125
127
|
const message = value.message || "";
|
|
126
128
|
let result;
|
|
127
129
|
switch (name) {
|
|
130
|
+
case "EvalError":
|
|
131
|
+
result = new EvalError(message);
|
|
132
|
+
break;
|
|
128
133
|
case "RangeError":
|
|
129
134
|
result = new RangeError(message);
|
|
130
135
|
break;
|
|
@@ -137,22 +142,20 @@ function cloneError(value, options, ref) {
|
|
|
137
142
|
case "TypeError":
|
|
138
143
|
result = new TypeError(message);
|
|
139
144
|
break;
|
|
145
|
+
case "URIError":
|
|
146
|
+
result = new URIError(message);
|
|
147
|
+
break;
|
|
140
148
|
default:
|
|
141
149
|
result = new Error(message);
|
|
142
150
|
result.name = name;
|
|
143
151
|
}
|
|
144
|
-
|
|
145
|
-
|
|
152
|
+
ref.set(value, result);
|
|
153
|
+
if ("cause" in value && value.cause !== void 0) {
|
|
154
|
+
result.cause = clone(value.cause, options, ref);
|
|
146
155
|
}
|
|
147
156
|
if (value.stack) {
|
|
148
157
|
result.stack = value.stack;
|
|
149
158
|
}
|
|
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
159
|
return result;
|
|
157
160
|
}
|
|
158
161
|
function cloneWithDescriptors(node, options, ref) {
|
|
@@ -162,6 +165,9 @@ function cloneWithDescriptors(node, options, ref) {
|
|
|
162
165
|
const keys = Reflect.ownKeys(descs);
|
|
163
166
|
for (let i = 0, l = keys.length; i < l; i++) {
|
|
164
167
|
const key = keys[i];
|
|
168
|
+
if (!key) {
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
165
171
|
if (isUnsafeKey(key)) {
|
|
166
172
|
continue;
|
|
167
173
|
}
|
|
@@ -193,7 +199,7 @@ function isUnsafeKey(key) {
|
|
|
193
199
|
* High-performance deep clone utility with descriptor support.
|
|
194
200
|
* Supports circular ref and complex built-in types.
|
|
195
201
|
*
|
|
196
|
-
* @version 1.0.
|
|
202
|
+
* @version 1.0.8
|
|
197
203
|
* @author Yusuke Kamiyamane
|
|
198
204
|
* @license MIT
|
|
199
205
|
* @copyright Copyright (c) 2026 Yusuke Kamiyamane
|
package/dist/index.d.cts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -68,25 +68,22 @@ function clone(node, options, ref) {
|
|
|
68
68
|
return result;
|
|
69
69
|
}
|
|
70
70
|
if (ArrayBuffer.isView(node)) {
|
|
71
|
+
const { buffer, byteOffset, byteLength } = node;
|
|
71
72
|
if (node instanceof DataView) {
|
|
72
|
-
const result = new DataView(
|
|
73
|
-
node.buffer.slice(0),
|
|
74
|
-
node.byteOffset,
|
|
75
|
-
node.byteLength
|
|
76
|
-
);
|
|
73
|
+
const result = new DataView(buffer.slice(0), byteOffset, byteLength);
|
|
77
74
|
ref.set(node, result);
|
|
78
75
|
return result;
|
|
79
76
|
} else {
|
|
80
77
|
const Ctor = node.constructor;
|
|
81
|
-
const result = new Ctor(
|
|
78
|
+
const result = new Ctor(
|
|
79
|
+
buffer.slice(byteOffset, byteOffset + byteLength)
|
|
80
|
+
);
|
|
82
81
|
ref.set(node, result);
|
|
83
82
|
return result;
|
|
84
83
|
}
|
|
85
84
|
}
|
|
86
85
|
if (node instanceof Error || typeof DOMException !== "undefined" && node instanceof DOMException) {
|
|
87
|
-
|
|
88
|
-
ref.set(node, result);
|
|
89
|
-
return result;
|
|
86
|
+
return cloneError(node, options, ref);
|
|
90
87
|
}
|
|
91
88
|
if (typeof Blob !== "undefined" && node instanceof Blob) {
|
|
92
89
|
const result = node.slice(0, node.size, node.type);
|
|
@@ -119,10 +116,18 @@ function clone(node, options, ref) {
|
|
|
119
116
|
return node;
|
|
120
117
|
}
|
|
121
118
|
function cloneError(value, options, ref) {
|
|
119
|
+
if (value instanceof DOMException) {
|
|
120
|
+
const result2 = new DOMException(value.message, value.name);
|
|
121
|
+
ref.set(value, result2);
|
|
122
|
+
return result2;
|
|
123
|
+
}
|
|
122
124
|
const name = value.name || "Error";
|
|
123
125
|
const message = value.message || "";
|
|
124
126
|
let result;
|
|
125
127
|
switch (name) {
|
|
128
|
+
case "EvalError":
|
|
129
|
+
result = new EvalError(message);
|
|
130
|
+
break;
|
|
126
131
|
case "RangeError":
|
|
127
132
|
result = new RangeError(message);
|
|
128
133
|
break;
|
|
@@ -135,22 +140,20 @@ function cloneError(value, options, ref) {
|
|
|
135
140
|
case "TypeError":
|
|
136
141
|
result = new TypeError(message);
|
|
137
142
|
break;
|
|
143
|
+
case "URIError":
|
|
144
|
+
result = new URIError(message);
|
|
145
|
+
break;
|
|
138
146
|
default:
|
|
139
147
|
result = new Error(message);
|
|
140
148
|
result.name = name;
|
|
141
149
|
}
|
|
142
|
-
|
|
143
|
-
|
|
150
|
+
ref.set(value, result);
|
|
151
|
+
if ("cause" in value && value.cause !== void 0) {
|
|
152
|
+
result.cause = clone(value.cause, options, ref);
|
|
144
153
|
}
|
|
145
154
|
if (value.stack) {
|
|
146
155
|
result.stack = value.stack;
|
|
147
156
|
}
|
|
148
|
-
for (const key of Object.keys(value)) {
|
|
149
|
-
if (key === "name" || key === "message" || key === "stack") {
|
|
150
|
-
continue;
|
|
151
|
-
}
|
|
152
|
-
result[key] = value[key];
|
|
153
|
-
}
|
|
154
157
|
return result;
|
|
155
158
|
}
|
|
156
159
|
function cloneWithDescriptors(node, options, ref) {
|
|
@@ -160,6 +163,9 @@ function cloneWithDescriptors(node, options, ref) {
|
|
|
160
163
|
const keys = Reflect.ownKeys(descs);
|
|
161
164
|
for (let i = 0, l = keys.length; i < l; i++) {
|
|
162
165
|
const key = keys[i];
|
|
166
|
+
if (!key) {
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
163
169
|
if (isUnsafeKey(key)) {
|
|
164
170
|
continue;
|
|
165
171
|
}
|
|
@@ -191,7 +197,7 @@ function isUnsafeKey(key) {
|
|
|
191
197
|
* High-performance deep clone utility with descriptor support.
|
|
192
198
|
* Supports circular ref and complex built-in types.
|
|
193
199
|
*
|
|
194
|
-
* @version 1.0.
|
|
200
|
+
* @version 1.0.8
|
|
195
201
|
* @author Yusuke Kamiyamane
|
|
196
202
|
* @license MIT
|
|
197
203
|
* @copyright Copyright (c) 2026 Yusuke Kamiyamane
|