2023-04-22 16:44:26 -05:00
|
|
|
function deep_copy(from) {
|
|
|
|
if (typeof from !== 'object')
|
|
|
|
return from;
|
|
|
|
|
|
|
|
if (Array.isArray(from)) {
|
|
|
|
var c = [];
|
|
|
|
from.forEach(function(x,i) { c[i] = deep_copy(x); });
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
var obj = {};
|
|
|
|
for (var key in from)
|
|
|
|
obj[key] = deep_copy(from[key]);
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
var walk_up_get_prop = function(obj, prop, endobj) {
|
|
|
|
var props = [];
|
|
|
|
var cur = obj;
|
|
|
|
while (cur !== Object.prototype) {
|
|
|
|
if (cur.hasOwn(prop))
|
|
|
|
props.push(cur[prop]);
|
|
|
|
|
|
|
|
cur = cur.__proto__;
|
|
|
|
}
|
|
|
|
|
|
|
|
return props;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Deeply remove source keys from target, not removing objects */
|
|
|
|
function unmerge(target, source) {
|
|
|
|
for (var key in source) {
|
|
|
|
if (typeof source[key] === 'object' && !Array.isArray(source[key]))
|
|
|
|
unmerge(target[key], source[key]);
|
|
|
|
else
|
|
|
|
delete target[key];
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Deeply merge two objects, not clobbering objects on target with objects on source */
|
|
|
|
function deep_merge(target, source)
|
|
|
|
{
|
2023-04-28 12:49:18 -05:00
|
|
|
Log.warn("Doing a deep merge ...");
|
2023-04-22 16:44:26 -05:00
|
|
|
for (var key in source) {
|
2023-04-28 12:49:18 -05:00
|
|
|
if (typeof source[key] === 'object' && !Array.isArray(source[key])) {
|
2023-04-29 10:07:58 -05:00
|
|
|
Log.warn(`Deeper merge on ${key}`);
|
2023-04-22 16:44:26 -05:00
|
|
|
deep_merge(target[key], source[key]);
|
2023-04-28 12:49:18 -05:00
|
|
|
}
|
|
|
|
else {
|
2023-04-29 10:07:58 -05:00
|
|
|
Log.warn(`Setting key ${key}`);
|
2023-04-22 16:44:26 -05:00
|
|
|
target[key] = source[key];
|
2023-04-28 12:49:18 -05:00
|
|
|
}
|
2023-04-22 16:44:26 -05:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
function equal(x,y) {
|
|
|
|
if (typeof x === 'object')
|
|
|
|
for (var key in x)
|
|
|
|
return equal(x[key],y[key]);
|
|
|
|
|
|
|
|
return x === y;
|
|
|
|
};
|
|
|
|
|
|
|
|
function diffassign(target, from) {
|
|
|
|
if (from.empty) return;
|
|
|
|
|
|
|
|
for (var e in from) {
|
|
|
|
if (typeof from[e] === 'object') {
|
|
|
|
if (!target.hasOwnProperty(e))
|
|
|
|
target[e] = from[e];
|
|
|
|
else
|
|
|
|
diffassign(target[e], from[e]);
|
|
|
|
} else {
|
|
|
|
if (from[e] === "DELETE") {
|
|
|
|
delete target[e];
|
|
|
|
} else {
|
|
|
|
target[e] = from[e];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2023-10-05 17:30:17 -05:00
|
|
|
function ediff(from,to)
|
2023-10-02 17:03:01 -05:00
|
|
|
{
|
2023-10-05 17:30:17 -05:00
|
|
|
var ret = {};
|
|
|
|
|
2023-10-09 18:10:10 -05:00
|
|
|
if (!to)
|
|
|
|
return ediff(from,{});
|
|
|
|
|
2023-10-05 17:30:17 -05:00
|
|
|
Object.entries(from).forEach(function([key,v]) {
|
|
|
|
if (typeof v === 'function') return;
|
|
|
|
if (typeof v === 'undefined') return;
|
2023-10-05 08:02:12 -05:00
|
|
|
|
2023-10-05 17:30:17 -05:00
|
|
|
if (Array.isArray(v)) {
|
|
|
|
if (!Array.isArray(to[key]) || v.length !== to[key].length)
|
|
|
|
ret[key] = Object.values(ediff(v, []));
|
2023-10-05 08:02:12 -05:00
|
|
|
|
2023-10-05 17:30:17 -05:00
|
|
|
var diff = ediff(from[key], to[key]);
|
|
|
|
if (diff && !diff.empty)
|
|
|
|
ret[key] = Object.values(ediff(v,[]));
|
2023-10-05 08:02:12 -05:00
|
|
|
|
2023-10-05 17:30:17 -05:00
|
|
|
return;
|
2023-10-05 08:02:12 -05:00
|
|
|
}
|
|
|
|
|
2023-10-05 17:30:17 -05:00
|
|
|
if (typeof v === 'object') {
|
|
|
|
var diff = ediff(v, to[key]);
|
|
|
|
if (diff && !diff.empty)
|
|
|
|
ret[key] = diff;
|
|
|
|
return;
|
|
|
|
}
|
2023-04-22 16:44:26 -05:00
|
|
|
|
2023-10-05 17:30:17 -05:00
|
|
|
if (typeof v === 'number') {
|
|
|
|
var a = Number.prec(v);
|
|
|
|
if (!to || a !== to[key])
|
|
|
|
ret[key] = a;
|
|
|
|
return;
|
2023-04-22 16:44:26 -05:00
|
|
|
}
|
|
|
|
|
2023-10-05 17:30:17 -05:00
|
|
|
if (!to || v !== to[key])
|
|
|
|
ret[key] = v;
|
|
|
|
});
|
2023-10-10 17:37:58 -05:00
|
|
|
if (ret.empty) return undefined;
|
2023-10-05 17:30:17 -05:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|