diff options
author | Elad Keyshawn <elad.kishon@msmail.ariel.ac.il> | 2021-06-05 16:57:51 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-06-05 15:57:51 +0200 |
commit | 4b3d55b449dd703aaa693410f0d37a2308bb0fd6 (patch) | |
tree | e02d507946120e0fb9670d34194456f03d485871 /runtime/js/01_web_util.js | |
parent | 1d070f3d47f456099a46462d5d79175c26e3c21d (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.js | 114 |
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; } } |