aboutsummaryrefslogtreecommitdiff
path: root/ext/mixed/js
diff options
context:
space:
mode:
authortoasted-nutbread <toasted-nutbread@users.noreply.github.com>2020-06-28 12:38:34 -0400
committerGitHub <noreply@github.com>2020-06-28 12:38:34 -0400
commitcdf191336aa616a206b977ba3beeb1233cf41c32 (patch)
tree07df9e5eec80dd4379c7ed97854a2bd9ef5149eb /ext/mixed/js
parent5bf805755a33f6f10fd9621f8a2bff7ba1cb7440 (diff)
Clone function (#624)
* Add clone function * Replace utilIsolate with clone * Replace JsonSchema.isolate with clone function * Include core.js for tests which use json-schema.js * Update visisted set
Diffstat (limited to 'ext/mixed/js')
-rw-r--r--ext/mixed/js/core.js67
1 files changed, 67 insertions, 0 deletions
diff --git a/ext/mixed/js/core.js b/ext/mixed/js/core.js
index 21b7bf5e..9b3ea3e2 100644
--- a/ext/mixed/js/core.js
+++ b/ext/mixed/js/core.js
@@ -157,6 +157,73 @@ function getSetDifference(set1, set2) {
);
}
+const clone = (() => {
+ // eslint-disable-next-line no-shadow
+ function clone(value) {
+ if (value === null) { return null; }
+ switch (typeof value) {
+ case 'boolean':
+ case 'number':
+ case 'string':
+ case 'bigint':
+ case 'symbol':
+ case 'undefined':
+ return value;
+ default:
+ return cloneInternal(value, new Set());
+ }
+ }
+
+ function cloneInternal(value, visited) {
+ if (value === null) { return null; }
+ switch (typeof value) {
+ case 'boolean':
+ case 'number':
+ case 'string':
+ case 'bigint':
+ case 'symbol':
+ case 'undefined':
+ return value;
+ case 'function':
+ return cloneObject(value, visited);
+ case 'object':
+ return Array.isArray(value) ? cloneArray(value, visited) : cloneObject(value, visited);
+ }
+ }
+
+ function cloneArray(value, visited) {
+ if (visited.has(value)) { throw new Error('Circular'); }
+ try {
+ visited.add(value);
+ const result = [];
+ for (const item of value) {
+ result.push(cloneInternal(item, visited));
+ }
+ return result;
+ } finally {
+ visited.delete(value);
+ }
+ }
+
+ function cloneObject(value, visited) {
+ if (visited.has(value)) { throw new Error('Circular'); }
+ try {
+ visited.add(value);
+ const result = {};
+ for (const key in value) {
+ if (Object.prototype.hasOwnProperty.call(value, key)) {
+ result[key] = cloneInternal(value[key], visited);
+ }
+ }
+ return result;
+ } finally {
+ visited.delete(value);
+ }
+ }
+
+ return clone;
+})();
+
/*
* Async utilities