55 lines
1.2 KiB
JavaScript
55 lines
1.2 KiB
JavaScript
|
'use strict';
|
||
|
|
||
|
const Reach = require('./reach');
|
||
|
|
||
|
|
||
|
const internals = {};
|
||
|
|
||
|
|
||
|
exports.keys = function (obj, options = {}) {
|
||
|
|
||
|
return options.symbols !== false ? Reflect.ownKeys(obj) : Object.getOwnPropertyNames(obj); // Defaults to true
|
||
|
};
|
||
|
|
||
|
|
||
|
exports.store = function (source, keys) {
|
||
|
|
||
|
const storage = new Map();
|
||
|
for (let i = 0; i < keys.length; ++i) {
|
||
|
const key = keys[i];
|
||
|
const value = Reach(source, key);
|
||
|
if (typeof value === 'object' ||
|
||
|
typeof value === 'function') {
|
||
|
|
||
|
storage.set(key, value);
|
||
|
internals.reachSet(source, key, undefined);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return storage;
|
||
|
};
|
||
|
|
||
|
|
||
|
exports.restore = function (copy, source, storage) {
|
||
|
|
||
|
for (const [key, value] of storage) {
|
||
|
internals.reachSet(copy, key, value);
|
||
|
internals.reachSet(source, key, value);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
internals.reachSet = function (obj, key, value) {
|
||
|
|
||
|
const path = Array.isArray(key) ? key : key.split('.');
|
||
|
let ref = obj;
|
||
|
for (let i = 0; i < path.length; ++i) {
|
||
|
const segment = path[i];
|
||
|
if (i + 1 === path.length) {
|
||
|
ref[segment] = value;
|
||
|
}
|
||
|
|
||
|
ref = ref[segment];
|
||
|
}
|
||
|
};
|