summaryrefslogtreecommitdiff
path: root/runtime/js/01_web_util.js
diff options
context:
space:
mode:
authorElad Keyshawn <elad.kishon@msmail.ariel.ac.il>2021-06-05 16:57:51 +0300
committerGitHub <noreply@github.com>2021-06-05 15:57:51 +0200
commit4b3d55b449dd703aaa693410f0d37a2308bb0fd6 (patch)
treee02d507946120e0fb9670d34194456f03d485871 /runtime/js/01_web_util.js
parent1d070f3d47f456099a46462d5d79175c26e3c21d (diff)
webutil: replace cloneValue impl with serialize/deserialize (#10215)
Co-authored-by: Bartek IwaƄczuk <biwanczuk@gmail.com>
Diffstat (limited to 'runtime/js/01_web_util.js')
-rw-r--r--runtime/js/01_web_util.js114
1 files changed, 36 insertions, 78 deletions
diff --git a/runtime/js/01_web_util.js b/runtime/js/01_web_util.js
index ea8ea4873..5960691eb 100644
--- a/runtime/js/01_web_util.js
+++ b/runtime/js/01_web_util.js
@@ -35,86 +35,44 @@
/** Clone a value in a similar way to structured cloning. It is similar to a
* StructureDeserialize(StructuredSerialize(...)). */
function cloneValue(value) {
- switch (typeof value) {
- case "number":
- case "string":
- case "boolean":
- case "undefined":
- case "bigint":
- return value;
- case "object": {
- if (objectCloneMemo.has(value)) {
- return objectCloneMemo.get(value);
- }
- if (value === null) {
- return value;
- }
- if (value instanceof Date) {
- return new Date(value.valueOf());
- }
- if (value instanceof RegExp) {
- return new RegExp(value);
- }
- if (value instanceof SharedArrayBuffer) {
- return value;
- }
- 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;
- }
+ // Performance optimization for buffers, otherwise
+ // `serialize/deserialize` will allocate new buffer.
+ 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,
+ );
+ }
- // 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;
+ try {
+ return Deno.core.deserialize(Deno.core.serialize(value));
+ } catch (e) {
+ if (e instanceof TypeError) {
+ throw new DOMException("Uncloneable value", "DataCloneError");
}
- case "symbol":
- case "function":
- default:
- throw new DOMException("Uncloneable value in stream", "DataCloneError");
+ throw e;
}
}