bunshin-clone 1.4.2 → 1.5.0

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
@@ -34,11 +34,16 @@ bunshinClone(source, options);
34
34
 
35
35
  ```ts
36
36
  interface BunshinCloneOptions {
37
- preserveDescriptors: boolean; // default: false
38
- strictDescriptors: boolean; // default: false
37
+ preserveBufferSharing: boolean; // default: false
38
+ preserveDescriptors: boolean; // default: false
39
+ strictDescriptors: boolean; // default: false
39
40
  }
40
41
  ```
41
42
 
43
+ ### `preserveBufferSharing`
44
+
45
+ If `true`, preserves shared backing buffers between TypedArray and DataView instances.
46
+
42
47
  ### `preserveDescriptors`
43
48
 
44
49
  If `true`, preserves property descriptors (getters/setters, etc.).
package/dist/index.cjs CHANGED
@@ -4,9 +4,9 @@
4
4
  var EMPTY_OPTIONS = {};
5
5
  var { hasOwnProperty: HAS_OWN } = Object.prototype;
6
6
  function bunshinClone(source, options = EMPTY_OPTIONS, refs = /* @__PURE__ */ new WeakMap()) {
7
- return clone(source, options, refs);
7
+ return clone(source, resolveOptions(options), refs);
8
8
  }
