var baseCopy = require('./baseCopy'),
    getSymbols = require('./getSymbols'),
    isNative = require('../lang/isNative'),
    keys = require('../object/keys');

/** Native method references. */
var preventExtensions = isNative(preventExtensions = Object.preventExtensions) && preventExtensions;

/** Used as `baseAssign`. */
var nativeAssign = (function() {
  // Avoid `Object.assign` in Firefox 34-37 which have an early implementation
  // with a now defunct try/catch behavior. See https://bugzilla.mozilla.org/show_bug.cgi?id=1103344
  // for more details.
  //
  // Use `Object.preventExtensions` on a plain object instead of simply using
  // `Object('x')` because Chrome and IE fail to throw an error when attempting
  // to assign values to readonly indexes of strings.
  var func = preventExtensions && isNative(func = Object.assign) && func;
  try {
    if (func) {
      var object = preventExtensions({ '1': 0 });
      object[0] = 1;
    }
  } catch(e) {
    // Only attempt in strict mode.
    try { func(object, 'xo'); } catch(e) {}
    return !object[1] && func;
  }
  return false;
}());

/**
 * The base implementation of `_.assign` without support for argument juggling,
 * multiple sources, and `customizer` functions.
 *
 * @private
 * @param {Object} object The destination object.
 * @param {Object} source The source object.
 * @returns {Object} Returns `object`.
 */
var baseAssign = nativeAssign || function(object, source) {
  return source == null
    ? object
    : baseCopy(source, getSymbols(source), baseCopy(source, keys(source), object));
};

module.exports = baseAssign;
