<commit_before>import { Ref, unref, ref, computed, onBeforeUnmount } from 'vue';
import { isNullOrUndefined } from '../../shared';
import { FormContextKey } from './symbols';
import { FieldArrayContext, FieldEntry, MaybeRef } from './types';
import { getFromPath, injectWithSelf, warn } from './utils';

let FIELD_ARRAY_COUNTER = 0;
export function useFieldArray<TValue = unknown>(arrayPath: MaybeRef<string>): FieldArrayContext<TValue> {
  const id = FIELD_ARRAY_COUNTER++;
  const form = injectWithSelf(FormContextKey, undefined);
  const fields: Ref<FieldEntry<TValue>[]> = ref([]);

  // eslint-disable-next-line @typescript-eslint/no-empty-function
  const noOp = () => {};
  const noOpApi: FieldArrayContext<TValue> = {
    fields,
    remove: noOp,
    push: noOp,
    swap: noOp,
    insert: noOp,
    update: noOp,
    replace: noOp,
    prepend: noOp,
    move: noOp,
  };

  if (!form) {
    warn(
      'FieldArray requires being a child of `<Form/>` or `useForm` being called before it. Array fields may not work correctly'
    );

    return noOpApi;
  }

  if (!unref(arrayPath)) {
    warn('FieldArray requires a field path to be provided, did you forget to pass the `name` prop?');

    return noOpApi;
  }

  let entryCounter = 0;
  function initFields() {
    const currentValues = getFromPath<TValue[]>(form?.values, unref(arrayPath), []);
    fields.value = currentValues.map(createEntry);
    updateEntryFlags();
  }

  initFields();

  function updateEntryFlags() {
    const fieldsLength = fields.value.length;
    for (let i = 0; i < fieldsLength; i++) {
      const entry = fields.value[i];
      entry.isFirst = i === 0;
      entry.isLast = i === fieldsLength - 1;
    }
  }

  function createEntry(value: TValue): FieldEntry<TValue> {
    const key = entryCounter++;

    const entry: FieldEntry<TValue> = {
      key,
      value: computed<TValue>({
        get() {
          const currentValues = getFromPath<TValue[]>(form?.values, unref(arrayPath), []);
          const idx = fields.value.findIndex(e => e.key === key);

          return idx === -1 ? value : currentValues[idx];
        },
        set(value: TValue) {
          const idx = fields.value.findIndex(e => e.key === key);
          if (idx === -1) {
            warn(`Attempting to update a non-existent array item`);
            return;
          }

          update(idx, value);
        },<commit_msg>fix: added existing undefined path fallback closes #3801<commit_after>import { Ref, unref, ref, computed, onBeforeUnmount } from 'vue';
import { isNullOrUndefined } from '../../shared';
import { FormContextKey } from './symbols';
import { FieldArrayContext, FieldEntry, MaybeRef } from './types';
import { getFromPath, injectWithSelf, warn } from './utils';

let FIELD_ARRAY_COUNTER = 0;
export function useFieldArray<TValue = unknown>(arrayPath: MaybeRef<string>): FieldArrayContext<TValue> {
  const id = FIELD_ARRAY_COUNTER++;
  const form = injectWithSelf(FormContextKey, undefined);
  const fields: Ref<FieldEntry<TValue>[]> = ref([]);

  // eslint-disable-next-line @typescript-eslint/no-empty-function
  const noOp = () => {};
  const noOpApi: FieldArrayContext<TValue> = {
    fields,
    remove: noOp,
    push: noOp,
    swap: noOp,
    insert: noOp,
    update: noOp,
    replace: noOp,
    prepend: noOp,
    move: noOp,
  };

  if (!form) {
    warn(
      'FieldArray requires being a child of `<Form/>` or `useForm` being called before it. Array fields may not work correctly'
    );

    return noOpApi;
  }

  if (!unref(arrayPath)) {
    warn('FieldArray requires a field path to be provided, did you forget to pass the `name` prop?');

    return noOpApi;
  }

  let entryCounter = 0;
  function initFields() {
    const currentValues = getFromPath<TValue[]>(form?.values, unref(arrayPath), []) || [];
    fields.value = currentValues.map(createEntry);
    updateEntryFlags();
  }

  initFields();

  function updateEntryFlags() {
    const fieldsLength = fields.value.length;
    for (let i = 0; i < fieldsLength; i++) {
      const entry = fields.value[i];
      entry.isFirst = i === 0;
      entry.isLast = i === fieldsLength - 1;
    }
  }

  function createEntry(value: TValue): FieldEntry<TValue> {
    const key = entryCounter++;

    const entry: FieldEntry<TValue> = {
      key,
      value: computed<TValue>({
        get() {
          const currentValues = getFromPath<TValue[]>(form?.values, unref(arrayPath), []) || [];
          const idx = fields.value.findIndex(e => e.key === key);

          return idx === -1 ? value : currentValues[idx];
        },
        set(value: TValue) {
          const idx = fields.value.findIndex(e => e.key === key);
          if (idx === -1) {
            warn(`Attempting to update a non-existent array item`);
            return;
          }

          update(idx, value);
        },
{'fraction_non_alphanumeric': 0.13929528126931795, 'fraction_numerical': 0.00370904595095817, 'mean_word_length': 2.946341463414634, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 33, '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': '2355426', 'n_tokens_mistral': 1529, 'n_tokens_neox': 1491, 'n_words': 405}