bunshin-clone 2.0.0 → 2.0.2

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 CHANGED
@@ -37,7 +37,6 @@ interface BunshinCloneOptions {
37
37
  preserveBufferSharing: boolean; // default: false
38
38
  preserveDescriptors: boolean; // default: false
39
39
  preserveSymbolKeys: boolean; // default: false
40
- strictDescriptors: boolean; // default: false
41
40
  }
42
41
  ```
43
42
 
@@ -52,155 +51,3 @@ If `true`, preserves property descriptors, including non-enumerable properties.
52
51
  ### `preserveSymbolKeys`
53
52
 
54
53
  If `true`, preserves symbol keys (slower).
55
-
56
- ### `strictDescriptors`
57
-
58
- If `true`, throws if property descriptor cannot be copied (e.g. non-configurable or non-writable).
59
-
60
- ## 📖 Details
61
-
62
- <details>
63
- <summary>Read more</summary>
64
-
65
- ### Example
66
-
67
- ```ts
68
- const source = { foo: 1, nested: { x: 1 } };
69
-
70
- const result = bunshinClone(source);
71
-
72
- console.log(result);
73
- // { foo: 1, nested: { x: 1 } }
74
-
75
- console.log(result === source); // false
76
- console.log(result.nested === source.nested); // false
77
- ```
78
-
79
- ### Supported Types
80
-
81
- bunshin-clone correctly handles:
82
-
83
- - Object (plain + prototype preserved)
84
- - Array
85
- - Map
86
- - Set
87
- - Date
88
- - RegExp
89
- - ArrayBuffer
90
- - DataView
91
- - TypedArray (Uint8Array, etc.)
92
- - DOMException / Error
93
- - Blob
94
- - ImageData
95
- - URL
96
- - URLSearchParams
97
-
98
- ### Circular ref
99
-
100
- ```ts
101
- const a: any = { x: 1 };
102
- a.self = a;
103
-
104
- const result = bunshinClone(a);
105
-
106
- result.self === result; // true
107
- ```
108
-
109
- ### Descriptor Behavior
110
-
111
- #### Default (fast path)
112
-
113
- ```ts
114
- const source = {
115
- get x() {
116
- return 42;
117
- },
118
- };
119
-
120
- const result = bunshinClone(source);
121
-
122
- result.x; // 42
123
- // getter is NOT preserved
124
- ```
125
-
126
- #### preserveDescriptors: true
127
-
128
- ```ts
129
- const source = {};
130
- Object.defineProperty(source, 'x', {
131
- get: () => 42,
132
- enumerable: true,
133
- });
134
-
135
- const result = bunshinClone(source, {
136
- preserveDescriptors: true,
137
- });
138
-
139
- Object.getOwnPropertyDescriptor(result, 'x')?.get;
140
- // => preserved
141
- ```
142
-
143
- #### Unsupported / Pass-through Types
144
-
145
- Some values are returned as-is:
146
-
147
- - Function
148
- - WeakMap / WeakSet
149
- - Proxy (not cloned)
150
- - Other non-cloneable host objects
151
-
152
- ```ts
153
- const fn = () => {};
154
-
155
- bunshinClone(fn) === fn; // true
156
- ```
157
-
158
- ### Design Notes
159
-
160
- #### Deep clone (no structural sharing)
161
-
162
- Unlike merge utilities, bunshin-clone always produces a new structure:
163
-
164
- ```ts
165
- const source = { a: { b: 1 } };
166
-
167
- const result = bunshinClone(source);
168
-
169
- result !== source; // true
170
- result.a !== source.a; // true
171
- ```
172
-
173
- #### Getter / Setter behavior
174
-
175
- - Default: evaluated and converted to value
176
- - preserveDescriptors: preserved as-is
177
-
178
- #### Descriptor safety
179
-
180
- When `preserveDescriptors` is enabled:
181
-
182
- - descriptors are cloned safely
183
- - original object is never mutated
184
- - errors are controlled via `strictDescriptors`
185
-
186
- ### Performance
187
-
188
- - No proxy / no diffing
189
- - Minimal branching
190
- - Fast path for plain objects and arrays
191
- - Competitive with structuredClone in many cases
192
-
193
- ### Comparison
194
-
195
- | Feature | Bunshin Clone | structuredClone | lodash.clonedeep |
196
- | ------------------- | ------------- | --------------- | ---------------- |
197
- | Circular refs | ✅ | ✅ | ✅ |
198
- | Map / Set | ✅ | ✅ | ⚠️ (partial) |
199
- | TypedArray | ✅ | ✅ | ⚠️ (shallow) |
200
- | Descriptor support | ✅ | ❌ | ❌ |
201
- | Functions | pass-through | ❌ (throws) | pass-through |
202
- | Prototype preserved | ✅ | ❌ | ⚠️ |
203
- | Custom control | ✅ | ❌ | ❌ |
204
- | Performance | ⚡ fast | ⚡ fast | 🐢 slower |
205
-
206
- </details>
@@ -0,0 +1,359 @@
1
+ 'use strict';
2
+
3
+ // src/utils.ts
4
+ function isObject(value) {
5
+ return typeof value === "object" && value !== null;
6
+ }
7
+ function isPlainObject(value) {
8
+ if (!isObject(value)) {
9
+ return false;
10
+ }
11
+ const proto = Object.getPrototypeOf(value);
12
+ return proto === Object.prototype || proto === null;
13
+ }
14
+
15
+ // src/clone/array.ts
16
+ function cloneArray(array, settings, refs) {
17
+ const result = isPrimitiveArray(array) ? array.slice() : array.map((i) => clone(i, settings, refs));
18
+ refs.set(array, result);
19
+ return result;
20
+ }
21
+ function isPrimitiveArray(array) {
22
+ return array.every((i) => !isObject(i));
23
+ }
24
+
25
+ // src/clone/array-buffer.ts
26
+ function cloneArrayBuffer(buffer, refs) {
27
+ const result = buffer.slice(0);
28
+ refs.set(buffer, result);
29
+ return result;
30
+ }
31
+
32
+ // src/clone/array-buffer-view.ts
33
+ function cloneArrayBufferView(view, settings, refs) {
34
+ if (view instanceof DataView) {
35
+ const { buffer: buffer2, byteOffset: byteOffset2, byteLength } = view;
36
+ const result2 = new DataView(
37
+ cloneBuffer(buffer2, refs),
38
+ byteOffset2,
39
+ byteLength
40
+ );
41
+ refs.set(view, result2);
42
+ return result2;
43
+ }
44
+ if (!settings.preserveBufferSharing) {
45
+ const Ctor2 = view.constructor;
46
+ const result2 = new Ctor2(view);
47
+ refs.set(view, result2);
48
+ return result2;
49
+ }
50
+ const Ctor = view.constructor;
51
+ const { buffer, byteOffset, length } = view;
52
+ const result = new Ctor(cloneBuffer(buffer, refs), byteOffset, length);
53
+ refs.set(view, result);
54
+ return result;
55
+ }
56
+ function cloneBuffer(buffer, refs) {
57
+ if (refs.has(buffer)) {
58
+ return refs.get(buffer);
59
+ }
60
+ const result = buffer.slice(0);
61
+ refs.set(buffer, result);
62
+ return result;
63
+ }
64
+
65
+ // src/clone/blob.ts
66
+ function cloneBlob(blob, refs) {
67
+ const { size, type } = blob;
68
+ const result = blob.slice(0, size, type);
69
+ refs.set(blob, result);
70
+ return result;
71
+ }
72
+
73
+ // src/clone/date.ts
74
+ function cloneDate(date, refs) {
75
+ const result = new Date(date.getTime());
76
+ refs.set(date, result);
77
+ return result;
78
+ }
79
+
80
+ // src/clone/error.ts
81
+ function cloneError(error, settings, refs) {
82
+ const result = createErrorInstance(error, settings, refs);
83
+ refs.set(error, result);
84
+ if (error instanceof DOMException) {
85
+ return result;
86
+ }
87
+ const { stack, cause } = error;
88
+ if (stack) {
89
+ try {
90
+ result.stack = stack;
91
+ } catch {
92
+ }
93
+ }
94
+ if ("cause" in error && cause !== void 0) {
95
+ result.cause = clone(cause, settings, refs);
96
+ }
97
+ for (const key of Object.keys(error)) {
98
+ Reflect.set(result, key, clone(Reflect.get(error, key), settings, refs));
99
+ }
100
+ return result;
101
+ }
102
+ var ERROR_CTORS = {
103
+ EvalError,
104
+ RangeError,
105
+ ReferenceError,
106
+ SyntaxError,
107
+ TypeError,
108
+ URIError
109
+ };
110
+ function createErrorInstance(error, settings, refs) {
111
+ const { message, name } = error;
112
+ if (error instanceof DOMException) {
113
+ return new DOMException(message, name);
114
+ }
115
+ if (error instanceof AggregateError) {
116
+ return new AggregateError(
117
+ error.errors.map((e) => clone(e, settings, refs)),
118
+ message
119
+ );
120
+ }
121
+ const Ctor = ERROR_CTORS[name];
122
+ if (Ctor) {
123
+ return new Ctor(message);
124
+ }
125
+ const result = new Error(message);
126
+ result.name = name;
127
+ return result;
128
+ }
129
+
130
+ // src/clone/image-data.ts
131
+ function cloneImageData(data, refs) {
132
+ const { data: d, width, height, colorSpace } = data;
133
+ const result = new ImageData(new Uint8ClampedArray(d), width, height, {
134
+ colorSpace
135
+ });
136
+ refs.set(data, result);
137
+ return result;
138
+ }
139
+
140
+ // src/clone/map.ts
141
+ function cloneMap(map, settings, refs) {
142
+ const result = /* @__PURE__ */ new Map();
143
+ refs.set(map, result);
144
+ for (const [key, value] of map) {
145
+ result.set(clone(key, settings, refs), clone(value, settings, refs));
146
+ }
147
+ return result;
148
+ }
149
+ var OWN_DESCS = Object.getOwnPropertyDescriptors;
150
+ function OWN_ENUM_STRING_KEYS(object) {
151
+ const keys = Object.keys(object);
152
+ for (const key of keys) {
153
+ if (isUnsafeKey(key)) {
154
+ keys.splice(keys.indexOf(key), 1);
155
+ }
156
+ }
157
+ return keys;
158
+ }
159
+ function OWN_ENUM_SYMBOL_KEYS(object) {
160
+ const keys = OWN_SYMBOL_KEYS(object);
161
+ for (const key of keys) {
162
+ if (!Object.prototype.propertyIsEnumerable.call(object, key)) {
163
+ keys.splice(keys.indexOf(key), 1);
164
+ }
165
+ }
166
+ return keys;
167
+ }
168
+ function OWN_STRING_KEYS(object) {
169
+ const keys = Object.getOwnPropertyNames(object);
170
+ for (const key of keys) {
171
+ if (isUnsafeKey(key)) {
172
+ keys.splice(keys.indexOf(key), 1);
173
+ }
174
+ }
175
+ return keys;
176
+ }
177
+ var OWN_SYMBOL_KEYS = Object.getOwnPropertySymbols;
178
+ function isUnsafeKey(key) {
179
+ return typeof key === "string" && (key === "__proto__" || key === "prototype" || key === "constructor");
180
+ }
181
+
182
+ // src/clone/plain-object.ts
183
+ function clonePlainObject(object, settings, refs) {
184
+ const result = Object.create(Object.getPrototypeOf(object));
185
+ refs.set(object, result);
186
+ function copy(key) {
187
+ result[key] = clone(object[key], settings, refs);
188
+ }
189
+ for (const key of OWN_ENUM_STRING_KEYS(object)) {
190
+ copy(key);
191
+ }
192
+ if (settings.preserveSymbolKeys) {
193
+ for (const key of OWN_ENUM_SYMBOL_KEYS(object)) {
194
+ copy(key);
195
+ }
196
+ }
197
+ return result;
198
+ }
199
+
200
+ // src/clone/regexp.ts
201
+ function cloneRegExp(re, refs) {
202
+ const { source, flags, lastIndex } = re;
203
+ const result = new RegExp(source, flags);
204
+ refs.set(re, result);
205
+ result.lastIndex = lastIndex;
206
+ return result;
207
+ }
208
+
209
+ // src/clone/set.ts
210
+ function cloneSet(set, settings, refs) {
211
+ if (isPrimitiveSet(set)) {
212
+ const result2 = new Set(set);
213
+ refs.set(set, result2);
214
+ return result2;
215
+ }
216
+ const result = /* @__PURE__ */ new Set();
217
+ refs.set(set, result);
218
+ for (const item of set) {
219
+ result.add(clone(item, settings, refs));
220
+ }
221
+ return result;
222
+ }
223
+ function isPrimitiveSet(set) {
224
+ for (const value of set) {
225
+ if (isObject(value)) {
226
+ return false;
227
+ }
228
+ }
229
+ return true;
230
+ }
231
+
232
+ // src/clone/url.ts
233
+ function cloneURL(url, refs) {
234
+ const result = new URL(url.href);
235
+ refs.set(url, result);
236
+ return result;
237
+ }
238
+
239
+ // src/clone/url-search-params.ts
240
+ function cloneURLSearchParams(params, refs) {
241
+ const result = new URLSearchParams(params);
242
+ refs.set(params, result);
243
+ return result;
244
+ }
245
+
246
+ // src/clone/with-descriptors.ts
247
+ function cloneWithDescriptors(object, settings, refs) {
248
+ const result = Object.create(Object.getPrototypeOf(object));
249
+ refs.set(object, result);
250
+ const descs = OWN_DESCS(object);
251
+ function copy(key) {
252
+ const desc = { ...descs[key] };
253
+ if ("value" in desc) {
254
+ desc.value = clone(desc.value, settings, refs);
255
+ }
256
+ Object.defineProperty(result, key, desc);
257
+ }
258
+ for (const key of OWN_STRING_KEYS(object)) {
259
+ copy(key);
260
+ }
261
+ if (settings.preserveSymbolKeys) {
262
+ for (const key of OWN_SYMBOL_KEYS(object)) {
263
+ copy(key);
264
+ }
265
+ }
266
+ return result;
267
+ }
268
+
269
+ // src/index.ts
270
+ function bunshinClone(value, options = {}) {
271
+ return clone(value, resolveOptions(options), /* @__PURE__ */ new WeakMap());
272
+ }
273
+ function clone(value, settings, refs) {
274
+ if (!isObject(value)) {
275
+ return value;
276
+ }
277
+ if (refs.has(value)) {
278
+ return refs.get(value);
279
+ }
280
+ const isClonePlainObject = isPlainObject(value);
281
+ if (settings.preserveDescriptors && isClonePlainObject) {
282
+ return cloneWithDescriptors(value, settings, refs);
283
+ }
284
+ if (Array.isArray(value)) {
285
+ return cloneArray(value, settings, refs);
286
+ }
287
+ if (isClonePlainObject) {
288
+ return clonePlainObject(value, settings, refs);
289
+ }
290
+ if (value instanceof Map) {
291
+ return cloneMap(value, settings, refs);
292
+ }
293
+ if (value instanceof Set) {
294
+ return cloneSet(value, settings, refs);
295
+ }
296
+ if (value instanceof Date) {
297
+ return cloneDate(value, refs);
298
+ }
299
+ if (value instanceof RegExp) {
300
+ return cloneRegExp(value, refs);
301
+ }
302
+ if (value instanceof ArrayBuffer) {
303
+ return cloneArrayBuffer(value, refs);
304
+ }
305
+ if (ArrayBuffer.isView(value)) {
306
+ return cloneArrayBufferView(
307
+ value,
308
+ settings,
309
+ refs
310
+ );
311
+ }
312
+ if (value instanceof Error) {
313
+ return cloneError(value, settings, refs);
314
+ }
315
+ if (value instanceof Blob) {
316
+ return cloneBlob(value, refs);
317
+ }
318
+ if (typeof ImageData !== "undefined" && value instanceof ImageData) {
319
+ return cloneImageData(value, refs);
320
+ }
321
+ if (value instanceof URL) {
322
+ return cloneURL(value, refs);
323
+ }
324
+ if (value instanceof URLSearchParams) {
325
+ return cloneURLSearchParams(value, refs);
326
+ }
327
+ refs.set(value, value);
328
+ return value;
329
+ }
330
+ function resolveOptions(options) {
331
+ let {
332
+ preserveBufferSharing = false,
333
+ preserveDescriptors = false,
334
+ preserveSymbolKeys = false
335
+ } = options;
336
+ if (typeof preserveBufferSharing !== "boolean") {
337
+ console.warn("Invalid preserveBufferSharing option. Fallback: false.");
338
+ preserveBufferSharing = false;
339
+ }
340
+ if (typeof preserveDescriptors !== "boolean") {
341
+ console.warn("Invalid preserveDescriptors option. Fallback: false.");
342
+ preserveDescriptors = false;
343
+ }
344
+ if (typeof preserveSymbolKeys !== "boolean") {
345
+ console.warn("Invalid preserveSymbolKeys option. Fallback: false.");
346
+ preserveSymbolKeys = false;
347
+ }
348
+ return {
349
+ preserveBufferSharing,
350
+ preserveDescriptors,
351
+ preserveSymbolKeys
352
+ };
353
+ }
354
+
355
+ exports.bunshinClone = bunshinClone;
356
+ exports.clone = clone;
357
+ exports.isObject = isObject;
358
+ exports.isPlainObject = isPlainObject;
359
+ exports.isPrimitiveArray = isPrimitiveArray;
@@ -0,0 +1,353 @@
1
+ // src/utils.ts
2
+ function isObject(value) {
3
+ return typeof value === "object" && value !== null;
4
+ }
5
+ function isPlainObject(value) {
6
+ if (!isObject(value)) {
7
+ return false;
8
+ }
9
+ const proto = Object.getPrototypeOf(value);
10
+ return proto === Object.prototype || proto === null;
11
+ }
12
+
13
+ // src/clone/array.ts
14
+ function cloneArray(array, settings, refs) {
15
+ const result = isPrimitiveArray(array) ? array.slice() : array.map((i) => clone(i, settings, refs));
16
+ refs.set(array, result);
17
+ return result;
18
+ }
19
+ function isPrimitiveArray(array) {
20
+ return array.every((i) => !isObject(i));
21
+ }
22
+
23
+ // src/clone/array-buffer.ts
24
+ function cloneArrayBuffer(buffer, refs) {
25
+ const result = buffer.slice(0);
26
+ refs.set(buffer, result);
27
+ return result;
28
+ }
29
+
30
+ // src/clone/array-buffer-view.ts
31
+ function cloneArrayBufferView(view, settings, refs) {
32
+ if (view instanceof DataView) {
33
+ const { buffer: buffer2, byteOffset: byteOffset2, byteLength } = view;
34
+ const result2 = new DataView(
35
+ cloneBuffer(buffer2, refs),
36
+ byteOffset2,
37
+ byteLength
38
+ );
39
+ refs.set(view, result2);
40
+ return result2;
41
+ }
42
+ if (!settings.preserveBufferSharing) {
43
+ const Ctor2 = view.constructor;
44
+ const result2 = new Ctor2(view);
45
+ refs.set(view, result2);
46
+ return result2;
47
+ }
48
+ const Ctor = view.constructor;
49
+ const { buffer, byteOffset, length } = view;
50
+ const result = new Ctor(cloneBuffer(buffer, refs), byteOffset, length);
51
+ refs.set(view, result);
52
+ return result;
53
+ }
54
+ function cloneBuffer(buffer, refs) {
55
+ if (refs.has(buffer)) {
56
+ return refs.get(buffer);
57
+ }
58
+ const result = buffer.slice(0);
59
+ refs.set(buffer, result);
60
+ return result;
61
+ }
62
+
63
+ // src/clone/blob.ts
64
+ function cloneBlob(blob, refs) {
65
+ const { size, type } = blob;
66
+ const result = blob.slice(0, size, type);
67
+ refs.set(blob, result);
68
+ return result;
69
+ }
70
+
71
+ // src/clone/date.ts
72
+ function cloneDate(date, refs) {
73
+ const result = new Date(date.getTime());
74
+ refs.set(date, result);
75
+ return result;
76
+ }
77
+
78
+ // src/clone/error.ts
79
+ function cloneError(error, settings, refs) {
80
+ const result = createErrorInstance(error, settings, refs);
81
+ refs.set(error, result);
82
+ if (error instanceof DOMException) {
83
+ return result;
84
+ }
85
+ const { stack, cause } = error;
86
+ if (stack) {
87
+ try {
88
+ result.stack = stack;
89
+ } catch {
90
+ }
91
+ }
92
+ if ("cause" in error && cause !== void 0) {
93
+ result.cause = clone(cause, settings, refs);
94
+ }
95
+ for (const key of Object.keys(error)) {
96
+ Reflect.set(result, key, clone(Reflect.get(error, key), settings, refs));
97
+ }
98
+ return result;
99
+ }
100
+ var ERROR_CTORS = {
101
+ EvalError,
102
+ RangeError,
103
+ ReferenceError,
104
+ SyntaxError,
105
+ TypeError,
106
+ URIError
107
+ };
108
+ function createErrorInstance(error, settings, refs) {
109
+ const { message, name } = error;
110
+ if (error instanceof DOMException) {
111
+ return new DOMException(message, name);
112
+ }
113
+ if (error instanceof AggregateError) {
114
+ return new AggregateError(
115
+ error.errors.map((e) => clone(e, settings, refs)),
116
+ message
117
+ );
118
+ }
119
+ const Ctor = ERROR_CTORS[name];
120
+ if (Ctor) {
121
+ return new Ctor(message);
122
+ }
123
+ const result = new Error(message);
124
+ result.name = name;
125
+ return result;
126
+ }
127
+
128
+ // src/clone/image-data.ts
129
+ function cloneImageData(data, refs) {
130
+ const { data: d, width, height, colorSpace } = data;
131
+ const result = new ImageData(new Uint8ClampedArray(d), width, height, {
132
+ colorSpace
133
+ });
134
+ refs.set(data, result);
135
+ return result;
136
+ }
137
+
138
+ // src/clone/map.ts
139
+ function cloneMap(map, settings, refs) {
140
+ const result = /* @__PURE__ */ new Map();
141
+ refs.set(map, result);
142
+ for (const [key, value] of map) {
143
+ result.set(clone(key, settings, refs), clone(value, settings, refs));
144
+ }
145
+ return result;
146
+ }
147
+ var OWN_DESCS = Object.getOwnPropertyDescriptors;
148
+ function OWN_ENUM_STRING_KEYS(object) {
149
+ const keys = Object.keys(object);
150
+ for (const key of keys) {
151
+ if (isUnsafeKey(key)) {
152
+ keys.splice(keys.indexOf(key), 1);
153
+ }
154
+ }
155
+ return keys;
156
+ }
157
+ function OWN_ENUM_SYMBOL_KEYS(object) {
158
+ const keys = OWN_SYMBOL_KEYS(object);
159
+ for (const key of keys) {
160
+ if (!Object.prototype.propertyIsEnumerable.call(object, key)) {
161
+ keys.splice(keys.indexOf(key), 1);
162
+ }
163
+ }
164
+ return keys;
165
+ }
166
+ function OWN_STRING_KEYS(object) {
167
+ const keys = Object.getOwnPropertyNames(object);
168
+ for (const key of keys) {
169
+ if (isUnsafeKey(key)) {
170
+ keys.splice(keys.indexOf(key), 1);
171
+ }
172
+ }
173
+ return keys;
174
+ }
175
+ var OWN_SYMBOL_KEYS = Object.getOwnPropertySymbols;
176
+ function isUnsafeKey(key) {
177
+ return typeof key === "string" && (key === "__proto__" || key === "prototype" || key === "constructor");
178
+ }
179
+
180
+ // src/clone/plain-object.ts
181
+ function clonePlainObject(object, settings, refs) {
182
+ const result = Object.create(Object.getPrototypeOf(object));
183
+ refs.set(object, result);
184
+ function copy(key) {
185
+ result[key] = clone(object[key], settings, refs);
186
+ }
187
+ for (const key of OWN_ENUM_STRING_KEYS(object)) {
188
+ copy(key);
189
+ }
190
+ if (settings.preserveSymbolKeys) {
191
+ for (const key of OWN_ENUM_SYMBOL_KEYS(object)) {
192
+ copy(key);
193
+ }
194
+ }
195
+ return result;
196
+ }
197
+
198
+ // src/clone/regexp.ts
199
+ function cloneRegExp(re, refs) {
200
+ const { source, flags, lastIndex } = re;
201
+ const result = new RegExp(source, flags);
202
+ refs.set(re, result);
203
+ result.lastIndex = lastIndex;
204
+ return result;
205
+ }
206
+
207
+ // src/clone/set.ts
208
+ function cloneSet(set, settings, refs) {
209
+ if (isPrimitiveSet(set)) {
210
+ const result2 = new Set(set);
211
+ refs.set(set, result2);
212
+ return result2;
213
+ }
214
+ const result = /* @__PURE__ */ new Set();
215
+ refs.set(set, result);
216
+ for (const item of set) {
217
+ result.add(clone(item, settings, refs));
218
+ }
219
+ return result;
220
+ }
221
+ function isPrimitiveSet(set) {
222
+ for (const value of set) {
223
+ if (isObject(value)) {
224
+ return false;
225
+ }
226
+ }
227
+ return true;
228
+ }
229
+
230
+ // src/clone/url.ts
231
+ function cloneURL(url, refs) {
232
+ const result = new URL(url.href);
233
+ refs.set(url, result);
234
+ return result;
235
+ }
236
+
237
+ // src/clone/url-search-params.ts
238
+ function cloneURLSearchParams(params, refs) {
239
+ const result = new URLSearchParams(params);
240
+ refs.set(params, result);
241
+ return result;
242
+ }
243
+
244
+ // src/clone/with-descriptors.ts
245
+ function cloneWithDescriptors(object, settings, refs) {
246
+ const result = Object.create(Object.getPrototypeOf(object));
247
+ refs.set(object, result);
248
+ const descs = OWN_DESCS(object);
249
+ function copy(key) {
250
+ const desc = { ...descs[key] };
251
+ if ("value" in desc) {
252
+ desc.value = clone(desc.value, settings, refs);
253
+ }
254
+ Object.defineProperty(result, key, desc);
255
+ }
256
+ for (const key of OWN_STRING_KEYS(object)) {
257
+ copy(key);
258
+ }
259
+ if (settings.preserveSymbolKeys) {
260
+ for (const key of OWN_SYMBOL_KEYS(object)) {
261
+ copy(key);
262
+ }
263
+ }
264
+ return result;
265
+ }
266
+
267
+ // src/index.ts
268
+ function bunshinClone(value, options = {}) {
269
+ return clone(value, resolveOptions(options), /* @__PURE__ */ new WeakMap());
270
+ }
271
+ function clone(value, settings, refs) {
272
+ if (!isObject(value)) {
273
+ return value;
274
+ }
275
+ if (refs.has(value)) {
276
+ return refs.get(value);
277
+ }
278
+ const isClonePlainObject = isPlainObject(value);
279
+ if (settings.preserveDescriptors && isClonePlainObject) {
280
+ return cloneWithDescriptors(value, settings, refs);
281
+ }
282
+ if (Array.isArray(value)) {
283
+ return cloneArray(value, settings, refs);
284
+ }
285
+ if (isClonePlainObject) {
286
+ return clonePlainObject(value, settings, refs);
287
+ }
288
+ if (value instanceof Map) {
289
+ return cloneMap(value, settings, refs);
290
+ }
291
+ if (value instanceof Set) {
292
+ return cloneSet(value, settings, refs);
293
+ }
294
+ if (value instanceof Date) {
295
+ return cloneDate(value, refs);
296
+ }
297
+ if (value instanceof RegExp) {
298
+ return cloneRegExp(value, refs);
299
+ }
300
+ if (value instanceof ArrayBuffer) {
301
+ return cloneArrayBuffer(value, refs);
302
+ }
303
+ if (ArrayBuffer.isView(value)) {
304
+ return cloneArrayBufferView(
305
+ value,
306
+ settings,
307
+ refs
308
+ );
309
+ }
310
+ if (value instanceof Error) {
311
+ return cloneError(value, settings, refs);
312
+ }
313
+ if (value instanceof Blob) {
314
+ return cloneBlob(value, refs);
315
+ }
316
+ if (typeof ImageData !== "undefined" && value instanceof ImageData) {
317
+ return cloneImageData(value, refs);
318
+ }
319
+ if (value instanceof URL) {
320
+ return cloneURL(value, refs);
321
+ }
322
+ if (value instanceof URLSearchParams) {
323
+ return cloneURLSearchParams(value, refs);
324
+ }
325
+ refs.set(value, value);
326
+ return value;
327
+ }
328
+ function resolveOptions(options) {
329
+ let {
330
+ preserveBufferSharing = false,
331
+ preserveDescriptors = false,
332
+ preserveSymbolKeys = false
333
+ } = options;
334
+ if (typeof preserveBufferSharing !== "boolean") {
335
+ console.warn("Invalid preserveBufferSharing option. Fallback: false.");
336
+ preserveBufferSharing = false;
337
+ }
338
+ if (typeof preserveDescriptors !== "boolean") {
339
+ console.warn("Invalid preserveDescriptors option. Fallback: false.");
340
+ preserveDescriptors = false;
341
+ }
342
+ if (typeof preserveSymbolKeys !== "boolean") {
343
+ console.warn("Invalid preserveSymbolKeys option. Fallback: false.");
344
+ preserveSymbolKeys = false;
345
+ }
346
+ return {
347
+ preserveBufferSharing,
348
+ preserveDescriptors,
349
+ preserveSymbolKeys
350
+ };
351
+ }
352
+
353
+ export { bunshinClone, clone, isObject, isPlainObject, isPrimitiveArray };
package/dist/index.cjs CHANGED
@@ -219,13 +219,7 @@ function cloneWithDescriptors(object, settings, refs) {
219
219
  if ("value" in desc) {
220
220
  desc.value = clone(desc.value, settings, refs);
221
221
  }
222
- try {
223
- Object.defineProperty(result, key, desc);
224
- } catch (error) {
225
- if (settings.strictDescriptors) {
226
- throw error;
227
- }
228
- }
222
+ Object.defineProperty(result, key, desc);
229
223
  }
230
224
  for (const key of own.OWN_STRING_KEYS(object)) {
231
225
  copy(key);
@@ -303,13 +297,8 @@ function resolveOptions(options) {
303
297
  let {
304
298
  preserveBufferSharing = false,
305
299
  preserveDescriptors = false,
306
- strictDescriptors = false,
307
300
  preserveSymbolKeys = false
308
301
  } = options;
309
- if (typeof preserveSymbolKeys !== "boolean") {
310
- console.warn("Invalid preserveSymbolKeys option. Fallback: false.");
311
- preserveSymbolKeys = false;
312
- }
313
302
  if (typeof preserveBufferSharing !== "boolean") {
314
303
  console.warn("Invalid preserveBufferSharing option. Fallback: false.");
315
304
  preserveBufferSharing = false;
@@ -318,15 +307,14 @@ function resolveOptions(options) {
318
307
  console.warn("Invalid preserveDescriptors option. Fallback: false.");
319
308
  preserveDescriptors = false;
320
309
  }
321
- if (typeof strictDescriptors !== "boolean") {
322
- console.warn("Invalid strictDescriptors option. Fallback: false.");
323
- strictDescriptors = false;
310
+ if (typeof preserveSymbolKeys !== "boolean") {
311
+ console.warn("Invalid preserveSymbolKeys option. Fallback: false.");
312
+ preserveSymbolKeys = false;
324
313
  }
325
314
  return {
326
315
  preserveBufferSharing,
327
316
  preserveDescriptors,
328
- preserveSymbolKeys,
329
- strictDescriptors
317
+ preserveSymbolKeys
330
318
  };
331
319
  }
332
320
 
package/dist/index.d.cts CHANGED
@@ -4,7 +4,6 @@ interface BunshinCloneOptions {
4
4
  preserveBufferSharing: boolean;
5
5
  preserveDescriptors: boolean;
6
6
  preserveSymbolKeys: boolean;
7
- strictDescriptors: boolean;
8
7
  }
9
8
  type PlainObject = Record<PropertyKey, unknown>;
10
9
 
package/dist/index.d.ts CHANGED
@@ -4,7 +4,6 @@ interface BunshinCloneOptions {
4
4
  preserveBufferSharing: boolean;
5
5
  preserveDescriptors: boolean;
6
6
  preserveSymbolKeys: boolean;
7
- strictDescriptors: boolean;
8
7
  }
9
8
  type PlainObject = Record<PropertyKey, unknown>;
10
9
 
package/dist/index.js CHANGED
@@ -217,13 +217,7 @@ function cloneWithDescriptors(object, settings, refs) {
217
217
  if ("value" in desc) {
218
218
  desc.value = clone(desc.value, settings, refs);
219
219
  }
220
- try {
221
- Object.defineProperty(result, key, desc);
222
- } catch (error) {
223
- if (settings.strictDescriptors) {
224
- throw error;
225
- }
226
- }
220
+ Object.defineProperty(result, key, desc);
227
221
  }
228
222
  for (const key of OWN_STRING_KEYS(object)) {
229
223
  copy(key);
@@ -301,13 +295,8 @@ function resolveOptions(options) {
301
295
  let {
302
296
  preserveBufferSharing = false,
303
297
  preserveDescriptors = false,
304
- strictDescriptors = false,
305
298
  preserveSymbolKeys = false
306
299
  } = options;
307
- if (typeof preserveSymbolKeys !== "boolean") {
308
- console.warn("Invalid preserveSymbolKeys option. Fallback: false.");
309
- preserveSymbolKeys = false;
310
- }
311
300
  if (typeof preserveBufferSharing !== "boolean") {
312
301
  console.warn("Invalid preserveBufferSharing option. Fallback: false.");
313
302
  preserveBufferSharing = false;
@@ -316,15 +305,14 @@ function resolveOptions(options) {
316
305
  console.warn("Invalid preserveDescriptors option. Fallback: false.");
317
306
  preserveDescriptors = false;
318
307
  }
319
- if (typeof strictDescriptors !== "boolean") {
320
- console.warn("Invalid strictDescriptors option. Fallback: false.");
321
- strictDescriptors = false;
308
+ if (typeof preserveSymbolKeys !== "boolean") {
309
+ console.warn("Invalid preserveSymbolKeys option. Fallback: false.");
310
+ preserveSymbolKeys = false;
322
311
  }
323
312
  return {
324
313
  preserveBufferSharing,
325
314
  preserveDescriptors,
326
- preserveSymbolKeys,
327
- strictDescriptors
315
+ preserveSymbolKeys
328
316
  };
329
317
  }
330
318
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bunshin-clone",
3
- "version": "2.0.0",
3
+ "version": "2.0.2",
4
4
  "description": "High-performance deep clone utility with descriptor support",
5
5
  "keywords": [
6
6
  "array",
@@ -69,7 +69,7 @@
69
69
  "test": "bun test"
70
70
  },
71
71
  "dependencies": {
72
- "@y14e/own": "^1.0.0"
72
+ "@y14e/own": "^1.0.1"
73
73
  },
74
74
  "devDependencies": {
75
75
  "bun-types": "latest",