1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-24 08:09:08 -05:00

webutil: replace cloneValue impl with serialize/deserialize (#10215)

Co-authored-by: Bartek Iwańczuk <biwanczuk@gmail.com>
This commit is contained in:
Elad Keyshawn 2021-06-05 16:57:51 +03:00 committed by GitHub
parent 1d070f3d47
commit 4b3d55b449
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -35,86 +35,44 @@
/** Clone a value in a similar way to structured cloning. It is similar to a /** Clone a value in a similar way to structured cloning. It is similar to a
* StructureDeserialize(StructuredSerialize(...)). */ * StructureDeserialize(StructuredSerialize(...)). */
function cloneValue(value) { function cloneValue(value) {
switch (typeof value) { // Performance optimization for buffers, otherwise
case "number": // `serialize/deserialize` will allocate new buffer.
case "string": if (value instanceof ArrayBuffer) {
case "boolean": const cloned = cloneArrayBuffer(
case "undefined": value,
case "bigint": 0,
return value; value.byteLength,
case "object": { ArrayBuffer,
if (objectCloneMemo.has(value)) { );
return objectCloneMemo.get(value); objectCloneMemo.set(value, cloned);
} return cloned;
if (value === null) { }
return value; if (ArrayBuffer.isView(value)) {
} const clonedBuffer = cloneValue(value.buffer);
if (value instanceof Date) { // Use DataViewConstructor type purely for type-checking, can be a
return new Date(value.valueOf()); // DataView or TypedArray. They use the same constructor signature,
} // only DataView has a length in bytes and TypedArrays use a length in
if (value instanceof RegExp) { // terms of elements, so we adjust for that.
return new RegExp(value); let length;
} if (value instanceof DataView) {
if (value instanceof SharedArrayBuffer) { length = value.byteLength;
return value; } else {
} length = value.length;
if (value instanceof ArrayBuffer) {
const cloned = cloneArrayBuffer(
value,
0,
value.byteLength,
ArrayBuffer,
);
objectCloneMemo.set(value, cloned);
return cloned;
}
if (ArrayBuffer.isView(value)) {
const clonedBuffer = cloneValue(value.buffer);
// Use DataViewConstructor type purely for type-checking, can be a
// DataView or TypedArray. They use the same constructor signature,
// only DataView has a length in bytes and TypedArrays use a length in
// terms of elements, so we adjust for that.
let length;
if (value instanceof DataView) {
length = value.byteLength;
} else {
length = value.length;
}
return new (value.constructor)(
clonedBuffer,
value.byteOffset,
length,
);
}
if (value instanceof Map) {
const clonedMap = new Map();
objectCloneMemo.set(value, clonedMap);
value.forEach((v, k) => {
clonedMap.set(cloneValue(k), cloneValue(v));
});
return clonedMap;
}
if (value instanceof Set) {
// assumes that cloneValue still takes only one argument
const clonedSet = new Set([...value].map(cloneValue));
objectCloneMemo.set(value, clonedSet);
return clonedSet;
}
// default for objects
const clonedObj = {};
objectCloneMemo.set(value, clonedObj);
const sourceKeys = Object.getOwnPropertyNames(value);
for (const key of sourceKeys) {
clonedObj[key] = cloneValue(value[key]);
}
Reflect.setPrototypeOf(clonedObj, Reflect.getPrototypeOf(value));
return clonedObj;
} }
case "symbol": return new (value.constructor)(
case "function": clonedBuffer,
default: value.byteOffset,
throw new DOMException("Uncloneable value in stream", "DataCloneError"); length,
);
}
try {
return Deno.core.deserialize(Deno.core.serialize(value));
} catch (e) {
if (e instanceof TypeError) {
throw new DOMException("Uncloneable value", "DataCloneError");
}
throw e;
} }
} }