aboutsummaryrefslogtreecommitdiff
path: root/node_modules/merge-options/index.js
diff options
context:
space:
mode:
authorruki <waruqi@gmail.com>2018-11-08 00:38:48 +0800
committerruki <waruqi@gmail.com>2018-11-07 21:53:09 +0800
commit26105034da4fcce7ac883c899d781f016559310d (patch)
treec459a5dc4e3aa0972d9919033ece511ce76dd129 /node_modules/merge-options/index.js
parent2c77f00f1a7ecb6c8192f9c16d3b2001b254a107 (diff)
downloadxmake-docs-26105034da4fcce7ac883c899d781f016559310d.tar.gz
xmake-docs-26105034da4fcce7ac883c899d781f016559310d.zip
switch to vuepress
Diffstat (limited to 'node_modules/merge-options/index.js')
-rw-r--r--node_modules/merge-options/index.js163
1 files changed, 163 insertions, 0 deletions
diff --git a/node_modules/merge-options/index.js b/node_modules/merge-options/index.js
new file mode 100644
index 00000000..8eb954de
--- /dev/null
+++ b/node_modules/merge-options/index.js
@@ -0,0 +1,163 @@
+'use strict';
+const isOptionObject = require('is-plain-obj');
+
+const hasOwnProperty = Object.prototype.hasOwnProperty;
+const propIsEnumerable = Object.propertyIsEnumerable;
+const defineProperty = (obj, name, value) => Object.defineProperty(obj, name, {
+ value,
+ writable: true,
+ enumerable: true,
+ configurable: true
+});
+
+const globalThis = this;
+const defaultMergeOpts = {
+ concatArrays: false
+};
+
+const getEnumerableOwnPropertyKeys = value => {
+ const keys = [];
+
+ for (const key in value) {
+ if (hasOwnProperty.call(value, key)) {
+ keys.push(key);
+ }
+ }
+
+ /* istanbul ignore else */
+ if (Object.getOwnPropertySymbols) {
+ const symbols = Object.getOwnPropertySymbols(value);
+
+ for (let i = 0; i < symbols.length; i++) {
+ if (propIsEnumerable.call(value, symbols[i])) {
+ keys.push(symbols[i]);
+ }
+ }
+ }
+
+ return keys;
+};
+
+function clone(value) {
+ if (Array.isArray(value)) {
+ return cloneArray(value);
+ }
+
+ if (isOptionObject(value)) {
+ return cloneOptionObject(value);
+ }
+
+ return value;
+}
+
+function cloneArray(array) {
+ const result = array.slice(0, 0);
+
+ getEnumerableOwnPropertyKeys(array).forEach(key => {
+ defineProperty(result, key, clone(array[key]));
+ });
+
+ return result;
+}
+
+function cloneOptionObject(obj) {
+ const result = Object.getPrototypeOf(obj) === null ? Object.create(null) : {};
+
+ getEnumerableOwnPropertyKeys(obj).forEach(key => {
+ defineProperty(result, key, clone(obj[key]));
+ });
+
+ return result;
+}
+
+/**
+ * @param merged {already cloned}
+ * @return {cloned Object}
+ */
+const mergeKeys = (merged, source, keys, mergeOpts) => {
+ keys.forEach(key => {
+ // Do not recurse into prototype chain of merged
+ if (key in merged && merged[key] !== Object.getPrototypeOf(merged)) {
+ defineProperty(merged, key, merge(merged[key], source[key], mergeOpts));
+ } else {
+ defineProperty(merged, key, clone(source[key]));
+ }
+ });
+
+ return merged;
+};
+
+/**
+ * @param merged {already cloned}
+ * @return {cloned Object}
+ *
+ * see [Array.prototype.concat ( ...arguments )](http://www.ecma-international.org/ecma-262/6.0/#sec-array.prototype.concat)
+ */
+const concatArrays = (merged, source, mergeOpts) => {
+ let result = merged.slice(0, 0);
+ let resultIndex = 0;
+
+ [merged, source].forEach(array => {
+ const indices = [];
+
+ // `result.concat(array)` with cloning
+ for (let k = 0; k < array.length; k++) {
+ if (!hasOwnProperty.call(array, k)) {
+ continue;
+ }
+
+ indices.push(String(k));
+
+ if (array === merged) {
+ // Already cloned
+ defineProperty(result, resultIndex++, array[k]);
+ } else {
+ defineProperty(result, resultIndex++, clone(array[k]));
+ }
+ }
+
+ // Merge non-index keys
+ result = mergeKeys(result, array, getEnumerableOwnPropertyKeys(array).filter(key => {
+ return indices.indexOf(key) === -1;
+ }), mergeOpts);
+ });
+
+ return result;
+};
+
+/**
+ * @param merged {already cloned}
+ * @return {cloned Object}
+ */
+function merge(merged, source, mergeOpts) {
+ if (mergeOpts.concatArrays && Array.isArray(merged) && Array.isArray(source)) {
+ return concatArrays(merged, source, mergeOpts);
+ }
+
+ if (!isOptionObject(source) || !isOptionObject(merged)) {
+ return clone(source);
+ }
+
+ return mergeKeys(merged, source, getEnumerableOwnPropertyKeys(source), mergeOpts);
+}
+
+module.exports = function () {
+ const mergeOpts = merge(clone(defaultMergeOpts), (this !== globalThis && this) || {}, defaultMergeOpts);
+ let merged = {foobar: {}};
+
+ for (let i = 0; i < arguments.length; i++) {
+ const option = arguments[i];
+
+ if (option === undefined) {
+ continue;
+ }
+
+ if (!isOptionObject(option)) {
+ throw new TypeError('`' + option + '` is not an Option Object');
+ }
+
+ merged = merge(merged, {foobar: option}, mergeOpts);
+ }
+
+ return merged.foobar;
+};