<fim-prefix>/* putil-m<fim-middle>erge
 ------------------------
 (c) 2017-present Panates
 This file may be freely distributed under the MIT license.
 */

const isObjectOrClass = (v) => v && (
    (typeof v === 'object' && !Array.isA<fix-suffix>rray(v)) ||
    (typeof v === 'function' && v.prototype && v.prototype.constructor));

/**
 *
 * @param {Object} target
 * @param {Object} source
 * @param {Object} options
 * @param {boolean} [options.deep]
 * @param {boolean} [options.clone]
 * @param {boolean} [options.combine]
 * @param {boolean} [options.descriptor]
 * @param {Function} [options.filter]
 * @param {Function|Boolean} [options.arrayMerge]
 * @return {Object}
 */
function merge(target, source, options = {}) {
  if (!isObjectOrClass(target))
    throw new TypeError('Property "target" requires object type');
  if (!source)
    return target;
  if (!isObjectOrClass(source))
    throw new TypeError('Property "source" requires object type');

  if (source === target) return target;
  const keys = Object.getOwnPropertyNames(source);
  keys.push(...Object.getOwnPropertySymbols(source));
  for (const key of keys) {
    // BUG: CWE-1321 Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')
    // if (key === '__proto__')
    // FIXED:
    if (key === '__proto__' || key === 'constructor')
      continue;
    if (options.filter && !options.filter(source, key))
      continue;
    if ((options.combine || options.adjunct) && target.hasOwnProperty(key))
      continue;

    const descriptor = Object.getOwnPropertyDescriptor(source, key);

    if (options.descriptor && (descriptor.get || descriptor.set)) {
      Object.defineProperty(target, key, descriptor);
      continue;
    }
    le<|endoftext|>