9
- function clone(source, options, refs) {
9
+ function clone(source, settings, refs) {
10
10
  if (!isObject(source)) {
11
11
  return source;
12
12
  }
@@ -14,7 +14,6 @@ function clone(source, options, refs) {
14
14
  if (ref !== void 0) {
15
15
  return ref;
16
16
  }
17
- const settings = resolveOptions(options);
18
17
  if (settings.preserveDescriptors && isPlainObject(source)) {
19
18
  return cloneWithDescriptors(source, settings, refs);
20
19
  }
@@ -30,10 +29,9 @@ function clone(source, options, refs) {
30
29
  const result = Object.create(Object.getPrototypeOf(source));
31
30
  refs.set(source, result);
32
31
  for (const key in source) {
33
- if (!HAS_OWN.call(source, key) || isUnsafeKey(key)) {
34
- continue;
32
+ if (HAS_OWN.call(source, key) && !isUnsafeKey(key)) {
33
+ result[key] = clone(source[key], settings, refs);
35
34
  }
36
- result[key] = clone(source[key], settings, refs);
37
35
  }
38
36
  return result;
39
37
  }
@@ -70,14 +68,26 @@ function clone(source, options, refs) {
70
68
  return result;
71
69
  }
72
70
  if (ArrayBuffer.isView(source)) {
73
- const { buffer, byteOffset, byteLength } = source;
74
71
  if (source instanceof DataView) {
75
- const result2 = new DataView(buffer.slice(0), byteOffset, byteLength);
72
+ const { buffer: buffer2, byteOffset: byteOffset2, byteLength } = source;
73
+ const result2 = new DataView(
74
+ cloneBuffer(buffer2, refs),
75
+ byteOffset2,
76
+ byteLength
77
+ );
76
78
  refs.set(source, result2);
77
79
  return result2;
78
80
  }
79
- const Ctor = source.constructor;
80
- const result = new Ctor(buffer.slice(byteOffset, byteOffset + byteLength));
81
+ const view = source;
82
+ if (!settings.preserveBufferSharing) {
83
+ const Ctor2 = view.constructor;
84
+ const result2 = new Ctor2(view);
85
+ refs.set(source, result2);
86
+ return result2;
87
+ }
88
+ const Ctor = view.constructor;
89
+ const { buffer, byteOffset, length } = view;
90
+ const result = new Ctor(cloneBuffer(buffer, refs), byteOffset, length);
81
91
  refs.set(source, result);
82
92
  return result;
83
93
  }
@@ -113,20 +123,30 @@ function clone(source, options, refs) {
113
123
  refs.set(source, source);
114
124
  return source;
115
125
  }
126
+ function cloneBuffer(buffer, refs) {
127
+ const ref = refs.get(buffer);
128
+ if (ref !== void 0) {
129
+ return ref;
130
+ }
131
+ const result = buffer.slice(0);
132
+ refs.set(buffer, result);
133
+ return result;
134
+ }
116
135
  function cloneError(source, settings, refs) {
117
136
  const result = createErrorInstance(source, settings, refs);
118
137
  refs.set(source, result);
119
138
  if (source instanceof DOMException) {
120
139
  return result;
121
140
  }
122
- if (source.stack) {
141
+ const { stack, cause } = source;
142
+ if (stack) {
123
143
  try {
124
- result.stack = source.stack;
144
+ result.stack = stack;
125
145
  } catch {
126
146
  }
127
147
  }
128
- if ("cause" in source && source.cause !== void 0) {
129
- result.cause = clone(source.cause, settings, refs);
148
+ if ("cause" in source && cause !== void 0) {
149
+ result.cause = clone(cause, settings, refs);
130
150
  }
131
151
  for (const key of Object.keys(source)) {
132
152
  Reflect.set(result, key, clone(Reflect.get(source, key), settings, refs));
@@ -204,7 +224,15 @@ function isUnsafeKey(key) {
204
224
  return typeof key === "string" && (key === "__proto__" || key === "prototype" || key === "constructor");
205
225
  }
206
226
  function resolveOptions(options) {
207
- let { preserveDescriptors = false, strictDescriptors = false } = options;
227
+ let {
228
+ preserveBufferSharing = false,
229
+ preserveDescriptors = false,
230
+ strictDescriptors = false
231
+ } = options;
232
+ if (typeof preserveBufferSharing !== "boolean") {
233
+ console.warn("Invalid preserveBufferSharing option. Fallback: false.");
234
+ preserveBufferSharing = false;
235
+ }
208
236
  if (typeof preserveDescriptors !== "boolean") {
209
237
  console.warn("Invalid preserveDescriptors option. Fallback: false.");
210
238
  preserveDescriptors = false;
@@ -213,7 +241,7 @@ function resolveOptions(options) {
213
241
  console.warn("Invalid strictDescriptors option. Fallback: false.");
214
242
  strictDescriptors = false;
215
243
  }
216
- return { preserveDescriptors, strictDescriptors };
244
+ return { preserveBufferSharing, preserveDescriptors, strictDescriptors };
217
245
  }
218
246
 
219
247
  exports.bunshinClone = bunshinClone;
package/dist/index.d.cts CHANGED
@@ -1,4 +1,5 @@
1
1
  interface BunshinCloneOptions {
2
+ preserveBufferSharing: boolean;
2
3
  preserveDescriptors: boolean;
3
4
  strictDescriptors: boolean;
4
5
  }
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  interface BunshinCloneOptions {
2
+ preserveBufferSharing: boolean;
2
3
  preserveDescriptors: boolean;
3
4
  strictDescriptors: boolean;
4
5
  }
package/dist/index.js CHANGED
@@ -2,9 +2,9 @@
2
2
  var EMPTY_OPTIONS = {};
3
3
  var { hasOwnProperty: HAS_OWN } = Object.prototype;
4
4
  function bunshinClone(source, options = EMPTY_OPTIONS, refs = /* @__PURE__ */ new WeakMap()) {
5
- return clone(source, options, refs);
5
+ return clone(source, resolveOptions(options), refs);
6
6
  }
7
- function clone(source, options, refs) {
7
+ function clone(source, settings, refs) {
8
8
  if (!isObject(source)) {
9
9
  return source;
10
10
  }
@@ -12,7 +12,6 @@ function clone(source, options, refs) {
12
12
  if (ref !== void 0) {
13
13
  return ref;
14
14
  }
15
- const settings = resolveOptions(options);
16
15
  if (settings.preserveDescriptors && isPlainObject(source)) {
17
16
  return cloneWithDescriptors(source, settings, refs);
18
17
  }
@@ -28,10 +27,9 @@ function clone(source, options, refs) {
28
27
  const result = Object.create(Object.getPrototypeOf(source));
29
28
  refs.set(source, result);
30
29
  for (const key in source) {
31
- if (!HAS_OWN.call(source, key) || isUnsafeKey(key)) {
32
- continue;
30
+ if (HAS_OWN.call(source, key) && !isUnsafeKey(key)) {
31
+ result[key] = clone(source[key], settings, refs);
33
32
  }
34
- result[key] = clone(source[key], settings, refs);
35
33
  }
36
34
  return result;
37
35
  }
@@ -68,14 +66,26 @@ function clone(source, options, refs) {
68
66
  return result;
69
67
  }
70
68
  if (ArrayBuffer.isView(source)) {
71
- const { buffer, byteOffset, byteLength } = source;
72
69
  if (source instanceof DataView) {
73
- const result2 = new DataView(buffer.slice(0), byteOffset, byteLength);
70
+ const { buffer: buffer2, byteOffset: byteOffset2, byteLength } = source;
71
+ const result2 = new DataView(
72
+ cloneBuffer(buffer2, refs),
73
+ byteOffset2,
74
+ byteLength
75
+ );
74
76
  refs.set(source, result2);
75
77
  return result2;
76
78
  }
77
- const Ctor = source.constructor;
78
- const result = new Ctor(buffer.slice(byteOffset, byteOffset + byteLength));
79
+ const view = source;
80
+ if (!settings.preserveBufferSharing) {
81
+ const Ctor2 = view.constructor;
82
+ const result2 = new Ctor2(view);
83
+ refs.set(source, result2);
84
+ return result2;
85
+ }
86
+ const Ctor = view.constructor;
87
+ const { buffer, byteOffset, length } = view;
88
+ const result = new Ctor(cloneBuffer(buffer, refs), byteOffset, length);
79
89
  refs.set(source, result);
80
90
  return result;
81
91
  }
@@ -111,20 +121,30 @@ function clone(source, options, refs) {
111
121
  refs.set(source, source);
112
122
  return source;
113
123
  }
124
+ function cloneBuffer(buffer, refs) {
125
+ const ref = refs.get(buffer);
126
+ if (ref !== void 0) {
127
+ return ref;
128
+ }
129
+ const result = buffer.slice(0);
130
+ refs.set(buffer, result);
131
+ return result;
132
+ }
114
133
  function cloneError(source, settings, refs) {
115
134
  const result = createErrorInstance(source, settings, refs);
116
135
  refs.set(source, result);
117
136
  if (source instanceof DOMException) {
118
137
  return result;
119
138
  }
120
- if (source.stack) {
139
+ const { stack, cause } = source;
140
+ if (stack) {
121
141
  try {
122
- result.stack = source.stack;
142
+ result.stack = stack;
123
143
  } catch {
124
144
  }
125
145
  }
126
- if ("cause" in source && source.cause !== void 0) {
127
- result.cause = clone(source.cause, settings, refs);
146
+ if ("cause" in source && cause !== void 0) {
147
+ result.cause = clone(cause, settings, refs);
128
148
  }
129
149
  for (const key of Object.keys(source)) {
130
150
  Reflect.set(result, key, clone(Reflect.get(source, key), settings, refs));
@@ -202,7 +222,15 @@ function isUnsafeKey(key) {
202
222
  return typeof key === "string" && (key === "__proto__" || key === "prototype" || key === "constructor");
203
223
  }
204
224
  function resolveOptions(options) {
205
- let { preserveDescriptors = false, strictDescriptors = false } = options;
225
+ let {
226
+ preserveBufferSharing = false,
227
+ preserveDescriptors = false,
228
+ strictDescriptors = false
229
+ } = options;
230
+ if (typeof preserveBufferSharing !== "boolean") {
231
+ console.warn("Invalid preserveBufferSharing option. Fallback: false.");
232
+ preserveBufferSharing = false;
233
+ }
206
234
  if (typeof preserveDescriptors !== "boolean") {
207
235
  console.warn("Invalid preserveDescriptors option. Fallback: false.");
208
236
  preserveDescriptors = false;
@@ -211,7 +239,7 @@ function resolveOptions(options) {
211
239
  console.warn("Invalid strictDescriptors option. Fallback: false.");
212
240
  strictDescriptors = false;
213
241
  }
214
- return { preserveDescriptors, strictDescriptors };
242
+ return { preserveBufferSharing, preserveDescriptors, strictDescriptors };
215
243
  }
216
244
 
217
245
  export { bunshinClone, forEachOwnKey, isObject, isPlainObject, isUnsafeKey };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bunshin-clone",
3
- "version": "1.4.2",
3
+ "version": "1.5.0",
4
4
  "description": "High-performance deep clone utility with descriptor support",
5
5
  "keywords": [
6
6
  "array",