<commit_before>import {default as isObject} from "./isObject";

/**
    @function assign
    @desc A deeply recursive version of `Object.assign`.
    @param {...Object} objects
    @example <caption>this</caption>
assign({id: "foo", deep: {group: "A"}}, {id: "bar", deep: {value: 20}}));
    @example <caption>returns this</caption>
{id: "bar", deep: {group: "A", value: 20}}
*/
function assign(...objects) {

  const target = objects[0];
  for (let i = 1; i < objects.length; i++) {

    const source = objects[i];

    Object.keys(source).forEach(prop => {

      const value = source[prop];

      if (isObject(value) && (typeof window === undefined || value !== window)) {
        if (target.hasOwnProperty(prop) && isObject(target[prop])) target[prop] = assign({}, target[prop], value);
        else target[prop] = assign({}, value);
      }
      else if (Array.isArray(value)) {

        if (target.hasOwnProperty(prop) && Array.isArray(target[prop])) {

          const targetArray = target[prop];

          value.forEach((sourceItem, itemIndex) => {

            if (itemIndex < targetArray.length) {
              const targetItem = targetArray[itemIndex];

              if (Object.is(targetItem, sourceItem)) return;

              if (isObject(targetItem) && isObject(sourceItem) || Array.isArray(targetItem) && Array.isArray(sourceItem)) {
                targetArray[itemIndex] = assign({}, targetItem, sourceItem);
              }<commit_msg>adds more robust window and document detection to assign<commit_after>import {default as isObject} from "./isObject";

/**
    @function assign
    @desc Determines if the object passed is the document or window.
    @param {Object} obj
    @private
*/
function validObject(obj) {
  if (typeof window === "undefined") return true;
  else return obj !== window && obj !== document;
}

/**
    @function assign
    @desc A deeply recursive version of `Object.assign`.
    @param {...Object} objects
    @example <caption>this</caption>
assign({id: "foo", deep: {group: "A"}}, {id: "bar", deep: {value: 20}}));
    @example <caption>returns this</caption>
{id: "bar", deep: {group: "A", value: 20}}
*/
function assign(...objects) {

  const target = objects[0];
  for (let i = 1; i < objects.length; i++) {

    const source = objects[i];

    Object.keys(source).forEach(prop => {

      const value = source[prop];

      if (isObject(value) && validObject(value)) {
        if (target.hasOwnProperty(prop) && isObject(target[prop])) target[prop] = assign({}, target[prop], value);
        else target[prop] = assign({}, value);
      }
      else if (Array.isArray(value)) {

        if (target.hasOwnProperty(prop) && Array.isArray(target[prop])) {

          const targetArray = target[prop];

          value.forEach((sourceItem, itemIndex) => {

            if (itemIndex < targetArray.length) {
              const targetItem = targetArray[itemIndex];

              if (Object.is(targetItem, sourceItem)) return;

              if (isObject(targetItem) && isObject(sourceItem) || Array.isArray(targetItem) && Array.isArray(sourceItem)) {
                targetArray[itemIndex] = assign({}, targetItem, sourceItem);
              }
{'fraction_non_alphanumeric': 0.1599374021909233, 'fraction_numerical': 0.003755868544600939, 'mean_word_length': 3.0404551201011376, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3545763', 'n_tokens_mistral': 945, 'n_tokens_neox': 918, 'n_words': 249}